From ede6e7f9a1f68661e2602f9cb2697e4d93c19e7c Mon Sep 17 00:00:00 2001 From: Gagandeep Singh Date: Thu, 27 Feb 2025 19:29:23 +0530 Subject: [PATCH] WIP --- integration_tests/array_expr_05.py | 12 +- integration_tests/bindc_02.py | 10 +- src/bin/lpython.cpp | 16 +- src/libasr/ASR.asdl | 55 +- src/libasr/CMakeLists.txt | 15 +- src/libasr/asdl.py | 2 +- src/libasr/asdl_cpp.py | 533 +- src/libasr/asr_base_visitor.h | 551 + src/libasr/asr_builder.h | 1079 +- src/libasr/asr_deserialization_visitor.h | 4688 ++++++++ src/libasr/asr_expr_base_replacer_visitor.h | 2643 +++++ src/libasr/asr_expr_call_replacer_visitor.h | 3878 +++++++ src/libasr/asr_expr_stmt_duplicator_visitor.h | 2444 ++++ src/libasr/asr_expr_type_visitor.h | 159 + src/libasr/asr_expr_value_visitor.h | 154 + src/libasr/asr_json_visitor.h | 7794 +++++++++++++ src/libasr/asr_lookup_name.h | 227 + src/libasr/asr_lookup_name_visitor.h | 2190 ++++ src/libasr/asr_pass_walk_visitor.h | 1481 +++ src/libasr/asr_pickle_visitor.h | 9509 ++++++++++++++++ src/libasr/asr_scopes.cpp | 3 +- src/libasr/asr_scopes.h | 9 + src/libasr/asr_serialization_visitor.h | 3568 ++++++ src/libasr/asr_stmt_base_replacer_visitor.h | 569 + src/libasr/asr_tree_visitor.h | 9905 +++++++++++++++++ src/libasr/asr_utils.cpp | 511 +- src/libasr/asr_utils.h | 1943 +++- src/libasr/asr_verify.cpp | 178 +- src/libasr/asr_walk_visitor.h | 1448 +++ src/libasr/bwriter.h | 149 + src/libasr/casting_utils.cpp | 3 +- src/libasr/codegen/KaleidoscopeJIT.h | 5 + src/libasr/codegen/asr_to_c.cpp | 100 +- src/libasr/codegen/asr_to_c_cpp.h | 56 +- src/libasr/codegen/asr_to_cpp.cpp | 62 +- src/libasr/codegen/asr_to_fortran.cpp | 512 +- src/libasr/codegen/asr_to_julia.cpp | 53 +- src/libasr/codegen/asr_to_llvm.cpp | 3589 +++--- src/libasr/codegen/asr_to_mlir.cpp | 911 ++ src/libasr/codegen/asr_to_mlir.h | 15 + src/libasr/codegen/asr_to_py.cpp | 6 +- src/libasr/codegen/asr_to_python.cpp | 144 +- src/libasr/codegen/asr_to_wasm.cpp | 362 +- src/libasr/codegen/asr_to_x86.cpp | 12 +- src/libasr/codegen/c_utils.h | 28 +- src/libasr/codegen/evaluator.cpp | 113 +- src/libasr/codegen/evaluator.h | 23 +- src/libasr/codegen/llvm_array_utils.cpp | 331 +- src/libasr/codegen/llvm_array_utils.h | 38 +- src/libasr/codegen/llvm_utils.cpp | 2424 ++-- src/libasr/codegen/llvm_utils.h | 228 +- src/libasr/codegen/wasm_assembler.h | 1 + src/libasr/codegen/wasm_to_wat.cpp | 1 - src/libasr/codegen/wasm_to_x64.cpp | 1 - src/libasr/codegen/wasm_to_x86.cpp | 1 - src/libasr/compiler_tester/tester.py | 22 +- src/libasr/config.h.in | 2 + src/libasr/containers.h | 15 + src/libasr/diagnostics.cpp | 31 +- src/libasr/diagnostics.h | 12 +- src/libasr/gen_pass.py | 6 +- .../intrinsic_func_registry_util_gen.py | 498 +- src/libasr/location.h | 58 +- src/libasr/lsp.cpp | 546 + src/libasr/lsp_interface.h | 46 +- src/libasr/modfile.cpp | 154 +- src/libasr/modfile.h | 8 +- src/libasr/pass/arr_slice.cpp | 3 +- src/libasr/pass/array_op.cpp | 2671 ++--- .../pass/array_passed_in_function_call.cpp | 894 ++ src/libasr/pass/array_struct_temporary.cpp | 2651 +++++ src/libasr/pass/array_struct_temporary.h | 14 + src/libasr/pass/class_constructor.cpp | 2 - src/libasr/pass/dead_code_removal.cpp | 4 - src/libasr/pass/div_to_mul.cpp | 3 - src/libasr/pass/do_loops.cpp | 22 +- src/libasr/pass/flip_sign.cpp | 6 +- src/libasr/pass/fma.cpp | 146 +- src/libasr/pass/for_all.cpp | 6 +- .../pass/function_call_in_declaration.cpp | 211 +- src/libasr/pass/global_stmts.cpp | 90 +- src/libasr/pass/implied_do_loops.cpp | 249 +- src/libasr/pass/init_expr.cpp | 11 +- src/libasr/pass/inline_function_calls.cpp | 11 +- src/libasr/pass/insert_deallocate.cpp | 168 +- src/libasr/pass/instantiate_template.cpp | 94 +- .../pass/intrinsic_array_function_registry.h | 4229 +++++-- src/libasr/pass/intrinsic_function.cpp | 164 +- src/libasr/pass/intrinsic_function_registry.h | 310 +- src/libasr/pass/intrinsic_functions.h | 3137 ++++-- src/libasr/pass/intrinsic_subroutine.cpp | 5 +- .../pass/intrinsic_subroutine_registry.h | 62 +- src/libasr/pass/intrinsic_subroutines.h | 752 +- src/libasr/pass/loop_unroll.cpp | 3 - src/libasr/pass/loop_vectorise.cpp | 2 - src/libasr/pass/nested_vars.cpp | 227 +- src/libasr/pass/openmp.cpp | 1765 +++ src/libasr/pass/pass_array_by_data.cpp | 440 +- src/libasr/pass/pass_compare.cpp | 21 +- src/libasr/pass/pass_list_expr.cpp | 13 +- src/libasr/pass/pass_manager.h | 95 +- src/libasr/pass/pass_utils.cpp | 524 +- src/libasr/pass/pass_utils.h | 325 +- src/libasr/pass/print_arr.cpp | 289 +- src/libasr/pass/print_list_tuple.cpp | 139 +- src/libasr/pass/print_struct_type.cpp | 26 +- .../promote_allocatable_to_nonallocatable.cpp | 23 +- src/libasr/pass/python_bind.cpp | 140 +- .../replace_array_passed_in_function_call.h | 14 + src/libasr/pass/replace_openmp.h | 14 + src/libasr/pass/replace_symbolic.cpp | 264 +- .../pass/replace_with_compile_time_values.cpp | 123 + .../pass/replace_with_compile_time_values.h | 14 + src/libasr/pass/select_case.cpp | 2 +- src/libasr/pass/sign_from_value.cpp | 140 +- src/libasr/pass/subroutine_from_function.cpp | 443 +- .../transform_optional_argument_functions.cpp | 164 +- src/libasr/pass/unique_symbols.cpp | 15 +- src/libasr/pass/unused_functions.cpp | 14 + .../pass/update_array_dim_intrinsic_calls.cpp | 19 +- src/libasr/pass/where.cpp | 325 +- src/libasr/pass/while_else.cpp | 4 +- src/libasr/pass/while_else.h | 1 - src/libasr/pickle.cpp | 76 + src/libasr/runtime/lfortran_intrinsics.c | 2512 +++-- src/libasr/runtime/lfortran_intrinsics.h | 43 +- src/libasr/semantic_exception.h | 14 - src/libasr/serialization.cpp | 20 +- src/libasr/serialization.h | 4 +- src/libasr/stacktrace.cpp | 93 +- src/libasr/stacktrace.h | 2 + src/libasr/string_utils.cpp | 52 +- src/libasr/string_utils.h | 8 +- src/libasr/utils.h | 14 + src/libasr/utils2.cpp | 3 + src/libasr/wasm_instructions_visitor.py | 10 +- src/lpython/python_evaluator.cpp | 4 +- src/lpython/python_serialization.cpp | 2 +- src/lpython/semantics/python_ast_to_asr.cpp | 363 +- src/lpython/semantics/python_ast_to_asr.h | 2 +- src/lpython/semantics/python_comptime_eval.h | 12 +- src/lpython/semantics/python_intrinsic_eval.h | 38 +- src/runtime/lpython_builtin.py | 23 +- 143 files changed, 79029 insertions(+), 11909 deletions(-) create mode 100644 src/libasr/asr_base_visitor.h create mode 100644 src/libasr/asr_deserialization_visitor.h create mode 100644 src/libasr/asr_expr_base_replacer_visitor.h create mode 100644 src/libasr/asr_expr_call_replacer_visitor.h create mode 100644 src/libasr/asr_expr_stmt_duplicator_visitor.h create mode 100644 src/libasr/asr_expr_type_visitor.h create mode 100644 src/libasr/asr_expr_value_visitor.h create mode 100644 src/libasr/asr_json_visitor.h create mode 100644 src/libasr/asr_lookup_name.h create mode 100644 src/libasr/asr_lookup_name_visitor.h create mode 100644 src/libasr/asr_pass_walk_visitor.h create mode 100644 src/libasr/asr_pickle_visitor.h create mode 100644 src/libasr/asr_serialization_visitor.h create mode 100644 src/libasr/asr_stmt_base_replacer_visitor.h create mode 100644 src/libasr/asr_tree_visitor.h create mode 100644 src/libasr/asr_walk_visitor.h create mode 100644 src/libasr/codegen/asr_to_mlir.cpp create mode 100644 src/libasr/codegen/asr_to_mlir.h create mode 100644 src/libasr/lsp.cpp create mode 100644 src/libasr/pass/array_passed_in_function_call.cpp create mode 100644 src/libasr/pass/array_struct_temporary.cpp create mode 100644 src/libasr/pass/array_struct_temporary.h create mode 100644 src/libasr/pass/openmp.cpp create mode 100644 src/libasr/pass/replace_array_passed_in_function_call.h create mode 100644 src/libasr/pass/replace_openmp.h create mode 100644 src/libasr/pass/replace_with_compile_time_values.cpp create mode 100644 src/libasr/pass/replace_with_compile_time_values.h diff --git a/integration_tests/array_expr_05.py b/integration_tests/array_expr_05.py index 8736470c71..7a7beeb1ae 100644 --- a/integration_tests/array_expr_05.py +++ b/integration_tests/array_expr_05.py @@ -1,4 +1,4 @@ -from lpython import u8, u16, u32, u64 +from lpython import u8, u16, u32, u64, i8 from numpy import uint8, uint16, uint32, uint64, array def g(): @@ -7,11 +7,6 @@ def g(): a32: u32[3] = array([127, 3, 111], dtype=uint32) a64: u64[3] = array([127, 3, 111], dtype=uint64) - print(a8) - print(a16) - print(a32) - print(a64) - assert (a8[0] == u8(127)) assert (a8[1] == u8(3)) assert (a8[2] == u8(111)) @@ -28,4 +23,9 @@ def g(): assert (a64[1] == u64(3)) assert (a64[2] == u64(111)) + print(a8) + print(a16) + print(a32) + print(a64) + g() diff --git a/integration_tests/bindc_02.py b/integration_tests/bindc_02.py index 285b8e3085..1340a28d0e 100644 --- a/integration_tests/bindc_02.py +++ b/integration_tests/bindc_02.py @@ -13,12 +13,12 @@ def f(): y[1] = i16(2) yptr1 = pointer(y) print(pointer(y), yptr1) - print(yptr1[0], yptr1[1]) - assert yptr1[0] == i16(1) - assert yptr1[1] == i16(2) + # print(yptr1[0], yptr1[1]) + # assert yptr1[0] == i16(1) + # assert yptr1[1] == i16(2) - yptr1 = c_p_pointer(yq, i16[:], array([2])) + # yptr1 = c_p_pointer(yq, i16[:], array([2])) - print(yq, yptr1) + # print(yq, yptr1) f() diff --git a/src/bin/lpython.cpp b/src/bin/lpython.cpp index be8af27d0c..a630a7656d 100644 --- a/src/bin/lpython.cpp +++ b/src/bin/lpython.cpp @@ -856,9 +856,9 @@ int interactive_python_repl( std::cout << " - History (Keys: Up, Down)" << std::endl; std::vector history; - + std::function iscomplete = determine_completeness; - + std::string code_string; size_t cell_count = 0; while (true) { @@ -1013,8 +1013,8 @@ int interactive_python_repl( } case (LCompilers::PythonCompiler::EvalResult::struct_type) : { if (verbose) { - std::cout << "Return type: " - << LCompilers::ASRUtils::get_type_code(r.structure.ttype) + std::cout << "Return type: " + << LCompilers::ASRUtils::get_type_code(r.structure.ttype) << std::endl; } if (verbose) section("Result:"); @@ -1094,7 +1094,7 @@ int compile_python_using_llvm( } LCompilers::ASR::TranslationUnit_t* asr = r1.result; if( compiler_options.po.disable_main ) { - int err = LCompilers::LPython::save_pyc_files(*asr, infile); + int err = LCompilers::LPython::save_pyc_files(*asr, infile, lm); if( err ) { return err; } @@ -1237,7 +1237,7 @@ int compile_to_binary_wasm( } LCompilers::ASR::TranslationUnit_t* asr = r1.result; if( compiler_options.po.disable_main ) { - int err = LCompilers::LPython::save_pyc_files(*asr, infile); + int err = LCompilers::LPython::save_pyc_files(*asr, infile, lm); if( err ) { return err; } @@ -1310,7 +1310,7 @@ int compile_to_binary_x86( } LCompilers::ASR::TranslationUnit_t* asr = r1.result; if( compiler_options.po.disable_main ) { - int err = LCompilers::LPython::save_pyc_files(*asr, infile); + int err = LCompilers::LPython::save_pyc_files(*asr, infile, lm); if( err ) { return err; } @@ -1384,7 +1384,7 @@ int compile_to_binary_wasm_to_x86( } LCompilers::ASR::TranslationUnit_t* asr = r1.result; if( compiler_options.po.disable_main ) { - int err = LCompilers::LPython::save_pyc_files(*asr, infile); + int err = LCompilers::LPython::save_pyc_files(*asr, infile, lm); if( err ) { return err; } diff --git a/src/libasr/ASR.asdl b/src/libasr/ASR.asdl index 5ea9a482b5..c7ade751fc 100644 --- a/src/libasr/ASR.asdl +++ b/src/libasr/ASR.asdl @@ -9,17 +9,17 @@ unit = TranslationUnit(symbol_table symtab, node* items) symbol - = Program(symbol_table symtab, identifier name, identifier* dependencies, stmt* body) - | Module(symbol_table symtab, identifier name, identifier* dependencies, bool loaded_from_mod, bool intrinsic) - | Function(symbol_table symtab, identifier name, ttype function_signature, identifier* dependencies, expr* args, stmt* body, expr? return_var, access access, bool deterministic, bool side_effect_free, string? module_file) + = Program(symbol_table symtab, identifier name, identifier* dependencies, stmt* body, location start_name, location end_name) + | Module(symbol_table symtab, identifier name, identifier* dependencies, bool loaded_from_mod, bool intrinsic, location start_name, location end_name) + | Function(symbol_table symtab, identifier name, ttype function_signature, identifier* dependencies, expr* args, stmt* body, expr? return_var, access access, bool deterministic, bool side_effect_free, string? module_file, location start_name, location end_name) | GenericProcedure(symbol_table parent_symtab, identifier name, symbol* procs, access access) | CustomOperator(symbol_table parent_symtab, identifier name, symbol* procs, access access) | ExternalSymbol(symbol_table parent_symtab, identifier name, symbol external, identifier module_name, identifier* scope_names, identifier original_name, access access) | Struct(symbol_table symtab, identifier name, identifier* dependencies, identifier* members, identifier* member_functions, abi abi, access access, bool is_packed, bool is_abstract, call_arg* initializers, expr? alignment, symbol? parent) - | EnumType(symbol_table symtab, identifier name, identifier* dependencies, identifier* members, abi abi, access access, enumtype enum_value_type, ttype type, symbol? parent) - | UnionType(symbol_table symtab, identifier name, identifier* dependencies, identifier* members, abi abi, access access, call_arg* initializers, symbol? parent) - | Variable(symbol_table parent_symtab, identifier name, identifier* dependencies, intent intent, expr? symbolic_value, expr? value, storage_type storage, ttype type, symbol? type_declaration, abi abi, access access, presence presence, bool value_attr) - | ClassType(symbol_table symtab, identifier name, abi abi, access access) + | Enum(symbol_table symtab, identifier name, identifier* dependencies, identifier* members, abi abi, access access, enumtype enum_value_type, ttype type, symbol? parent) + | Union(symbol_table symtab, identifier name, identifier* dependencies, identifier* members, abi abi, access access, call_arg* initializers, symbol? parent) + | Variable(symbol_table parent_symtab, identifier name, identifier* dependencies, intent intent, expr? symbolic_value, expr? value, storage_type storage, ttype type, symbol? type_declaration, abi abi, access access, presence presence, bool value_attr, bool target_attr) + | Class(symbol_table symtab, identifier name, abi abi, access access) | ClassProcedure(symbol_table parent_symtab, identifier name, identifier? self_argument, identifier proc_name, symbol proc, abi abi, bool is_deferred, bool is_nopass) | AssociateBlock(symbol_table symtab, identifier name, stmt* body) | Block(symbol_table symtab, identifier name, stmt* body) @@ -35,7 +35,7 @@ stmt | Cycle(identifier? stmt_name) | ExplicitDeallocate(expr* vars) | ImplicitDeallocate(expr* vars) - | DoConcurrentLoop(do_loop_head head, stmt* body) + | DoConcurrentLoop(do_loop_head* head, expr* shared, expr* local, reduction_expr* reduction, stmt* body) | DoLoop(identifier? name, do_loop_head head, stmt* body, stmt* orelse) | ErrorStop(expr? code) | Exit(identifier? stmt_name) @@ -45,23 +45,23 @@ stmt | GoToTarget(int id, identifier name) | If(expr test, stmt* body, stmt* orelse) | IfArithmetic(expr test, int lt_label, int eq_label, int gt_label) - | Print(expr* values, expr? separator, expr? end) + | Print(expr text) | FileOpen(int label, expr? newunit, expr? filename, expr? status, expr? form) | FileClose(int label, expr? unit, expr? iostat, expr? iomsg, expr? err, expr? status) | FileRead(int label, expr? unit, expr? fmt, expr? iomsg, expr? iostat, expr? size, expr? id, expr* values, stmt? overloaded) | FileBackspace(int label, expr? unit, expr? iostat, expr? err) | FileRewind(int label, expr? unit, expr? iostat, expr? err) - | FileInquire(int label, expr? unit, expr? file, expr? iostat, expr? err, expr? exist, expr? opened, expr? number, expr? named, expr? name, expr? access, expr? sequential, expr? direct, expr? form, expr? formatted, expr? unformatted, expr? recl, expr? nextrec, expr? blank, expr? position, expr? action, expr? read, expr? write, expr? readwrite, expr? delim, expr? pad, expr? flen, expr? blocksize, expr? convert, expr? carriagecontrol, expr? iolength) + | FileInquire(int label, expr? unit, expr? file, expr? iostat, expr? err, expr? exist, expr? opened, expr? number, expr? named, expr? name, expr? access, expr? sequential, expr? direct, expr? form, expr? formatted, expr? unformatted, expr? recl, expr? nextrec, expr? blank, expr? position, expr? action, expr? read, expr? write, expr? readwrite, expr? delim, expr? pad, expr? flen, expr? blocksize, expr? convert, expr? carriagecontrol, expr? size, expr? iolength) | FileWrite(int label, expr? unit, expr? iomsg, expr? iostat, expr? id, expr* values, expr? separator, expr? end, stmt? overloaded) | Return() | Select(expr test, case_stmt* body, stmt* default, bool enable_fall_through) | Stop(expr? code) | Assert(expr test, expr? msg) | SubroutineCall(symbol name, symbol? original_name, call_arg* args, expr? dt) - | IntrinsicImpureSubroutine(int intrinsic_id, expr* args, int overload_id) + | IntrinsicImpureSubroutine(int sub_intrinsic_id, expr* args, int overload_id) | Where(expr test, stmt* body, stmt* orelse) | WhileLoop(identifier? name, expr test, stmt* body, stmt* orelse) - | Nullify(symbol* vars) + | Nullify(expr* vars) | Flush(int label, expr unit, expr? err, expr? iomsg, expr? iostat) | ListAppend(expr a, expr ele) | AssociateBlockCall(symbol m) @@ -89,11 +89,11 @@ expr | IntrinsicImpureFunction(int impure_intrinsic_id, expr* args, int overload_id, ttype? type, expr? value) | TypeInquiry(int inquiry_id, ttype arg_type, expr? arg, ttype type, expr value) | StructConstructor(symbol dt_sym, call_arg* args, ttype type, expr? value) - | EnumTypeConstructor(symbol dt_sym, expr* args, ttype type, expr? value) - | UnionTypeConstructor(symbol dt_sym, expr* args, ttype type, expr? value) + | StructConstant(symbol dt_sym, call_arg* args, ttype type) + | EnumConstructor(symbol dt_sym, expr* args, ttype type, expr? value) + | UnionConstructor(symbol dt_sym, expr* args, ttype type, expr? value) | ImpliedDoLoop(expr* values, expr var, expr start, expr end, expr? increment, ttype type, expr? value) - | IntegerConstant(int n, ttype type) - | IntegerBOZ(int v, integerboz intboz_type, ttype? type) + | IntegerConstant(int n, ttype type, integerboz intboz_type) | IntegerBitNot(expr arg, ttype type, expr? value) | IntegerUnaryMinus(expr arg, ttype type, expr? value) | IntegerCompare(expr left, cmpop op, expr right, ttype type, expr? value) @@ -139,7 +139,8 @@ expr | StringContains(expr substr, expr str, ttype type, expr? value) | StringOrd(expr arg, ttype type, expr? value) | StringChr(expr arg, ttype type, expr? value) - | StringFormat(expr fmt, expr* args, string_format_kind kind, ttype type, expr? value) + | StringFormat(expr? fmt, expr* args, string_format_kind kind, ttype type, expr? value) + | StringPhysicalCast(expr arg, string_physical_type old, string_physical_type new, ttype type, expr? value) | CPtrCompare(expr left, cmpop op, expr right, ttype type, expr? value) | SymbolicCompare(expr left, cmpop op, expr right, ttype type, expr? value) | DictConstant(expr* keys, expr* values, ttype type) @@ -147,7 +148,7 @@ expr | Var(symbol v) | FunctionParam(int param_number, ttype type, expr? value) | ArrayConstructor(expr* args, ttype type, expr? value, arraystorage storage_format) - | ArrayConstant(expr* args, ttype type, arraystorage storage_format) + | ArrayConstant(int n_data, void data, ttype type, arraystorage storage_format) | ArrayItem(expr v, array_index* args, ttype type, arraystorage storage_format, expr? value) | ArraySection(expr v, array_index* args, ttype type, expr? value) | ArraySize(expr v, expr? dim, ttype type, expr? value) @@ -191,21 +192,22 @@ expr | PointerNullConstant(ttype type) | PointerAssociated(expr ptr, expr? tgt, ttype type, expr? value) | RealSqrt(expr arg, ttype type, expr? value) + | ArrayIsContiguous(expr array, ttype type, expr? value) ttype = Integer(int kind) | UnsignedInteger(int kind) | Real(int kind) | Complex(int kind) - | Character(int kind, int len, expr? len_expr) + | String(int kind, int len, expr? len_expr, string_physical_type physical_type) | Logical(int kind) | Set(ttype type) | List(ttype type) | Tuple(ttype* type) | StructType(ttype* data_member_types, ttype* member_function_types, bool is_cstruct, symbol derived_type) - | Enum(symbol enum_type) - | Union(symbol union_type) - | Class(symbol class_type) + | EnumType(symbol enum_type) + | UnionType(symbol union_type) + | ClassType(symbol class_type) | Dict(ttype key_type, ttype value_type) | Pointer(ttype type) | Allocatable(ttype type) @@ -215,7 +217,7 @@ ttype | Array(ttype type, dimension* dims, array_physical_type physical_type) | FunctionType(ttype* arg_types, ttype? return_var_type, abi abi, deftype deftype, string? bindc_name, bool elemental, bool pure, bool module, bool inline, bool static, symbol* restrictions, bool is_restriction) -cast_kind = RealToInteger | IntegerToReal | LogicalToReal | RealToReal | IntegerToInteger | RealToComplex | IntegerToComplex | IntegerToLogical | RealToLogical | CharacterToLogical | CharacterToInteger | CharacterToList | ComplexToLogical | ComplexToComplex | ComplexToReal | ComplexToInteger | LogicalToInteger | RealToCharacter | IntegerToCharacter | LogicalToCharacter | UnsignedIntegerToInteger | UnsignedIntegerToUnsignedInteger | UnsignedIntegerToReal | UnsignedIntegerToLogical | IntegerToUnsignedInteger | RealToUnsignedInteger | CPtrToUnsignedInteger | UnsignedIntegerToCPtr | IntegerToSymbolicExpression | ListToArray | DerivedToBase +cast_kind = RealToInteger | IntegerToReal | LogicalToReal | RealToReal | IntegerToInteger | RealToComplex | IntegerToComplex | IntegerToLogical | RealToLogical | StringToLogical | StringToInteger | StringToList | ComplexToLogical | ComplexToComplex | ComplexToReal | ComplexToInteger | LogicalToInteger | RealToString | IntegerToString | LogicalToString | UnsignedIntegerToInteger | UnsignedIntegerToUnsignedInteger | UnsignedIntegerToReal | UnsignedIntegerToLogical | IntegerToUnsignedInteger | RealToUnsignedInteger | CPtrToUnsignedInteger | UnsignedIntegerToCPtr | IntegerToSymbolicExpression | ListToArray storage_type = Default | Save | Parameter access = Public | Private intent = Local | In | Out | InOut | ReturnVar | Unspecified @@ -227,6 +229,7 @@ alloc_arg = (expr a, dimension* dims, expr? len_expr, ttype? type) attribute = Attribute(identifier name, attribute_arg *args) attribute_arg = (identifier arg) call_arg = (expr? value) +reduction_expr = (reduction_op op, expr arg) tbind = Bind(string lang, string name) array_index = (expr? left, expr? right, expr? step) do_loop_head = (expr? v, expr? start, expr? end, expr? increment) @@ -234,11 +237,13 @@ case_stmt = CaseStmt(expr* test, stmt* body, bool fall_through) | CaseStmt_Range type_stmt = TypeStmtName(symbol sym, stmt* body) | ClassStmt(symbol sym, stmt* body) | TypeStmtType(ttype type, stmt* body) enumtype = IntegerConsecutiveFromZero | IntegerUnique | IntegerNotUnique | NonInteger require_instantiation = Require(identifier name, identifier* args) -array_physical_type = DescriptorArray | PointerToDataArray | UnboundedPointerToDataArray | FixedSizeArray | CharacterArraySinglePointer | NumPyArray | ISODescriptorArray | SIMDArray +array_physical_type = DescriptorArray | PointerToDataArray | UnboundedPointerToDataArray | FixedSizeArray | StringArraySinglePointer | NumPyArray | ISODescriptorArray | SIMDArray +string_physical_type = PointerString | DescriptorString binop = Add | Sub | Mul | Div | Pow | BitAnd | BitOr | BitXor | BitLShift | BitRShift +reduction_op = ReduceAdd | ReduceSub | ReduceMul | ReduceMIN | ReduceMAX logicalbinop = And | Or | Xor | NEqv | Eqv cmpop = Eq | NotEq | Lt | LtE | Gt | GtE -integerboz = Binary | Hex | Octal +integerboz = Binary | Hex | Octal | Decimal arraybound = LBound | UBound arraystorage = RowMajor | ColMajor string_format_kind = FormatFortran | FormatC | FormatPythonPercent | FormatPythonFString | FormatPythonFormat diff --git a/src/libasr/CMakeLists.txt b/src/libasr/CMakeLists.txt index 0d69d7cfaa..861fc439a7 100644 --- a/src/libasr/CMakeLists.txt +++ b/src/libasr/CMakeLists.txt @@ -12,7 +12,7 @@ if (NOT LFORTRAN_VERSION) CACHE STRING "LFortran version" FORCE) endif () -configure_file(config.h.in config.h) +configure_file(config.h.in ${CMAKE_CURRENT_SOURCE_DIR}/config.h) set(SRC codegen/asr_to_cpp.cpp @@ -30,8 +30,11 @@ set(SRC codegen/wasm_utils.cpp pass/nested_vars.cpp + pass/array_struct_temporary.cpp pass/where.cpp pass/function_call_in_declaration.cpp + pass/array_passed_in_function_call.cpp + pass/openmp.cpp pass/param_to_const.cpp pass/do_loops.cpp pass/for_all.cpp @@ -70,6 +73,7 @@ set(SRC pass/unique_symbols.cpp pass/insert_deallocate.cpp pass/promote_allocatable_to_nonallocatable.cpp + pass/replace_with_compile_time_values.cpp asr_verify.cpp asr_utils.cpp @@ -81,6 +85,7 @@ set(SRC modfile.cpp pickle.cpp serialization.cpp + stacktrace.cpp utils2.cpp ) if (WITH_LLVM) @@ -90,6 +95,9 @@ if (WITH_LLVM) codegen/llvm_array_utils.cpp codegen/llvm_utils.cpp ) + if (WITH_MLIR) + set(SRC ${SRC} codegen/asr_to_mlir.cpp) + endif() # We use deprecated API in LLVM, so we disable the warning until we upgrade if (NOT MSVC) set_source_files_properties(codegen/evaluator.cpp PROPERTIES @@ -100,11 +108,16 @@ if (WITH_LLVM) COMPILE_FLAGS -Wno-deprecated-declarations) set_source_files_properties(codegen/llvm_utils.cpp PROPERTIES COMPILE_FLAGS -Wno-deprecated-declarations) + set_source_files_properties(stacktrace.cpp PROPERTIES + COMPILE_FLAGS -Wno-deprecated-declarations) endif() endif() add_library(asr STATIC ${SRC}) target_include_directories(asr BEFORE PUBLIC ${libasr_SOURCE_DIR}/..) target_include_directories(asr BEFORE PUBLIC ${libasr_BINARY_DIR}/..) +if (WITH_LIBUNWIND) + target_link_libraries(asr p::libunwind) +endif() if (WITH_BFD) target_link_libraries(asr p::bfd) endif() diff --git a/src/libasr/asdl.py b/src/libasr/asdl.py index a579443b98..e737d4235d 100644 --- a/src/libasr/asdl.py +++ b/src/libasr/asdl.py @@ -33,7 +33,7 @@ # See the EBNF at the top of the file to understand the logical connection # between the various node types. -builtin_types = {'identifier', 'string', 'int', 'bool', 'float', 'node', 'symbol_table'} +builtin_types = {'identifier', 'string', 'int', 'bool', 'float', 'node', 'symbol_table', 'void', 'location'} class AST: def __repr__(self): diff --git a/src/libasr/asdl_cpp.py b/src/libasr/asdl_cpp.py index 9463cb9d1f..2b9ed51ea8 100644 --- a/src/libasr/asdl_cpp.py +++ b/src/libasr/asdl_cpp.py @@ -2,8 +2,10 @@ Generate C++ AST node definitions from an ASDL description. """ -import sys import os +from pathlib import Path +import sys + import asdl @@ -112,6 +114,12 @@ def convert_type(asdl_type, seq, opt, mod_name): elif asdl_type == "int": type_ = "int64_t" assert not seq + elif asdl_type == "void": + type_ = "void *" + assert not seq + elif asdl_type == "location": + type_ = "Location*" + assert not seq else: type_ = asdl_type + "_t" if asdl_type in products: @@ -241,7 +249,10 @@ def visitConstructor(self, cons, base, extra_attributes): else: seq = "" self.emit("%s m_%s;%s" % (type_, f.name, seq), 2) - args.append("%s a_%s" % (type_, f.name)) + if f.type == "location": + args.append("%s a_%s = nullptr" % (type_, f.name)) + else: + args.append("%s a_%s" % (type_, f.name)) lines.append("n->m_%s = a_%s;" % (f.name, f.name)) if f.name in ["global_scope", "symtab"]: lines.append("a_%s->asr_owner = (asr_t*)n;" % (f.name)) @@ -249,6 +260,8 @@ def visitConstructor(self, cons, base, extra_attributes): args.append("size_t n_%s" % (f.name)) lines.append("n->n_%s = n_%s;" % (f.name, f.name)) self.emit("};", 1) + if ( cons.name == "IntegerConstant" ): + args[-1] += " = ASR::integerbozType::Decimal" self.emit("static inline %s_t* make_%s_t(%s) {" % (subs["mod"], cons.name, ", ".join(args)), 1) self.emit( "%s_t *n;" % cons.name, 2) @@ -308,11 +321,11 @@ def visitModule(self, mod): self.emit("/" + "*"*78 + "/") self.emit("// Visitor base class") self.emit("") - self.emit("template ") + self.emit("template ") self.emit("class BaseVisitor") self.emit("{") self.emit("private:") - self.emit(" Struct& self() { return static_cast(*this); }") + self.emit(" StructType& self() { return static_cast(*this); }") self.emit("public:") self.emit( "void visit_%(mod)s(const %(mod)s_t &b) { visit_%(mod)s_t(b, self()); }" % subs, 1) super(ASTVisitorVisitor2, self).visitModule(mod) @@ -329,6 +342,190 @@ def visitSum(self, sum, base): self.emit("""void visit_%s(const %s_t & /* x */) { throw LCompilersException("visit_%s() not implemented"); }""" \ % (type_.name, type_.name, type_.name), 2) +class DefaultLookupNameVisitor(ASDLVisitor): + + def visitModule(self, mod): + self.emit("/" + "*"*78 + "/") + self.emit("// Walk Visitor base class") + self.emit("") + self.emit("template ") + self.emit("class DefaultLookupNameVisitor : public BaseVisitor") + self.emit("{") + self.emit("private:") + self.emit(" StructType& self() { return static_cast(*this); }") + self.emit("public:") + self.emit("uint16_t pos;", 1) + self.emit("uint32_t min_span = UINT32_MAX;", 1) + self.emit("ASR::asr_t* node_to_return = nullptr;", 1) + self.emit("bool test_loc_and_set_span(Location loc) {", 1) + self.emit("uint32_t first = loc.first;", 2) + self.emit("uint32_t last = loc.last;", 2) + self.emit("if (first <= pos && pos <= last) {", 2) + self.emit("uint32_t span = last - first;", 3) + self.emit("if (span < min_span) {", 3) + self.emit("min_span = span;", 4) + self.emit("return true;", 4) + self.emit("}", 3) + self.emit("}", 2) + self.emit("return false;", 2) + self.emit("}", 1) + self.emit("void handle_symbol(const symbol_t* sym) {", 1) + self.emit("switch(sym->type) {", 2) + self.emit("case ASR::symbolType::Program: {", 3) + self.emit("node_to_return = ( ASR::asr_t* ) ((Program_t*)sym);", 4) + self.emit("return;", 4) + self.emit("}", 3) + self.emit("case ASR::symbolType::Module: {", 3) + self.emit("node_to_return = ( ASR::asr_t* ) ((Module_t*)sym);", 4) + self.emit("return;", 4) + self.emit("}", 3) + self.emit("case ASR::symbolType::Function: {", 3) + self.emit("node_to_return = ( ASR::asr_t* ) ((Function_t*)sym);", 4) + self.emit("return;", 4) + self.emit("}", 3) + self.emit("case ASR::symbolType::GenericProcedure: {", 3) + self.emit("node_to_return = ( ASR::asr_t* ) ((GenericProcedure_t*)sym);", 4) + self.emit("return;", 4) + self.emit("}", 3) + self.emit("case ASR::symbolType::CustomOperator: {", 3) + self.emit("node_to_return = ( ASR::asr_t* ) ((CustomOperator_t*)sym);", 4) + self.emit("return;", 4) + self.emit("}", 3) + self.emit("case ASR::symbolType::ExternalSymbol: {", 3) + self.emit("node_to_return = ( ASR::asr_t* ) ((ExternalSymbol_t*)sym);", 4) + self.emit("return;", 4) + self.emit("}", 3) + self.emit("case ASR::symbolType::Struct: {", 3) + self.emit("node_to_return = ( ASR::asr_t* ) ((Struct_t*)sym);", 4) + self.emit("return;", 4) + self.emit("}", 3) + self.emit("case ASR::symbolType::Enum: {", 3) + self.emit("node_to_return = ( ASR::asr_t* ) ((Enum_t*)sym);", 4) + self.emit("return;", 4) + self.emit("}", 3) + self.emit("case ASR::symbolType::Union: {", 3) + self.emit("node_to_return = ( ASR::asr_t* ) ((Union_t*)sym);", 4) + self.emit("return;", 4) + self.emit("}", 3) + self.emit("case ASR::symbolType::Variable: {", 3) + self.emit("node_to_return = ( ASR::asr_t* ) ((Variable_t*)sym);", 4) + self.emit("return;", 4) + self.emit("}", 3) + self.emit("case ASR::symbolType::Class: {", 3) + self.emit("node_to_return = ( ASR::asr_t* ) ((Class_t*)sym);", 4) + self.emit("return;", 4) + self.emit("}", 3) + self.emit("case ASR::symbolType::ClassProcedure: {", 3) + self.emit("node_to_return = ( ASR::asr_t* ) ((ClassProcedure_t*)sym);", 4) + self.emit("return;", 4) + self.emit("}", 3) + self.emit("case ASR::symbolType::AssociateBlock: {", 3) + self.emit("node_to_return = ( ASR::asr_t* ) ((AssociateBlock_t*)sym);", 4) + self.emit("return;", 4) + self.emit("}", 3) + self.emit("case ASR::symbolType::Block: {", 3) + self.emit("node_to_return = ( ASR::asr_t* ) ((Block_t*)sym);", 4) + self.emit("return;", 4) + self.emit("}", 3) + self.emit("case ASR::symbolType::Requirement: {", 3) + self.emit("node_to_return = ( ASR::asr_t* ) ((Requirement_t*)sym);", 4) + self.emit("return;", 4) + self.emit("}", 3) + self.emit("case ASR::symbolType::Template: {", 3) + self.emit("node_to_return = ( ASR::asr_t* ) ((Template_t*)sym);", 4) + self.emit("return;", 4) + self.emit("}", 3) + self.emit("}", 2) + self.emit("}", 1) + self.emit("static inline const ASR::symbol_t *symbol_get_past_external_(ASR::symbol_t *f) {", 1) + self.emit("if (f->type == ASR::symbolType::ExternalSymbol) {", 2) + self.emit("ASR::ExternalSymbol_t *e = ASR::down_cast(f);", 3) + self.emit("LCOMPILERS_ASSERT(!ASR::is_a(*e->m_external));", 3) + self.emit("return e->m_external;", 3) + self.emit("} else {", 2) + self.emit("return f;", 3) + self.emit("}", 2) + self.emit("}", 1) + super(DefaultLookupNameVisitor, self).visitModule(mod) + self.emit("};") + + def visitType(self, tp): + if not (isinstance(tp.value, asdl.Sum) and + is_simple_sum(tp.value)): + super(DefaultLookupNameVisitor, self).visitType(tp, tp.name) + + def visitProduct(self, prod, name): + self.make_visitor(name, prod.fields) + + def visitConstructor(self, cons, _): + self.make_visitor(cons.name, cons.fields) + + def make_visitor(self, name, fields): + # if (test_loc_and_set_span(x.base.base.loc)) { + # node_to_return = (ASR::asr_t*) &x; + # } + self.emit("void visit_%s(const %s_t &x) {" % (name, name), 1) + self.used = False + have_body = False + have_symbol = False + sym_field_name = "" + for field in fields: + if ( not have_symbol and field.type == "symbol" and field.seq == False): + have_symbol = True + sym_field_name = field.name + self.visitField(field) + if not self.used: + # Note: a better solution would be to change `&x` to `& /* x */` + # above, but we would need to change emit to return a string. + self.emit("if ((bool&)x) { } // Suppress unused warning", 2) + if name in products: + self.emit("if (test_loc_and_set_span(x.loc)) {", 2) + else: + self.emit("if (test_loc_and_set_span(x.base.base.loc)) {", 2) + if ( have_symbol and name != "Variable" ): + self.emit(f"self().handle_symbol(self().symbol_get_past_external_(x.m_{sym_field_name}));", 3) + else: + self.emit("node_to_return = (ASR::asr_t*) &x;", 3) + self.emit("}", 2) + self.emit("}", 1) + + def visitField(self, field): + if (field.type not in asdl.builtin_types and + field.type not in self.data.simple_types): + level = 2 + if field.seq: + self.used = True + self.emit("for (size_t i=0; iget_scope()) {" % field.name, 2) + self.emit( "this->visit_symbol(*a.second);", 3) + self.emit("}", 2) class ASTWalkVisitorVisitor(ASDLVisitor): @@ -336,12 +533,13 @@ def visitModule(self, mod): self.emit("/" + "*"*78 + "/") self.emit("// Walk Visitor base class") self.emit("") - self.emit("template ") - self.emit("class BaseWalkVisitor : public BaseVisitor") + self.emit("template ") + self.emit("class BaseWalkVisitor : public BaseVisitor") self.emit("{") self.emit("private:") - self.emit(" Struct& self() { return static_cast(*this); }") + self.emit(" StructType& self() { return static_cast(*this); }") self.emit("public:") + self.emit(" bool visit_compile_time_value = true;") super(ASTWalkVisitorVisitor, self).visitModule(mod) self.emit("};") @@ -385,7 +583,10 @@ def visitField(self, field): if field.type in products: self.used = True if field.opt: - self.emit("if (x.m_%s)" % field.name, 2) + if field.name == "value": + self.emit("if (x.m_%s && visit_compile_time_value)" % field.name, 2) + else: + self.emit("if (x.m_%s)" % field.name, 2) level = 3 if field.opt: self.emit("self().visit_%s(*x.m_%s);" % (field.type, field.name), level) @@ -395,7 +596,10 @@ def visitField(self, field): if field.type != "symbol": self.used = True if field.opt: - self.emit("if (x.m_%s)" % field.name, 2) + if field.name == "value": + self.emit("if (x.m_%s && visit_compile_time_value)" % field.name, 2) + else: + self.emit("if (x.m_%s)" % field.name, 2) level = 3 self.emit("self().visit_%s(*x.m_%s);" % (field.type, field.name), level) elif field.type == "symbol_table" and field.name in["symtab", @@ -411,11 +615,11 @@ def visitModule(self, mod): self.emit("/" + "*"*78 + "/") self.emit("// Walk Visitor base class") self.emit("") - self.emit("template ") - self.emit("class ASRPassBaseWalkVisitor : public BaseVisitor") + self.emit("template ") + self.emit("class ASRPassBaseWalkVisitor : public BaseVisitor") self.emit("{") self.emit("private:") - self.emit(" Struct& self() { return static_cast(*this); }") + self.emit(" StructType& self() { return static_cast(*this); }") self.emit("public:") self.emit(" SymbolTable* current_scope=nullptr;") self.emit(" void transform_stmts(ASR::stmt_t **&m_body, size_t &n_body) {") @@ -520,13 +724,15 @@ def visitModule(self, mod): self.emit("/" + "*"*78 + "/") self.emit("// Walk Visitor base class") self.emit("") - self.emit("template ") - self.emit("class CallReplacerOnExpressionsVisitor : public BaseVisitor") + self.emit("template ") + self.emit("class CallReplacerOnExpressionsVisitor : public BaseVisitor") self.emit("{") self.emit("private:") - self.emit(" Struct& self() { return static_cast(*this); }") + self.emit(" StructType& self() { return static_cast(*this); }") self.emit("public:") - self.emit(" ASR::expr_t** current_expr;") + self.emit(" bool call_replacer_on_value=true;") + self.emit(" bool visit_expr_after_replacement=true;") + self.emit(" ASR::expr_t** current_expr=nullptr;") self.emit(" SymbolTable* current_scope=nullptr;") self.emit("") self.emit(" void call_replacer() {}") @@ -565,6 +771,10 @@ def make_visitor(self, name, fields): if is_stmt_present and name not in ("Assignment", "ForAllSingle", "FileRead", "FileWrite"): self.emit(" %s_t& xx = const_cast<%s_t&>(x);" % (name, name), 1) self.used = False + if name != "call_arg": + self.insert_call_replacer_on_value_check = True + else: + self.insert_call_replacer_on_value_check = False if is_symtab_present: self.emit("SymbolTable* current_scope_copy = current_scope;", 2) @@ -581,11 +791,16 @@ def make_visitor(self, name, fields): self.emit("current_scope = current_scope_copy;", 2) self.emit("}", 1) - def insert_call_replacer_code(self, name, level, index=""): - self.emit("ASR::expr_t** current_expr_copy_%d = current_expr;" % (self.current_expr_copy_variable_count), level) - self.emit("current_expr = const_cast(&(x.m_%s%s));" % (name, index), level) - self.emit("self().call_replacer();", level) - self.emit("current_expr = current_expr_copy_%d;" % (self.current_expr_copy_variable_count), level) + def insert_call_replacer_code(self, name, level, opt, index=""): + one_or_zero = (name == "value" or name == "symbolic_value") and opt and self.insert_call_replacer_on_value_check + if one_or_zero: + self.emit("if (call_replacer_on_value) {", level) + self.emit("ASR::expr_t** current_expr_copy_%d = current_expr;" % (self.current_expr_copy_variable_count), level + one_or_zero) + self.emit("current_expr = const_cast(&(x.m_%s%s));" % (name, index), level + one_or_zero) + self.emit("self().call_replacer();", level + one_or_zero) + self.emit("current_expr = current_expr_copy_%d;" % (self.current_expr_copy_variable_count), level + one_or_zero) + if one_or_zero: + self.emit("}", level) self.current_expr_copy_variable_count += 1 def visitField(self, field): @@ -600,14 +815,14 @@ def visitField(self, field): self.emit("for (size_t i=0; i") - self.emit("class TreeBaseVisitor : public BaseVisitor") + self.emit("template ") + self.emit("class TreeBaseVisitor : public BaseVisitor") self.emit("{") self.emit("private:") - self.emit( "Struct& self() { return static_cast(*this); }", 1) + self.emit( "StructType& self() { return static_cast(*this); }", 1) self.emit("public:") self.emit( "std::string s, indtd;", 1) self.emit( "bool use_colors;", 1) @@ -919,10 +1134,10 @@ def visitModule(self, mod): self.emit("/" + "*"*78 + "/") self.emit("// Expression and statement Duplicator class") self.emit("") - self.emit("template ") + self.emit("template ") self.emit("class BaseExprStmtDuplicator {") self.emit("public:") - self.emit(" Struct& self() { return static_cast(*this); }") + self.emit(" StructType& self() { return static_cast(*this); }") self.emit("") self.emit(" Allocator &al;") self.emit(" bool success;") @@ -1088,7 +1303,8 @@ def visitField(self, field): if (field.type != "call_arg" and field.type != "array_index" and field.type != "alloc_arg" and - field.type != "dimension"): + field.type != "dimension" and + field.type != "do_loop_head"): pointer_char = '*' self.emit("Vec<%s_t%s> m_%s;" % (field.type, pointer_char, field.name), level) self.emit("m_%s.reserve(al, x->n_%s);" % (field.name, field.name), level) @@ -1131,6 +1347,14 @@ def visitField(self, field): self.emit(" dim_copy.m_start = self().duplicate_expr(x->m_%s[i].m_start);"%(field.name), level) self.emit(" dim_copy.m_length = self().duplicate_expr(x->m_%s[i].m_length);"%(field.name), level) self.emit(" m_%s.push_back(al, dim_copy);" % (field.name), level) + elif field.type == "do_loop_head": + self.emit(" ASR::do_loop_head_t head;", level) + self.emit(" head.loc = x->m_head[i].loc;", level) + self.emit(" head.m_v = duplicate_expr(x->m_head[i].m_v);", level) + self.emit(" head.m_start = duplicate_expr(x->m_head[i].m_start);", level) + self.emit(" head.m_end = duplicate_expr(x->m_head[i].m_end);", level) + self.emit(" head.m_increment = duplicate_expr(x->m_head[i].m_increment);", level) + self.emit(" m_%s.push_back(al, head);" % (field.name), level) else: self.emit(" m_%s.push_back(al, self().duplicate_%s(x->m_%s[i]));" % (field.name, field.type, field.name), level) self.emit("}", level) @@ -1176,10 +1400,11 @@ def visitModule(self, mod): self.emit("/" + "*"*78 + "/") self.emit("// Expression Replacer Base class") self.emit("") - self.emit("template ") + self.emit("template ") self.emit("class BaseExprReplacer {") self.emit("public:") - self.emit(" Struct& self() { return static_cast(*this); }") + self.emit(" bool call_replacer_on_value=true;") + self.emit(" StructType& self() { return static_cast(*this); }") self.emit("") self.emit(" ASR::expr_t** current_expr;") self.emit("") @@ -1268,7 +1493,8 @@ def visitField(self, field): field.type == "symbol" or field.type == "call_arg" or field.type == "ttype" or - field.type == "dimension"): + field.type == "dimension" or + field.type == "array_index"): level = 2 if field.seq: self.used = True @@ -1281,6 +1507,16 @@ def visitField(self, field): self.emit(" current_expr = current_expr_copy_%d;" % (self.current_expr_copy_variable_count), level + 1) self.emit(" }", level) self.current_expr_copy_variable_count += 1 + elif field.type == "array_index": + attrs = ["left", "right", "step"] + for attr in attrs: + self.emit(" if (x->m_%s[i].m_%s != nullptr) {" % (field.name, attr), level) + self.emit(" ASR::expr_t** current_expr_copy_%d = current_expr;" % (self.current_expr_copy_variable_count), level + 1) + self.emit(" current_expr = &(x->m_%s[i].m_%s);" % (field.name, attr), level + 1) + self.emit(" self().replace_expr(x->m_%s[i].m_%s);"%(field.name, attr), level + 1) + self.emit(" current_expr = current_expr_copy_%d;" % (self.current_expr_copy_variable_count), level + 1) + self.emit(" }", level) + self.current_expr_copy_variable_count += 1 elif field.type == "dimension": self.emit(" ASR::expr_t** current_expr_copy_%d = current_expr;" % (self.current_expr_copy_variable_count), level) self.emit(" current_expr = &(x->m_%s[i].m_length);" % (field.name), level) @@ -1306,11 +1542,27 @@ def visitField(self, field): if field.type == "ttype": self.emit("self().replace_%s(x->m_%s);" % (field.type, field.name), level) else: - self.emit("ASR::expr_t** current_expr_copy_%d = current_expr;" % (self.current_expr_copy_variable_count), level) - self.emit("current_expr = &(x->m_%s);" % (field.name), level) - self.emit("self().replace_%s(x->m_%s);" % (field.type, field.name), level) - self.emit("current_expr = current_expr_copy_%d;" % (self.current_expr_copy_variable_count), level) - self.current_expr_copy_variable_count += 1 + if field.type == "array_index": + attrs = ["left", "right", "step"] + for attr in attrs: + self.emit("if (x->m_%s.m_%s != nullptr) {" % (field.name, attr), level) + self.emit("ASR::expr_t** current_expr_copy_%d = current_expr;" % (self.current_expr_copy_variable_count), level + 1) + self.emit("current_expr = &(x->m_%s.m_%s);" % (field.name, attr), level + 1) + self.emit("self().replace_expr(x->m_%s.m_%s);"%(field.name, attr), level + 1) + self.emit("current_expr = current_expr_copy_%d;" % (self.current_expr_copy_variable_count), level + 1) + self.emit("}", level) + self.current_expr_copy_variable_count += 1 + else: + one_or_zero = field.name == "value" + if field.name == "value" or field.name == "symbolic_value": + self.emit("if (call_replacer_on_value) {", level) + self.emit("ASR::expr_t** current_expr_copy_%d = current_expr;" % (self.current_expr_copy_variable_count), level + one_or_zero) + self.emit("current_expr = &(x->m_%s);" % (field.name), level + one_or_zero) + self.emit("self().replace_%s(x->m_%s);" % (field.type, field.name), level + one_or_zero) + self.emit("current_expr = current_expr_copy_%d;" % (self.current_expr_copy_variable_count), level + one_or_zero) + if field.name == "value" or field.name == "symbolic_value": + self.emit("}", level) + self.current_expr_copy_variable_count += 1 class StmtBaseReplacerVisitor(ASDLVisitor): @@ -1324,10 +1576,10 @@ def visitModule(self, mod): self.emit("/" + "*"*78 + "/") self.emit("// Statement Replacer Base class") self.emit("") - self.emit("template ") + self.emit("template ") self.emit("class BaseStmtReplacer {") self.emit("public:") - self.emit(" Struct& self() { return static_cast(*this); }") + self.emit(" StructType& self() { return static_cast(*this); }") self.emit("") self.emit(" ASR::stmt_t** current_stmt;") self.emit(" ASR::stmt_t** current_stmt_copy;") @@ -1409,11 +1661,11 @@ def visitModule(self, mod): self.emit("/" + "*"*78 + "/") self.emit("// Pickle Visitor base class") self.emit("") - self.emit("template ") - self.emit("class PickleBaseVisitor : public BaseVisitor") + self.emit("template ") + self.emit("class PickleBaseVisitor : public BaseVisitor") self.emit("{") self.emit("private:") - self.emit( "Struct& self() { return static_cast(*this); }", 1) + self.emit( "StructType& self() { return static_cast(*this); }", 1) self.emit("public:") self.emit( "std::string s, indented = \"\";", 1) self.emit( "bool use_colors;", 1) @@ -1461,7 +1713,7 @@ def make_visitor(self, name, fields, cons): "Integer", "Real", "Complex", - "Character", + "String", "Logical", "Var", ] @@ -1488,8 +1740,10 @@ def make_visitor(self, name, fields, cons): self.emit( 's.append(" ");', 2) self.used = False for n, field in enumerate(fields): + if field.type == "location": + continue self.visitField(field, cons) - if n < len(fields) - 1: + if n < len(fields) - 1 and field.type != "void" and fields[n+1].type != "location": if name not in symbol: self.emit( 'if(indent) s.append("\\n" + indented);', 2) self.emit( 'else s.append(" ");', 2) @@ -1672,6 +1926,8 @@ def visitField(self, field, cons): self.emit('s.append(self().convert_intrinsic_id(x.m_%s));' % field.name, 2) elif field.name == "impure_intrinsic_id": self.emit('s.append(self().convert_impure_intrinsic_id(x.m_%s));' % field.name, 2) + elif field.name == "sub_intrinsic_id": + self.emit('s.append(self().convert_sub_intrinsic_id(x.m_%s));' % field.name, 2) elif field.name == "arr_intrinsic_id": self.emit('s.append(self().convert_array_intrinsic_id(x.m_%s));' % field.name, 2) else: @@ -1690,6 +1946,9 @@ def visitField(self, field, cons): else: self.emit('visit_%sType(x.m_%s);' \ % (field.type, field.name), 2) + elif field.type == "void": + # just skip void fields + pass else: self.emit('s.append("Unimplemented' + field.type + '");', 2) @@ -1699,11 +1958,11 @@ def visitModule(self, mod): self.emit("/" + "*"*78 + "/") self.emit("// Json Visitor base class") self.emit("") - self.emit("template ") - self.emit("class JsonBaseVisitor : public BaseVisitor") + self.emit("template ") + self.emit("class JsonBaseVisitor : public BaseVisitor") self.emit("{") self.emit("private:") - self.emit( "Struct& self() { return static_cast(*this); }", 1) + self.emit( "StructType& self() { return static_cast(*this); }", 1) self.emit("public:") self.emit( "std::string s, indtd = \"\";", 1) self.emit( "bool no_loc = false;", 1) @@ -1795,8 +2054,10 @@ def make_visitor(self, name, fields, cons): if len(fields) > 0: self.emit('inc_indent(); s.append("\\n" + indtd);', 2) for n, field in enumerate(fields): + if field.type == "location": + continue self.visitField(field, cons) - if n < len(fields) - 1: + if n < len(fields) - 1 and fields[n+1].type!="location": self.emit('s.append(",\\n" + indtd);', 2) self.emit('dec_indent(); s.append("\\n" + indtd);', 2) self.emit( 's.append("}");', 2) @@ -1971,11 +2232,11 @@ def visitModule(self, mod): self.emit("/" + "*"*78 + "/") self.emit("// Serialization Visitor base class") self.emit("") - self.emit("template ") - self.emit("class SerializationBaseVisitor : public BaseVisitor") + self.emit("template ") + self.emit("class SerializationBaseVisitor : public BaseVisitor") self.emit("{") self.emit("private:") - self.emit( "Struct& self() { return static_cast(*this); }", 1) + self.emit( "StructType& self() { return static_cast(*this); }", 1) self.emit("public:") self.mod = mod super(SerializationVisitorVisitor, self).visitModule(mod) @@ -2087,6 +2348,8 @@ def visitField(self, field, cons, cons_name): field.name, level+1) self.emit("self().visit_%s(*x.m_%s[i]);" % (mod_name, field.name), level+1) self.emit("}", level) + elif field.type == "void": + self.emit('self().write_void(x.m_data, x.m_n_data);', 2) elif field.type == "symbol_table": assert not field.opt assert not field.seq @@ -2139,6 +2402,16 @@ def visitField(self, field, cons, cons_name): self.emit("}", 2) elif field.type == "float" and not field.seq and not field.opt: self.emit('self().write_float64(x.m_%s);' % field.name, 2) + elif field.type == "void": + assert True + elif field.type == "location": + # self.emit("if (x.m_%s != nullptr) {" % field.name, 2) + # self.emit('self().write_int64(x.m_%s->first);' % field.name, 3) + # self.emit('self().write_int64(x.m_%s->last);' % field.name, 3) + # self.emit("} else {", 2) + self.emit('self().write_int64(0);', 2) + self.emit('self().write_int64(0);', 2) + # self.emit("}", 2) elif field.type in self.data.simple_types: if field.opt: raise Exception("Unimplemented opt for field type: " + field.type); @@ -2154,16 +2427,17 @@ def visitModule(self, mod): self.emit("/" + "*"*78 + "/") self.emit("// Deserialization Visitor base class") self.emit("") - self.emit("template ") - self.emit("class DeserializationBaseVisitor : public BaseVisitor") + self.emit("template ") + self.emit("class DeserializationBaseVisitor : public BaseVisitor") self.emit("{") self.emit("private:") - self.emit( "Struct& self() { return static_cast(*this); }", 1) + self.emit( "StructType& self() { return static_cast(*this); }", 1) self.emit("public:") self.emit( "Allocator &al;", 1) self.emit( "bool load_symtab_id;", 1) + self.emit( "uint32_t offset = 0;", 1) self.emit( "std::map id_symtab_map;", 1) - self.emit( r"DeserializationBaseVisitor(Allocator &al, bool load_symtab_id) : al{al}, load_symtab_id{load_symtab_id} {}", 1) + self.emit( r"DeserializationBaseVisitor(Allocator &al, bool load_symtab_id, uint32_t offset) : al{al}, load_symtab_id{load_symtab_id}, offset{offset} {}", 1) self.emit_deserialize_node(); self.mod = mod super(DeserializationVisitorVisitor, self).visitModule(mod) @@ -2402,6 +2676,15 @@ def visitConstructor(self, cons, _): lines.append(" self().symtab_insert_symbol(*m_%s, name, sym);" % f.name) lines.append(" }") lines.append("}") + elif f.type == "void": + lines.append("void *m_%s = self().read_void(m_n_data);" % (f.name)) + args.append("m_%s" % (f.name)) + elif f.type == "location": + lines.append("Location* m_%s;"% f.name) + lines.append("m_%s = al.make_new();"% f.name) + lines.append("m_%s->first = self().read_int64();"% f.name) + lines.append("m_%s->last = self().read_int64();"% f.name) + args.append("m_%s" % (f.name)) else: print(f.type) assert False @@ -2435,13 +2718,8 @@ def visitConstructor(self, cons, _): args.append("m_%s" % (f.name)) self.emit( 'Location loc;', 2) - self.emit( 'loc.first = self().read_int64();', 2) - self.emit( 'loc.last = self().read_int64();', 2) - if subs["lcompiler"] == "lfortran": - # Set the location to 0 for now, since we do not yet - # support multiple files - self.emit( 'loc.first = 0;', 2) - self.emit( 'loc.last = 0;', 2) + self.emit( 'loc.first = self().read_int64() + offset;', 2) + self.emit( 'loc.last = self().read_int64() + offset;', 2) for line in lines: self.emit(line, 2) self.emit( 'return %s::make_%s_t(%s);' % (subs["MOD"], name, ", ".join(args)), 2) @@ -2509,6 +2787,8 @@ def make_visitor(self, name, fields): } else if( s->type == ASR::symbolType::Variable ) { return ASR::down_cast(s)->m_type; } else { + // ICE: only Function and Variable have types, this symbol + // does not have a type LCOMPILERS_ASSERT_MSG(false, std::to_string(s->type)); } return nullptr; @@ -2589,7 +2869,7 @@ def make_visitor(self, name, fields): return ASR::down_cast(s)->m_value; }""" \ % (name, name), 2, new_line=False) - elif name.endswith("Constant") or name == "IntegerBOZ": + elif name.endswith("Constant"): self.emit("case ASR::exprType::%s: { return f; }"\ % (name), 2, new_line=False) else: @@ -2708,10 +2988,68 @@ def add_masks(fields, node): #endif // LFORTRAN_%(MOD2)s_H """ -visitors = [ASTNodeVisitor0, ASTNodeVisitor1, ASTNodeVisitor, +HEAD_VISITOR = r"""#pragma once + +// Generated by grammar/asdl_cpp.py + +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace LCompilers::%(MOD)s { +""" + +HEAD_BASE_VISITOR = r"""#pragma once + +// Generated by grammar/asdl_cpp.py + +#include +#include +#include +#include +#include +#include +#include + + +namespace LCompilers::%(MOD)s { +""" + +FOOT_VISITOR = r"""} +""" + +ast_visitors = [ASTNodeVisitor0, ASTNodeVisitor1, ASTNodeVisitor, ASTVisitorVisitor1, ASTVisitorVisitor1b, ASTVisitorVisitor2, ASTWalkVisitorVisitor, TreeVisitorVisitor, PickleVisitorVisitor, - JsonVisitorVisitor, SerializationVisitorVisitor, DeserializationVisitorVisitor] + JsonVisitorVisitor, SerializationVisitorVisitor, + DeserializationVisitorVisitor] + +asr_visitors = [ASTNodeVisitor0, ASTNodeVisitor1, ASTNodeVisitor] + +asr_base_visitor = [ASTVisitorVisitor1, ASTVisitorVisitor1b, ASTVisitorVisitor2] + +asr_visitor_files = [ + ("serialization", SerializationVisitorVisitor), + ("deserialization", DeserializationVisitorVisitor), + ("pickle", PickleVisitorVisitor), + ("json", JsonVisitorVisitor), + ("lookup_name", DefaultLookupNameVisitor), + ("tree", TreeVisitorVisitor), + ("pass_walk", ASRPassWalkVisitorVisitor), + ("expr_stmt_duplicator", ExprStmtDuplicatorVisitor), + ("expr_base_replacer", ExprBaseReplacerVisitor), + ("stmt_base_replacer", StmtBaseReplacerVisitor), + ("expr_call_replacer", CallReplacerOnExpressionsVisitor), + ("expr_type", ExprTypeVisitor), + ("expr_value", ExprValueVisitor), + ("walk", ASTWalkVisitorVisitor), + ] def main(argv): @@ -2748,32 +3086,37 @@ def main(argv): fp = open(out_file, "w", encoding="utf-8") try: fp.write(HEAD % subs) - for visitor in visitors: - visitor(fp, data).visit(mod) - fp.write("\n\n") if not is_asr: - fp.write(FOOT % subs) - finally: - if not is_asr: - fp.close() - - try: + for visitor in ast_visitors: + visitor(fp, data).visit(mod) + fp.write("\n\n") if is_asr: - ASRPassWalkVisitorVisitor(fp, data).visit(mod) - fp.write("\n\n") - ExprStmtDuplicatorVisitor(fp, data).visit(mod) - fp.write("\n\n") - ExprBaseReplacerVisitor(fp, data).visit(mod) - fp.write("\n\n") - StmtBaseReplacerVisitor(fp, data).visit(mod) - fp.write("\n\n") - CallReplacerOnExpressionsVisitor(fp, data).visit(mod) - fp.write("\n\n") - ExprTypeVisitor(fp, data).visit(mod) - fp.write("\n\n") - ExprValueVisitor(fp, data).visit(mod) - fp.write("\n\n") - fp.write(FOOT % subs) + for visitor in asr_visitors: + visitor(fp, data).visit(mod) + fp.write("\n\n") + asr_path = Path(out_file) + + # asr_base_visitor + filename = "base" + full_filename = asr_path.with_name( + f"{asr_path.stem}_{filename}_visitor{asr_path.suffix}") + with open(full_filename, "w", encoding="utf-8") as f: + f.write(HEAD_BASE_VISITOR % subs) + for Visitor in asr_base_visitor: + Visitor(f, data).visit(mod) + f.write("\n\n") + f.write(FOOT_VISITOR) + + # asr_visitor_files + for filename, Visitor in asr_visitor_files: + full_filename = asr_path.with_name( + f"{asr_path.stem}_{filename}_visitor{asr_path.suffix}") + with open(full_filename, "w", encoding="utf-8") as f: + f.write(HEAD_VISITOR % subs) + Visitor(f, data).visit(mod) + f.write("\n\n") + f.write(FOOT_VISITOR) + fp.write(FOOT % subs) finally: fp.close() diff --git a/src/libasr/asr_base_visitor.h b/src/libasr/asr_base_visitor.h new file mode 100644 index 0000000000..a92649e892 --- /dev/null +++ b/src/libasr/asr_base_visitor.h @@ -0,0 +1,551 @@ +#pragma once + +// Generated by grammar/asdl_cpp.py + +#include +#include +#include +#include +#include +#include +#include + + +namespace LCompilers::ASR { +/******************************************************************************/ +// Visitor functions + +template +static void visit_unit_t(const unit_t &x, Visitor &v) { + LCOMPILERS_ASSERT(x.base.type == asrType::unit) + switch (x.type) { + case unitType::TranslationUnit: { v.visit_TranslationUnit((const TranslationUnit_t &)x); return; } + } +} + +template +static void visit_symbol_t(const symbol_t &x, Visitor &v) { + LCOMPILERS_ASSERT(x.base.type == asrType::symbol) + switch (x.type) { + case symbolType::Program: { v.visit_Program((const Program_t &)x); return; } + case symbolType::Module: { v.visit_Module((const Module_t &)x); return; } + case symbolType::Function: { v.visit_Function((const Function_t &)x); return; } + case symbolType::GenericProcedure: { v.visit_GenericProcedure((const GenericProcedure_t &)x); return; } + case symbolType::CustomOperator: { v.visit_CustomOperator((const CustomOperator_t &)x); return; } + case symbolType::ExternalSymbol: { v.visit_ExternalSymbol((const ExternalSymbol_t &)x); return; } + case symbolType::Struct: { v.visit_Struct((const Struct_t &)x); return; } + case symbolType::Enum: { v.visit_Enum((const Enum_t &)x); return; } + case symbolType::Union: { v.visit_Union((const Union_t &)x); return; } + case symbolType::Variable: { v.visit_Variable((const Variable_t &)x); return; } + case symbolType::Class: { v.visit_Class((const Class_t &)x); return; } + case symbolType::ClassProcedure: { v.visit_ClassProcedure((const ClassProcedure_t &)x); return; } + case symbolType::AssociateBlock: { v.visit_AssociateBlock((const AssociateBlock_t &)x); return; } + case symbolType::Block: { v.visit_Block((const Block_t &)x); return; } + case symbolType::Requirement: { v.visit_Requirement((const Requirement_t &)x); return; } + case symbolType::Template: { v.visit_Template((const Template_t &)x); return; } + } +} + +template +static void visit_stmt_t(const stmt_t &x, Visitor &v) { + LCOMPILERS_ASSERT(x.base.type == asrType::stmt) + switch (x.type) { + case stmtType::Allocate: { v.visit_Allocate((const Allocate_t &)x); return; } + case stmtType::ReAlloc: { v.visit_ReAlloc((const ReAlloc_t &)x); return; } + case stmtType::Assign: { v.visit_Assign((const Assign_t &)x); return; } + case stmtType::Assignment: { v.visit_Assignment((const Assignment_t &)x); return; } + case stmtType::Associate: { v.visit_Associate((const Associate_t &)x); return; } + case stmtType::Cycle: { v.visit_Cycle((const Cycle_t &)x); return; } + case stmtType::ExplicitDeallocate: { v.visit_ExplicitDeallocate((const ExplicitDeallocate_t &)x); return; } + case stmtType::ImplicitDeallocate: { v.visit_ImplicitDeallocate((const ImplicitDeallocate_t &)x); return; } + case stmtType::DoConcurrentLoop: { v.visit_DoConcurrentLoop((const DoConcurrentLoop_t &)x); return; } + case stmtType::DoLoop: { v.visit_DoLoop((const DoLoop_t &)x); return; } + case stmtType::ErrorStop: { v.visit_ErrorStop((const ErrorStop_t &)x); return; } + case stmtType::Exit: { v.visit_Exit((const Exit_t &)x); return; } + case stmtType::ForAllSingle: { v.visit_ForAllSingle((const ForAllSingle_t &)x); return; } + case stmtType::ForEach: { v.visit_ForEach((const ForEach_t &)x); return; } + case stmtType::GoTo: { v.visit_GoTo((const GoTo_t &)x); return; } + case stmtType::GoToTarget: { v.visit_GoToTarget((const GoToTarget_t &)x); return; } + case stmtType::If: { v.visit_If((const If_t &)x); return; } + case stmtType::IfArithmetic: { v.visit_IfArithmetic((const IfArithmetic_t &)x); return; } + case stmtType::Print: { v.visit_Print((const Print_t &)x); return; } + case stmtType::FileOpen: { v.visit_FileOpen((const FileOpen_t &)x); return; } + case stmtType::FileClose: { v.visit_FileClose((const FileClose_t &)x); return; } + case stmtType::FileRead: { v.visit_FileRead((const FileRead_t &)x); return; } + case stmtType::FileBackspace: { v.visit_FileBackspace((const FileBackspace_t &)x); return; } + case stmtType::FileRewind: { v.visit_FileRewind((const FileRewind_t &)x); return; } + case stmtType::FileInquire: { v.visit_FileInquire((const FileInquire_t &)x); return; } + case stmtType::FileWrite: { v.visit_FileWrite((const FileWrite_t &)x); return; } + case stmtType::Return: { v.visit_Return((const Return_t &)x); return; } + case stmtType::Select: { v.visit_Select((const Select_t &)x); return; } + case stmtType::Stop: { v.visit_Stop((const Stop_t &)x); return; } + case stmtType::Assert: { v.visit_Assert((const Assert_t &)x); return; } + case stmtType::SubroutineCall: { v.visit_SubroutineCall((const SubroutineCall_t &)x); return; } + case stmtType::IntrinsicImpureSubroutine: { v.visit_IntrinsicImpureSubroutine((const IntrinsicImpureSubroutine_t &)x); return; } + case stmtType::Where: { v.visit_Where((const Where_t &)x); return; } + case stmtType::WhileLoop: { v.visit_WhileLoop((const WhileLoop_t &)x); return; } + case stmtType::Nullify: { v.visit_Nullify((const Nullify_t &)x); return; } + case stmtType::Flush: { v.visit_Flush((const Flush_t &)x); return; } + case stmtType::ListAppend: { v.visit_ListAppend((const ListAppend_t &)x); return; } + case stmtType::AssociateBlockCall: { v.visit_AssociateBlockCall((const AssociateBlockCall_t &)x); return; } + case stmtType::SelectType: { v.visit_SelectType((const SelectType_t &)x); return; } + case stmtType::CPtrToPointer: { v.visit_CPtrToPointer((const CPtrToPointer_t &)x); return; } + case stmtType::BlockCall: { v.visit_BlockCall((const BlockCall_t &)x); return; } + case stmtType::SetInsert: { v.visit_SetInsert((const SetInsert_t &)x); return; } + case stmtType::SetRemove: { v.visit_SetRemove((const SetRemove_t &)x); return; } + case stmtType::SetDiscard: { v.visit_SetDiscard((const SetDiscard_t &)x); return; } + case stmtType::ListInsert: { v.visit_ListInsert((const ListInsert_t &)x); return; } + case stmtType::ListRemove: { v.visit_ListRemove((const ListRemove_t &)x); return; } + case stmtType::ListClear: { v.visit_ListClear((const ListClear_t &)x); return; } + case stmtType::DictInsert: { v.visit_DictInsert((const DictInsert_t &)x); return; } + case stmtType::DictClear: { v.visit_DictClear((const DictClear_t &)x); return; } + case stmtType::SetClear: { v.visit_SetClear((const SetClear_t &)x); return; } + case stmtType::Expr: { v.visit_Expr((const Expr_t &)x); return; } + } +} + +template +static void visit_expr_t(const expr_t &x, Visitor &v) { + LCOMPILERS_ASSERT(x.base.type == asrType::expr) + switch (x.type) { + case exprType::IfExp: { v.visit_IfExp((const IfExp_t &)x); return; } + case exprType::ComplexConstructor: { v.visit_ComplexConstructor((const ComplexConstructor_t &)x); return; } + case exprType::NamedExpr: { v.visit_NamedExpr((const NamedExpr_t &)x); return; } + case exprType::FunctionCall: { v.visit_FunctionCall((const FunctionCall_t &)x); return; } + case exprType::IntrinsicElementalFunction: { v.visit_IntrinsicElementalFunction((const IntrinsicElementalFunction_t &)x); return; } + case exprType::IntrinsicArrayFunction: { v.visit_IntrinsicArrayFunction((const IntrinsicArrayFunction_t &)x); return; } + case exprType::IntrinsicImpureFunction: { v.visit_IntrinsicImpureFunction((const IntrinsicImpureFunction_t &)x); return; } + case exprType::TypeInquiry: { v.visit_TypeInquiry((const TypeInquiry_t &)x); return; } + case exprType::StructConstructor: { v.visit_StructConstructor((const StructConstructor_t &)x); return; } + case exprType::StructConstant: { v.visit_StructConstant((const StructConstant_t &)x); return; } + case exprType::EnumConstructor: { v.visit_EnumConstructor((const EnumConstructor_t &)x); return; } + case exprType::UnionConstructor: { v.visit_UnionConstructor((const UnionConstructor_t &)x); return; } + case exprType::ImpliedDoLoop: { v.visit_ImpliedDoLoop((const ImpliedDoLoop_t &)x); return; } + case exprType::IntegerConstant: { v.visit_IntegerConstant((const IntegerConstant_t &)x); return; } + case exprType::IntegerBitNot: { v.visit_IntegerBitNot((const IntegerBitNot_t &)x); return; } + case exprType::IntegerUnaryMinus: { v.visit_IntegerUnaryMinus((const IntegerUnaryMinus_t &)x); return; } + case exprType::IntegerCompare: { v.visit_IntegerCompare((const IntegerCompare_t &)x); return; } + case exprType::IntegerBinOp: { v.visit_IntegerBinOp((const IntegerBinOp_t &)x); return; } + case exprType::UnsignedIntegerConstant: { v.visit_UnsignedIntegerConstant((const UnsignedIntegerConstant_t &)x); return; } + case exprType::UnsignedIntegerUnaryMinus: { v.visit_UnsignedIntegerUnaryMinus((const UnsignedIntegerUnaryMinus_t &)x); return; } + case exprType::UnsignedIntegerBitNot: { v.visit_UnsignedIntegerBitNot((const UnsignedIntegerBitNot_t &)x); return; } + case exprType::UnsignedIntegerCompare: { v.visit_UnsignedIntegerCompare((const UnsignedIntegerCompare_t &)x); return; } + case exprType::UnsignedIntegerBinOp: { v.visit_UnsignedIntegerBinOp((const UnsignedIntegerBinOp_t &)x); return; } + case exprType::RealConstant: { v.visit_RealConstant((const RealConstant_t &)x); return; } + case exprType::RealUnaryMinus: { v.visit_RealUnaryMinus((const RealUnaryMinus_t &)x); return; } + case exprType::RealCompare: { v.visit_RealCompare((const RealCompare_t &)x); return; } + case exprType::RealBinOp: { v.visit_RealBinOp((const RealBinOp_t &)x); return; } + case exprType::RealCopySign: { v.visit_RealCopySign((const RealCopySign_t &)x); return; } + case exprType::ComplexConstant: { v.visit_ComplexConstant((const ComplexConstant_t &)x); return; } + case exprType::ComplexUnaryMinus: { v.visit_ComplexUnaryMinus((const ComplexUnaryMinus_t &)x); return; } + case exprType::ComplexCompare: { v.visit_ComplexCompare((const ComplexCompare_t &)x); return; } + case exprType::ComplexBinOp: { v.visit_ComplexBinOp((const ComplexBinOp_t &)x); return; } + case exprType::LogicalConstant: { v.visit_LogicalConstant((const LogicalConstant_t &)x); return; } + case exprType::LogicalNot: { v.visit_LogicalNot((const LogicalNot_t &)x); return; } + case exprType::LogicalCompare: { v.visit_LogicalCompare((const LogicalCompare_t &)x); return; } + case exprType::LogicalBinOp: { v.visit_LogicalBinOp((const LogicalBinOp_t &)x); return; } + case exprType::ListConstant: { v.visit_ListConstant((const ListConstant_t &)x); return; } + case exprType::ListLen: { v.visit_ListLen((const ListLen_t &)x); return; } + case exprType::ListConcat: { v.visit_ListConcat((const ListConcat_t &)x); return; } + case exprType::ListCompare: { v.visit_ListCompare((const ListCompare_t &)x); return; } + case exprType::ListCount: { v.visit_ListCount((const ListCount_t &)x); return; } + case exprType::ListContains: { v.visit_ListContains((const ListContains_t &)x); return; } + case exprType::SetConstant: { v.visit_SetConstant((const SetConstant_t &)x); return; } + case exprType::SetLen: { v.visit_SetLen((const SetLen_t &)x); return; } + case exprType::TupleConstant: { v.visit_TupleConstant((const TupleConstant_t &)x); return; } + case exprType::TupleLen: { v.visit_TupleLen((const TupleLen_t &)x); return; } + case exprType::TupleCompare: { v.visit_TupleCompare((const TupleCompare_t &)x); return; } + case exprType::TupleConcat: { v.visit_TupleConcat((const TupleConcat_t &)x); return; } + case exprType::TupleContains: { v.visit_TupleContains((const TupleContains_t &)x); return; } + case exprType::StringConstant: { v.visit_StringConstant((const StringConstant_t &)x); return; } + case exprType::StringConcat: { v.visit_StringConcat((const StringConcat_t &)x); return; } + case exprType::StringRepeat: { v.visit_StringRepeat((const StringRepeat_t &)x); return; } + case exprType::StringLen: { v.visit_StringLen((const StringLen_t &)x); return; } + case exprType::StringItem: { v.visit_StringItem((const StringItem_t &)x); return; } + case exprType::StringSection: { v.visit_StringSection((const StringSection_t &)x); return; } + case exprType::StringCompare: { v.visit_StringCompare((const StringCompare_t &)x); return; } + case exprType::StringContains: { v.visit_StringContains((const StringContains_t &)x); return; } + case exprType::StringOrd: { v.visit_StringOrd((const StringOrd_t &)x); return; } + case exprType::StringChr: { v.visit_StringChr((const StringChr_t &)x); return; } + case exprType::StringFormat: { v.visit_StringFormat((const StringFormat_t &)x); return; } + case exprType::StringPhysicalCast: { v.visit_StringPhysicalCast((const StringPhysicalCast_t &)x); return; } + case exprType::CPtrCompare: { v.visit_CPtrCompare((const CPtrCompare_t &)x); return; } + case exprType::SymbolicCompare: { v.visit_SymbolicCompare((const SymbolicCompare_t &)x); return; } + case exprType::DictConstant: { v.visit_DictConstant((const DictConstant_t &)x); return; } + case exprType::DictLen: { v.visit_DictLen((const DictLen_t &)x); return; } + case exprType::Var: { v.visit_Var((const Var_t &)x); return; } + case exprType::FunctionParam: { v.visit_FunctionParam((const FunctionParam_t &)x); return; } + case exprType::ArrayConstructor: { v.visit_ArrayConstructor((const ArrayConstructor_t &)x); return; } + case exprType::ArrayConstant: { v.visit_ArrayConstant((const ArrayConstant_t &)x); return; } + case exprType::ArrayItem: { v.visit_ArrayItem((const ArrayItem_t &)x); return; } + case exprType::ArraySection: { v.visit_ArraySection((const ArraySection_t &)x); return; } + case exprType::ArraySize: { v.visit_ArraySize((const ArraySize_t &)x); return; } + case exprType::ArrayBound: { v.visit_ArrayBound((const ArrayBound_t &)x); return; } + case exprType::ArrayTranspose: { v.visit_ArrayTranspose((const ArrayTranspose_t &)x); return; } + case exprType::ArrayPack: { v.visit_ArrayPack((const ArrayPack_t &)x); return; } + case exprType::ArrayReshape: { v.visit_ArrayReshape((const ArrayReshape_t &)x); return; } + case exprType::ArrayAll: { v.visit_ArrayAll((const ArrayAll_t &)x); return; } + case exprType::ArrayBroadcast: { v.visit_ArrayBroadcast((const ArrayBroadcast_t &)x); return; } + case exprType::BitCast: { v.visit_BitCast((const BitCast_t &)x); return; } + case exprType::StructInstanceMember: { v.visit_StructInstanceMember((const StructInstanceMember_t &)x); return; } + case exprType::StructStaticMember: { v.visit_StructStaticMember((const StructStaticMember_t &)x); return; } + case exprType::EnumStaticMember: { v.visit_EnumStaticMember((const EnumStaticMember_t &)x); return; } + case exprType::UnionInstanceMember: { v.visit_UnionInstanceMember((const UnionInstanceMember_t &)x); return; } + case exprType::EnumName: { v.visit_EnumName((const EnumName_t &)x); return; } + case exprType::EnumValue: { v.visit_EnumValue((const EnumValue_t &)x); return; } + case exprType::OverloadedCompare: { v.visit_OverloadedCompare((const OverloadedCompare_t &)x); return; } + case exprType::OverloadedBinOp: { v.visit_OverloadedBinOp((const OverloadedBinOp_t &)x); return; } + case exprType::OverloadedUnaryMinus: { v.visit_OverloadedUnaryMinus((const OverloadedUnaryMinus_t &)x); return; } + case exprType::OverloadedStringConcat: { v.visit_OverloadedStringConcat((const OverloadedStringConcat_t &)x); return; } + case exprType::Cast: { v.visit_Cast((const Cast_t &)x); return; } + case exprType::ArrayPhysicalCast: { v.visit_ArrayPhysicalCast((const ArrayPhysicalCast_t &)x); return; } + case exprType::ComplexRe: { v.visit_ComplexRe((const ComplexRe_t &)x); return; } + case exprType::ComplexIm: { v.visit_ComplexIm((const ComplexIm_t &)x); return; } + case exprType::DictItem: { v.visit_DictItem((const DictItem_t &)x); return; } + case exprType::CLoc: { v.visit_CLoc((const CLoc_t &)x); return; } + case exprType::PointerToCPtr: { v.visit_PointerToCPtr((const PointerToCPtr_t &)x); return; } + case exprType::GetPointer: { v.visit_GetPointer((const GetPointer_t &)x); return; } + case exprType::ListItem: { v.visit_ListItem((const ListItem_t &)x); return; } + case exprType::TupleItem: { v.visit_TupleItem((const TupleItem_t &)x); return; } + case exprType::ListSection: { v.visit_ListSection((const ListSection_t &)x); return; } + case exprType::ListRepeat: { v.visit_ListRepeat((const ListRepeat_t &)x); return; } + case exprType::DictPop: { v.visit_DictPop((const DictPop_t &)x); return; } + case exprType::SetPop: { v.visit_SetPop((const SetPop_t &)x); return; } + case exprType::SetContains: { v.visit_SetContains((const SetContains_t &)x); return; } + case exprType::DictContains: { v.visit_DictContains((const DictContains_t &)x); return; } + case exprType::IntegerBitLen: { v.visit_IntegerBitLen((const IntegerBitLen_t &)x); return; } + case exprType::Ichar: { v.visit_Ichar((const Ichar_t &)x); return; } + case exprType::Iachar: { v.visit_Iachar((const Iachar_t &)x); return; } + case exprType::SizeOfType: { v.visit_SizeOfType((const SizeOfType_t &)x); return; } + case exprType::PointerNullConstant: { v.visit_PointerNullConstant((const PointerNullConstant_t &)x); return; } + case exprType::PointerAssociated: { v.visit_PointerAssociated((const PointerAssociated_t &)x); return; } + case exprType::RealSqrt: { v.visit_RealSqrt((const RealSqrt_t &)x); return; } + case exprType::ArrayIsContiguous: { v.visit_ArrayIsContiguous((const ArrayIsContiguous_t &)x); return; } + } +} + +template +static void visit_ttype_t(const ttype_t &x, Visitor &v) { + LCOMPILERS_ASSERT(x.base.type == asrType::ttype) + switch (x.type) { + case ttypeType::Integer: { v.visit_Integer((const Integer_t &)x); return; } + case ttypeType::UnsignedInteger: { v.visit_UnsignedInteger((const UnsignedInteger_t &)x); return; } + case ttypeType::Real: { v.visit_Real((const Real_t &)x); return; } + case ttypeType::Complex: { v.visit_Complex((const Complex_t &)x); return; } + case ttypeType::String: { v.visit_String((const String_t &)x); return; } + case ttypeType::Logical: { v.visit_Logical((const Logical_t &)x); return; } + case ttypeType::Set: { v.visit_Set((const Set_t &)x); return; } + case ttypeType::List: { v.visit_List((const List_t &)x); return; } + case ttypeType::Tuple: { v.visit_Tuple((const Tuple_t &)x); return; } + case ttypeType::StructType: { v.visit_StructType((const StructType_t &)x); return; } + case ttypeType::EnumType: { v.visit_EnumType((const EnumType_t &)x); return; } + case ttypeType::UnionType: { v.visit_UnionType((const UnionType_t &)x); return; } + case ttypeType::ClassType: { v.visit_ClassType((const ClassType_t &)x); return; } + case ttypeType::Dict: { v.visit_Dict((const Dict_t &)x); return; } + case ttypeType::Pointer: { v.visit_Pointer((const Pointer_t &)x); return; } + case ttypeType::Allocatable: { v.visit_Allocatable((const Allocatable_t &)x); return; } + case ttypeType::CPtr: { v.visit_CPtr((const CPtr_t &)x); return; } + case ttypeType::SymbolicExpression: { v.visit_SymbolicExpression((const SymbolicExpression_t &)x); return; } + case ttypeType::TypeParameter: { v.visit_TypeParameter((const TypeParameter_t &)x); return; } + case ttypeType::Array: { v.visit_Array((const Array_t &)x); return; } + case ttypeType::FunctionType: { v.visit_FunctionType((const FunctionType_t &)x); return; } + } +} + +template +static void visit_attribute_t(const attribute_t &x, Visitor &v) { + LCOMPILERS_ASSERT(x.base.type == asrType::attribute) + switch (x.type) { + case attributeType::Attribute: { v.visit_Attribute((const Attribute_t &)x); return; } + } +} + +template +static void visit_tbind_t(const tbind_t &x, Visitor &v) { + LCOMPILERS_ASSERT(x.base.type == asrType::tbind) + switch (x.type) { + case tbindType::Bind: { v.visit_Bind((const Bind_t &)x); return; } + } +} + +template +static void visit_case_stmt_t(const case_stmt_t &x, Visitor &v) { + LCOMPILERS_ASSERT(x.base.type == asrType::case_stmt) + switch (x.type) { + case case_stmtType::CaseStmt: { v.visit_CaseStmt((const CaseStmt_t &)x); return; } + case case_stmtType::CaseStmt_Range: { v.visit_CaseStmt_Range((const CaseStmt_Range_t &)x); return; } + } +} + +template +static void visit_type_stmt_t(const type_stmt_t &x, Visitor &v) { + LCOMPILERS_ASSERT(x.base.type == asrType::type_stmt) + switch (x.type) { + case type_stmtType::TypeStmtName: { v.visit_TypeStmtName((const TypeStmtName_t &)x); return; } + case type_stmtType::ClassStmt: { v.visit_ClassStmt((const ClassStmt_t &)x); return; } + case type_stmtType::TypeStmtType: { v.visit_TypeStmtType((const TypeStmtType_t &)x); return; } + } +} + +template +static void visit_require_instantiation_t(const require_instantiation_t &x, Visitor &v) { + LCOMPILERS_ASSERT(x.base.type == asrType::require_instantiation) + switch (x.type) { + case require_instantiationType::Require: { v.visit_Require((const Require_t &)x); return; } + } +} + + + +template +static void visit_asr_t(const asr_t &x, Visitor &v) { + switch (x.type) { + case asrType::unit: { v.visit_unit((const unit_t &)x); return; } + case asrType::symbol: { v.visit_symbol((const symbol_t &)x); return; } + case asrType::stmt: { v.visit_stmt((const stmt_t &)x); return; } + case asrType::expr: { v.visit_expr((const expr_t &)x); return; } + case asrType::ttype: { v.visit_ttype((const ttype_t &)x); return; } + case asrType::attribute: { v.visit_attribute((const attribute_t &)x); return; } + case asrType::tbind: { v.visit_tbind((const tbind_t &)x); return; } + case asrType::case_stmt: { v.visit_case_stmt((const case_stmt_t &)x); return; } + case asrType::type_stmt: { v.visit_type_stmt((const type_stmt_t &)x); return; } + case asrType::require_instantiation: { v.visit_require_instantiation((const require_instantiation_t &)x); return; } + } +} + + + +/******************************************************************************/ +// Visitor base class + +template +class BaseVisitor +{ +private: + StructType& self() { return static_cast(*this); } +public: + void visit_asr(const asr_t &b) { visit_asr_t(b, self()); } + void visit_unit(const unit_t &b) { visit_unit_t(b, self()); } + void visit_TranslationUnit(const TranslationUnit_t & /* x */) { throw LCompilersException("visit_TranslationUnit() not implemented"); } + void visit_symbol(const symbol_t &b) { visit_symbol_t(b, self()); } + void visit_Program(const Program_t & /* x */) { throw LCompilersException("visit_Program() not implemented"); } + void visit_Module(const Module_t & /* x */) { throw LCompilersException("visit_Module() not implemented"); } + void visit_Function(const Function_t & /* x */) { throw LCompilersException("visit_Function() not implemented"); } + void visit_GenericProcedure(const GenericProcedure_t & /* x */) { throw LCompilersException("visit_GenericProcedure() not implemented"); } + void visit_CustomOperator(const CustomOperator_t & /* x */) { throw LCompilersException("visit_CustomOperator() not implemented"); } + void visit_ExternalSymbol(const ExternalSymbol_t & /* x */) { throw LCompilersException("visit_ExternalSymbol() not implemented"); } + void visit_Struct(const Struct_t & /* x */) { throw LCompilersException("visit_Struct() not implemented"); } + void visit_Enum(const Enum_t & /* x */) { throw LCompilersException("visit_Enum() not implemented"); } + void visit_Union(const Union_t & /* x */) { throw LCompilersException("visit_Union() not implemented"); } + void visit_Variable(const Variable_t & /* x */) { throw LCompilersException("visit_Variable() not implemented"); } + void visit_Class(const Class_t & /* x */) { throw LCompilersException("visit_Class() not implemented"); } + void visit_ClassProcedure(const ClassProcedure_t & /* x */) { throw LCompilersException("visit_ClassProcedure() not implemented"); } + void visit_AssociateBlock(const AssociateBlock_t & /* x */) { throw LCompilersException("visit_AssociateBlock() not implemented"); } + void visit_Block(const Block_t & /* x */) { throw LCompilersException("visit_Block() not implemented"); } + void visit_Requirement(const Requirement_t & /* x */) { throw LCompilersException("visit_Requirement() not implemented"); } + void visit_Template(const Template_t & /* x */) { throw LCompilersException("visit_Template() not implemented"); } + void visit_stmt(const stmt_t &b) { visit_stmt_t(b, self()); } + void visit_Allocate(const Allocate_t & /* x */) { throw LCompilersException("visit_Allocate() not implemented"); } + void visit_ReAlloc(const ReAlloc_t & /* x */) { throw LCompilersException("visit_ReAlloc() not implemented"); } + void visit_Assign(const Assign_t & /* x */) { throw LCompilersException("visit_Assign() not implemented"); } + void visit_Assignment(const Assignment_t & /* x */) { throw LCompilersException("visit_Assignment() not implemented"); } + void visit_Associate(const Associate_t & /* x */) { throw LCompilersException("visit_Associate() not implemented"); } + void visit_Cycle(const Cycle_t & /* x */) { throw LCompilersException("visit_Cycle() not implemented"); } + void visit_ExplicitDeallocate(const ExplicitDeallocate_t & /* x */) { throw LCompilersException("visit_ExplicitDeallocate() not implemented"); } + void visit_ImplicitDeallocate(const ImplicitDeallocate_t & /* x */) { throw LCompilersException("visit_ImplicitDeallocate() not implemented"); } + void visit_DoConcurrentLoop(const DoConcurrentLoop_t & /* x */) { throw LCompilersException("visit_DoConcurrentLoop() not implemented"); } + void visit_DoLoop(const DoLoop_t & /* x */) { throw LCompilersException("visit_DoLoop() not implemented"); } + void visit_ErrorStop(const ErrorStop_t & /* x */) { throw LCompilersException("visit_ErrorStop() not implemented"); } + void visit_Exit(const Exit_t & /* x */) { throw LCompilersException("visit_Exit() not implemented"); } + void visit_ForAllSingle(const ForAllSingle_t & /* x */) { throw LCompilersException("visit_ForAllSingle() not implemented"); } + void visit_ForEach(const ForEach_t & /* x */) { throw LCompilersException("visit_ForEach() not implemented"); } + void visit_GoTo(const GoTo_t & /* x */) { throw LCompilersException("visit_GoTo() not implemented"); } + void visit_GoToTarget(const GoToTarget_t & /* x */) { throw LCompilersException("visit_GoToTarget() not implemented"); } + void visit_If(const If_t & /* x */) { throw LCompilersException("visit_If() not implemented"); } + void visit_IfArithmetic(const IfArithmetic_t & /* x */) { throw LCompilersException("visit_IfArithmetic() not implemented"); } + void visit_Print(const Print_t & /* x */) { throw LCompilersException("visit_Print() not implemented"); } + void visit_FileOpen(const FileOpen_t & /* x */) { throw LCompilersException("visit_FileOpen() not implemented"); } + void visit_FileClose(const FileClose_t & /* x */) { throw LCompilersException("visit_FileClose() not implemented"); } + void visit_FileRead(const FileRead_t & /* x */) { throw LCompilersException("visit_FileRead() not implemented"); } + void visit_FileBackspace(const FileBackspace_t & /* x */) { throw LCompilersException("visit_FileBackspace() not implemented"); } + void visit_FileRewind(const FileRewind_t & /* x */) { throw LCompilersException("visit_FileRewind() not implemented"); } + void visit_FileInquire(const FileInquire_t & /* x */) { throw LCompilersException("visit_FileInquire() not implemented"); } + void visit_FileWrite(const FileWrite_t & /* x */) { throw LCompilersException("visit_FileWrite() not implemented"); } + void visit_Return(const Return_t & /* x */) { throw LCompilersException("visit_Return() not implemented"); } + void visit_Select(const Select_t & /* x */) { throw LCompilersException("visit_Select() not implemented"); } + void visit_Stop(const Stop_t & /* x */) { throw LCompilersException("visit_Stop() not implemented"); } + void visit_Assert(const Assert_t & /* x */) { throw LCompilersException("visit_Assert() not implemented"); } + void visit_SubroutineCall(const SubroutineCall_t & /* x */) { throw LCompilersException("visit_SubroutineCall() not implemented"); } + void visit_IntrinsicImpureSubroutine(const IntrinsicImpureSubroutine_t & /* x */) { throw LCompilersException("visit_IntrinsicImpureSubroutine() not implemented"); } + void visit_Where(const Where_t & /* x */) { throw LCompilersException("visit_Where() not implemented"); } + void visit_WhileLoop(const WhileLoop_t & /* x */) { throw LCompilersException("visit_WhileLoop() not implemented"); } + void visit_Nullify(const Nullify_t & /* x */) { throw LCompilersException("visit_Nullify() not implemented"); } + void visit_Flush(const Flush_t & /* x */) { throw LCompilersException("visit_Flush() not implemented"); } + void visit_ListAppend(const ListAppend_t & /* x */) { throw LCompilersException("visit_ListAppend() not implemented"); } + void visit_AssociateBlockCall(const AssociateBlockCall_t & /* x */) { throw LCompilersException("visit_AssociateBlockCall() not implemented"); } + void visit_SelectType(const SelectType_t & /* x */) { throw LCompilersException("visit_SelectType() not implemented"); } + void visit_CPtrToPointer(const CPtrToPointer_t & /* x */) { throw LCompilersException("visit_CPtrToPointer() not implemented"); } + void visit_BlockCall(const BlockCall_t & /* x */) { throw LCompilersException("visit_BlockCall() not implemented"); } + void visit_SetInsert(const SetInsert_t & /* x */) { throw LCompilersException("visit_SetInsert() not implemented"); } + void visit_SetRemove(const SetRemove_t & /* x */) { throw LCompilersException("visit_SetRemove() not implemented"); } + void visit_SetDiscard(const SetDiscard_t & /* x */) { throw LCompilersException("visit_SetDiscard() not implemented"); } + void visit_ListInsert(const ListInsert_t & /* x */) { throw LCompilersException("visit_ListInsert() not implemented"); } + void visit_ListRemove(const ListRemove_t & /* x */) { throw LCompilersException("visit_ListRemove() not implemented"); } + void visit_ListClear(const ListClear_t & /* x */) { throw LCompilersException("visit_ListClear() not implemented"); } + void visit_DictInsert(const DictInsert_t & /* x */) { throw LCompilersException("visit_DictInsert() not implemented"); } + void visit_DictClear(const DictClear_t & /* x */) { throw LCompilersException("visit_DictClear() not implemented"); } + void visit_SetClear(const SetClear_t & /* x */) { throw LCompilersException("visit_SetClear() not implemented"); } + void visit_Expr(const Expr_t & /* x */) { throw LCompilersException("visit_Expr() not implemented"); } + void visit_expr(const expr_t &b) { visit_expr_t(b, self()); } + void visit_IfExp(const IfExp_t & /* x */) { throw LCompilersException("visit_IfExp() not implemented"); } + void visit_ComplexConstructor(const ComplexConstructor_t & /* x */) { throw LCompilersException("visit_ComplexConstructor() not implemented"); } + void visit_NamedExpr(const NamedExpr_t & /* x */) { throw LCompilersException("visit_NamedExpr() not implemented"); } + void visit_FunctionCall(const FunctionCall_t & /* x */) { throw LCompilersException("visit_FunctionCall() not implemented"); } + void visit_IntrinsicElementalFunction(const IntrinsicElementalFunction_t & /* x */) { throw LCompilersException("visit_IntrinsicElementalFunction() not implemented"); } + void visit_IntrinsicArrayFunction(const IntrinsicArrayFunction_t & /* x */) { throw LCompilersException("visit_IntrinsicArrayFunction() not implemented"); } + void visit_IntrinsicImpureFunction(const IntrinsicImpureFunction_t & /* x */) { throw LCompilersException("visit_IntrinsicImpureFunction() not implemented"); } + void visit_TypeInquiry(const TypeInquiry_t & /* x */) { throw LCompilersException("visit_TypeInquiry() not implemented"); } + void visit_StructConstructor(const StructConstructor_t & /* x */) { throw LCompilersException("visit_StructConstructor() not implemented"); } + void visit_StructConstant(const StructConstant_t & /* x */) { throw LCompilersException("visit_StructConstant() not implemented"); } + void visit_EnumConstructor(const EnumConstructor_t & /* x */) { throw LCompilersException("visit_EnumConstructor() not implemented"); } + void visit_UnionConstructor(const UnionConstructor_t & /* x */) { throw LCompilersException("visit_UnionConstructor() not implemented"); } + void visit_ImpliedDoLoop(const ImpliedDoLoop_t & /* x */) { throw LCompilersException("visit_ImpliedDoLoop() not implemented"); } + void visit_IntegerConstant(const IntegerConstant_t & /* x */) { throw LCompilersException("visit_IntegerConstant() not implemented"); } + void visit_IntegerBitNot(const IntegerBitNot_t & /* x */) { throw LCompilersException("visit_IntegerBitNot() not implemented"); } + void visit_IntegerUnaryMinus(const IntegerUnaryMinus_t & /* x */) { throw LCompilersException("visit_IntegerUnaryMinus() not implemented"); } + void visit_IntegerCompare(const IntegerCompare_t & /* x */) { throw LCompilersException("visit_IntegerCompare() not implemented"); } + void visit_IntegerBinOp(const IntegerBinOp_t & /* x */) { throw LCompilersException("visit_IntegerBinOp() not implemented"); } + void visit_UnsignedIntegerConstant(const UnsignedIntegerConstant_t & /* x */) { throw LCompilersException("visit_UnsignedIntegerConstant() not implemented"); } + void visit_UnsignedIntegerUnaryMinus(const UnsignedIntegerUnaryMinus_t & /* x */) { throw LCompilersException("visit_UnsignedIntegerUnaryMinus() not implemented"); } + void visit_UnsignedIntegerBitNot(const UnsignedIntegerBitNot_t & /* x */) { throw LCompilersException("visit_UnsignedIntegerBitNot() not implemented"); } + void visit_UnsignedIntegerCompare(const UnsignedIntegerCompare_t & /* x */) { throw LCompilersException("visit_UnsignedIntegerCompare() not implemented"); } + void visit_UnsignedIntegerBinOp(const UnsignedIntegerBinOp_t & /* x */) { throw LCompilersException("visit_UnsignedIntegerBinOp() not implemented"); } + void visit_RealConstant(const RealConstant_t & /* x */) { throw LCompilersException("visit_RealConstant() not implemented"); } + void visit_RealUnaryMinus(const RealUnaryMinus_t & /* x */) { throw LCompilersException("visit_RealUnaryMinus() not implemented"); } + void visit_RealCompare(const RealCompare_t & /* x */) { throw LCompilersException("visit_RealCompare() not implemented"); } + void visit_RealBinOp(const RealBinOp_t & /* x */) { throw LCompilersException("visit_RealBinOp() not implemented"); } + void visit_RealCopySign(const RealCopySign_t & /* x */) { throw LCompilersException("visit_RealCopySign() not implemented"); } + void visit_ComplexConstant(const ComplexConstant_t & /* x */) { throw LCompilersException("visit_ComplexConstant() not implemented"); } + void visit_ComplexUnaryMinus(const ComplexUnaryMinus_t & /* x */) { throw LCompilersException("visit_ComplexUnaryMinus() not implemented"); } + void visit_ComplexCompare(const ComplexCompare_t & /* x */) { throw LCompilersException("visit_ComplexCompare() not implemented"); } + void visit_ComplexBinOp(const ComplexBinOp_t & /* x */) { throw LCompilersException("visit_ComplexBinOp() not implemented"); } + void visit_LogicalConstant(const LogicalConstant_t & /* x */) { throw LCompilersException("visit_LogicalConstant() not implemented"); } + void visit_LogicalNot(const LogicalNot_t & /* x */) { throw LCompilersException("visit_LogicalNot() not implemented"); } + void visit_LogicalCompare(const LogicalCompare_t & /* x */) { throw LCompilersException("visit_LogicalCompare() not implemented"); } + void visit_LogicalBinOp(const LogicalBinOp_t & /* x */) { throw LCompilersException("visit_LogicalBinOp() not implemented"); } + void visit_ListConstant(const ListConstant_t & /* x */) { throw LCompilersException("visit_ListConstant() not implemented"); } + void visit_ListLen(const ListLen_t & /* x */) { throw LCompilersException("visit_ListLen() not implemented"); } + void visit_ListConcat(const ListConcat_t & /* x */) { throw LCompilersException("visit_ListConcat() not implemented"); } + void visit_ListCompare(const ListCompare_t & /* x */) { throw LCompilersException("visit_ListCompare() not implemented"); } + void visit_ListCount(const ListCount_t & /* x */) { throw LCompilersException("visit_ListCount() not implemented"); } + void visit_ListContains(const ListContains_t & /* x */) { throw LCompilersException("visit_ListContains() not implemented"); } + void visit_SetConstant(const SetConstant_t & /* x */) { throw LCompilersException("visit_SetConstant() not implemented"); } + void visit_SetLen(const SetLen_t & /* x */) { throw LCompilersException("visit_SetLen() not implemented"); } + void visit_TupleConstant(const TupleConstant_t & /* x */) { throw LCompilersException("visit_TupleConstant() not implemented"); } + void visit_TupleLen(const TupleLen_t & /* x */) { throw LCompilersException("visit_TupleLen() not implemented"); } + void visit_TupleCompare(const TupleCompare_t & /* x */) { throw LCompilersException("visit_TupleCompare() not implemented"); } + void visit_TupleConcat(const TupleConcat_t & /* x */) { throw LCompilersException("visit_TupleConcat() not implemented"); } + void visit_TupleContains(const TupleContains_t & /* x */) { throw LCompilersException("visit_TupleContains() not implemented"); } + void visit_StringConstant(const StringConstant_t & /* x */) { throw LCompilersException("visit_StringConstant() not implemented"); } + void visit_StringConcat(const StringConcat_t & /* x */) { throw LCompilersException("visit_StringConcat() not implemented"); } + void visit_StringRepeat(const StringRepeat_t & /* x */) { throw LCompilersException("visit_StringRepeat() not implemented"); } + void visit_StringLen(const StringLen_t & /* x */) { throw LCompilersException("visit_StringLen() not implemented"); } + void visit_StringItem(const StringItem_t & /* x */) { throw LCompilersException("visit_StringItem() not implemented"); } + void visit_StringSection(const StringSection_t & /* x */) { throw LCompilersException("visit_StringSection() not implemented"); } + void visit_StringCompare(const StringCompare_t & /* x */) { throw LCompilersException("visit_StringCompare() not implemented"); } + void visit_StringContains(const StringContains_t & /* x */) { throw LCompilersException("visit_StringContains() not implemented"); } + void visit_StringOrd(const StringOrd_t & /* x */) { throw LCompilersException("visit_StringOrd() not implemented"); } + void visit_StringChr(const StringChr_t & /* x */) { throw LCompilersException("visit_StringChr() not implemented"); } + void visit_StringFormat(const StringFormat_t & /* x */) { throw LCompilersException("visit_StringFormat() not implemented"); } + void visit_StringPhysicalCast(const StringPhysicalCast_t & /* x */) { throw LCompilersException("visit_StringPhysicalCast() not implemented"); } + void visit_CPtrCompare(const CPtrCompare_t & /* x */) { throw LCompilersException("visit_CPtrCompare() not implemented"); } + void visit_SymbolicCompare(const SymbolicCompare_t & /* x */) { throw LCompilersException("visit_SymbolicCompare() not implemented"); } + void visit_DictConstant(const DictConstant_t & /* x */) { throw LCompilersException("visit_DictConstant() not implemented"); } + void visit_DictLen(const DictLen_t & /* x */) { throw LCompilersException("visit_DictLen() not implemented"); } + void visit_Var(const Var_t & /* x */) { throw LCompilersException("visit_Var() not implemented"); } + void visit_FunctionParam(const FunctionParam_t & /* x */) { throw LCompilersException("visit_FunctionParam() not implemented"); } + void visit_ArrayConstructor(const ArrayConstructor_t & /* x */) { throw LCompilersException("visit_ArrayConstructor() not implemented"); } + void visit_ArrayConstant(const ArrayConstant_t & /* x */) { throw LCompilersException("visit_ArrayConstant() not implemented"); } + void visit_ArrayItem(const ArrayItem_t & /* x */) { throw LCompilersException("visit_ArrayItem() not implemented"); } + void visit_ArraySection(const ArraySection_t & /* x */) { throw LCompilersException("visit_ArraySection() not implemented"); } + void visit_ArraySize(const ArraySize_t & /* x */) { throw LCompilersException("visit_ArraySize() not implemented"); } + void visit_ArrayBound(const ArrayBound_t & /* x */) { throw LCompilersException("visit_ArrayBound() not implemented"); } + void visit_ArrayTranspose(const ArrayTranspose_t & /* x */) { throw LCompilersException("visit_ArrayTranspose() not implemented"); } + void visit_ArrayPack(const ArrayPack_t & /* x */) { throw LCompilersException("visit_ArrayPack() not implemented"); } + void visit_ArrayReshape(const ArrayReshape_t & /* x */) { throw LCompilersException("visit_ArrayReshape() not implemented"); } + void visit_ArrayAll(const ArrayAll_t & /* x */) { throw LCompilersException("visit_ArrayAll() not implemented"); } + void visit_ArrayBroadcast(const ArrayBroadcast_t & /* x */) { throw LCompilersException("visit_ArrayBroadcast() not implemented"); } + void visit_BitCast(const BitCast_t & /* x */) { throw LCompilersException("visit_BitCast() not implemented"); } + void visit_StructInstanceMember(const StructInstanceMember_t & /* x */) { throw LCompilersException("visit_StructInstanceMember() not implemented"); } + void visit_StructStaticMember(const StructStaticMember_t & /* x */) { throw LCompilersException("visit_StructStaticMember() not implemented"); } + void visit_EnumStaticMember(const EnumStaticMember_t & /* x */) { throw LCompilersException("visit_EnumStaticMember() not implemented"); } + void visit_UnionInstanceMember(const UnionInstanceMember_t & /* x */) { throw LCompilersException("visit_UnionInstanceMember() not implemented"); } + void visit_EnumName(const EnumName_t & /* x */) { throw LCompilersException("visit_EnumName() not implemented"); } + void visit_EnumValue(const EnumValue_t & /* x */) { throw LCompilersException("visit_EnumValue() not implemented"); } + void visit_OverloadedCompare(const OverloadedCompare_t & /* x */) { throw LCompilersException("visit_OverloadedCompare() not implemented"); } + void visit_OverloadedBinOp(const OverloadedBinOp_t & /* x */) { throw LCompilersException("visit_OverloadedBinOp() not implemented"); } + void visit_OverloadedUnaryMinus(const OverloadedUnaryMinus_t & /* x */) { throw LCompilersException("visit_OverloadedUnaryMinus() not implemented"); } + void visit_OverloadedStringConcat(const OverloadedStringConcat_t & /* x */) { throw LCompilersException("visit_OverloadedStringConcat() not implemented"); } + void visit_Cast(const Cast_t & /* x */) { throw LCompilersException("visit_Cast() not implemented"); } + void visit_ArrayPhysicalCast(const ArrayPhysicalCast_t & /* x */) { throw LCompilersException("visit_ArrayPhysicalCast() not implemented"); } + void visit_ComplexRe(const ComplexRe_t & /* x */) { throw LCompilersException("visit_ComplexRe() not implemented"); } + void visit_ComplexIm(const ComplexIm_t & /* x */) { throw LCompilersException("visit_ComplexIm() not implemented"); } + void visit_DictItem(const DictItem_t & /* x */) { throw LCompilersException("visit_DictItem() not implemented"); } + void visit_CLoc(const CLoc_t & /* x */) { throw LCompilersException("visit_CLoc() not implemented"); } + void visit_PointerToCPtr(const PointerToCPtr_t & /* x */) { throw LCompilersException("visit_PointerToCPtr() not implemented"); } + void visit_GetPointer(const GetPointer_t & /* x */) { throw LCompilersException("visit_GetPointer() not implemented"); } + void visit_ListItem(const ListItem_t & /* x */) { throw LCompilersException("visit_ListItem() not implemented"); } + void visit_TupleItem(const TupleItem_t & /* x */) { throw LCompilersException("visit_TupleItem() not implemented"); } + void visit_ListSection(const ListSection_t & /* x */) { throw LCompilersException("visit_ListSection() not implemented"); } + void visit_ListRepeat(const ListRepeat_t & /* x */) { throw LCompilersException("visit_ListRepeat() not implemented"); } + void visit_DictPop(const DictPop_t & /* x */) { throw LCompilersException("visit_DictPop() not implemented"); } + void visit_SetPop(const SetPop_t & /* x */) { throw LCompilersException("visit_SetPop() not implemented"); } + void visit_SetContains(const SetContains_t & /* x */) { throw LCompilersException("visit_SetContains() not implemented"); } + void visit_DictContains(const DictContains_t & /* x */) { throw LCompilersException("visit_DictContains() not implemented"); } + void visit_IntegerBitLen(const IntegerBitLen_t & /* x */) { throw LCompilersException("visit_IntegerBitLen() not implemented"); } + void visit_Ichar(const Ichar_t & /* x */) { throw LCompilersException("visit_Ichar() not implemented"); } + void visit_Iachar(const Iachar_t & /* x */) { throw LCompilersException("visit_Iachar() not implemented"); } + void visit_SizeOfType(const SizeOfType_t & /* x */) { throw LCompilersException("visit_SizeOfType() not implemented"); } + void visit_PointerNullConstant(const PointerNullConstant_t & /* x */) { throw LCompilersException("visit_PointerNullConstant() not implemented"); } + void visit_PointerAssociated(const PointerAssociated_t & /* x */) { throw LCompilersException("visit_PointerAssociated() not implemented"); } + void visit_RealSqrt(const RealSqrt_t & /* x */) { throw LCompilersException("visit_RealSqrt() not implemented"); } + void visit_ArrayIsContiguous(const ArrayIsContiguous_t & /* x */) { throw LCompilersException("visit_ArrayIsContiguous() not implemented"); } + void visit_ttype(const ttype_t &b) { visit_ttype_t(b, self()); } + void visit_Integer(const Integer_t & /* x */) { throw LCompilersException("visit_Integer() not implemented"); } + void visit_UnsignedInteger(const UnsignedInteger_t & /* x */) { throw LCompilersException("visit_UnsignedInteger() not implemented"); } + void visit_Real(const Real_t & /* x */) { throw LCompilersException("visit_Real() not implemented"); } + void visit_Complex(const Complex_t & /* x */) { throw LCompilersException("visit_Complex() not implemented"); } + void visit_String(const String_t & /* x */) { throw LCompilersException("visit_String() not implemented"); } + void visit_Logical(const Logical_t & /* x */) { throw LCompilersException("visit_Logical() not implemented"); } + void visit_Set(const Set_t & /* x */) { throw LCompilersException("visit_Set() not implemented"); } + void visit_List(const List_t & /* x */) { throw LCompilersException("visit_List() not implemented"); } + void visit_Tuple(const Tuple_t & /* x */) { throw LCompilersException("visit_Tuple() not implemented"); } + void visit_StructType(const StructType_t & /* x */) { throw LCompilersException("visit_StructType() not implemented"); } + void visit_EnumType(const EnumType_t & /* x */) { throw LCompilersException("visit_EnumType() not implemented"); } + void visit_UnionType(const UnionType_t & /* x */) { throw LCompilersException("visit_UnionType() not implemented"); } + void visit_ClassType(const ClassType_t & /* x */) { throw LCompilersException("visit_ClassType() not implemented"); } + void visit_Dict(const Dict_t & /* x */) { throw LCompilersException("visit_Dict() not implemented"); } + void visit_Pointer(const Pointer_t & /* x */) { throw LCompilersException("visit_Pointer() not implemented"); } + void visit_Allocatable(const Allocatable_t & /* x */) { throw LCompilersException("visit_Allocatable() not implemented"); } + void visit_CPtr(const CPtr_t & /* x */) { throw LCompilersException("visit_CPtr() not implemented"); } + void visit_SymbolicExpression(const SymbolicExpression_t & /* x */) { throw LCompilersException("visit_SymbolicExpression() not implemented"); } + void visit_TypeParameter(const TypeParameter_t & /* x */) { throw LCompilersException("visit_TypeParameter() not implemented"); } + void visit_Array(const Array_t & /* x */) { throw LCompilersException("visit_Array() not implemented"); } + void visit_FunctionType(const FunctionType_t & /* x */) { throw LCompilersException("visit_FunctionType() not implemented"); } + void visit_attribute(const attribute_t &b) { visit_attribute_t(b, self()); } + void visit_Attribute(const Attribute_t & /* x */) { throw LCompilersException("visit_Attribute() not implemented"); } + void visit_tbind(const tbind_t &b) { visit_tbind_t(b, self()); } + void visit_Bind(const Bind_t & /* x */) { throw LCompilersException("visit_Bind() not implemented"); } + void visit_case_stmt(const case_stmt_t &b) { visit_case_stmt_t(b, self()); } + void visit_CaseStmt(const CaseStmt_t & /* x */) { throw LCompilersException("visit_CaseStmt() not implemented"); } + void visit_CaseStmt_Range(const CaseStmt_Range_t & /* x */) { throw LCompilersException("visit_CaseStmt_Range() not implemented"); } + void visit_type_stmt(const type_stmt_t &b) { visit_type_stmt_t(b, self()); } + void visit_TypeStmtName(const TypeStmtName_t & /* x */) { throw LCompilersException("visit_TypeStmtName() not implemented"); } + void visit_ClassStmt(const ClassStmt_t & /* x */) { throw LCompilersException("visit_ClassStmt() not implemented"); } + void visit_TypeStmtType(const TypeStmtType_t & /* x */) { throw LCompilersException("visit_TypeStmtType() not implemented"); } + void visit_require_instantiation(const require_instantiation_t &b) { visit_require_instantiation_t(b, self()); } + void visit_Require(const Require_t & /* x */) { throw LCompilersException("visit_Require() not implemented"); } +}; + + +} diff --git a/src/libasr/asr_builder.h b/src/libasr/asr_builder.h index 0e4073381b..a866bd8549 100644 --- a/src/libasr/asr_builder.h +++ b/src/libasr/asr_builder.h @@ -39,13 +39,35 @@ class ASRBuilder { ASR::ttype_t *type, ASR::intentType intent, ASR::abiType abi=ASR::abiType::Source, bool a_value_attr=false) { ASR::symbol_t* sym = ASR::down_cast( - ASR::make_Variable_t(al, loc, symtab, s2c(al, var_name), nullptr, 0, + ASRUtils::make_Variable_t_util(al, loc, symtab, s2c(al, var_name), nullptr, 0, intent, nullptr, nullptr, ASR::storage_typeType::Default, type, nullptr, abi, ASR::Public, ASR::presenceType::Required, a_value_attr)); symtab->add_symbol(s2c(al, var_name), sym); return ASRUtils::EXPR(ASR::make_Var_t(al, loc, sym)); } + void VariableDeclaration(SymbolTable *symtab, std::string var_name, + ASR::ttype_t *type, ASR::intentType intent, + ASR::abiType abi=ASR::abiType::Source, bool a_value_attr=false) { + ASR::symbol_t* sym = ASR::down_cast( + ASRUtils::make_Variable_t_util(al, loc, symtab, s2c(al, var_name), nullptr, 0, + intent, nullptr, nullptr, ASR::storage_typeType::Default, type, nullptr, abi, + ASR::Public, ASR::presenceType::Required, a_value_attr)); + symtab->add_symbol(s2c(al, var_name), sym); + return; + } + + ASR::expr_t *VariableOverwrite(SymbolTable *symtab, std::string var_name, + ASR::ttype_t *type, ASR::intentType intent, + ASR::abiType abi=ASR::abiType::Source, bool a_value_attr=false) { + ASR::symbol_t* sym = ASR::down_cast( + ASRUtils::make_Variable_t_util(al, loc, symtab, s2c(al, var_name), nullptr, 0, + intent, nullptr, nullptr, ASR::storage_typeType::Default, type, nullptr, abi, + ASR::Public, ASR::presenceType::Required, a_value_attr)); + symtab->add_or_overwrite_symbol(s2c(al, var_name), sym); + return ASRUtils::EXPR(ASR::make_Var_t(al, loc, sym)); + } + #define declare(var_name, type, intent) \ b.Variable(fn_symtab, var_name, type, ASR::intentType::intent) @@ -74,16 +96,17 @@ class ASRBuilder { false, nullptr, 0, false, false, false)); // Types ------------------------------------------------------------------- - #define int8 TYPE(ASR::make_Integer_t(al, loc, 1)) - #define int16 TYPE(ASR::make_Integer_t(al, loc, 2)) - #define int32 TYPE(ASR::make_Integer_t(al, loc, 4)) - #define int64 TYPE(ASR::make_Integer_t(al, loc, 8)) - #define real32 TYPE(ASR::make_Real_t(al, loc, 4)) - #define real64 TYPE(ASR::make_Real_t(al, loc, 8)) - #define complex32 TYPE(ASR::make_Complex_t(al, loc, 4)) - #define logical TYPE(ASR::make_Logical_t(al, loc, 4)) - #define character(x) TYPE(ASR::make_Character_t(al, loc, 1, x, nullptr)) - #define List(x) TYPE(ASR::make_List_t(al, loc, x)) + #define int8 ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 1)) + #define int16 ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 2)) + #define int32 ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)) + #define int64 ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 8)) + #define real32 ASRUtils::TYPE(ASR::make_Real_t(al, loc, 4)) + #define real64 ASRUtils::TYPE(ASR::make_Real_t(al, loc, 8)) + #define complex32 ASRUtils::TYPE(ASR::make_Complex_t(al, loc, 4)) + #define complex64 ASRUtils::TYPE(ASR::make_Complex_t(al, loc, 8)) + #define logical ASRUtils::TYPE(ASR::make_Logical_t(al, loc, 4)) + #define character(x) ASRUtils::TYPE(ASR::make_String_t(al, loc, 1, x, nullptr, ASR::string_physical_typeType::PointerString)) + #define List(x) ASRUtils::TYPE(ASR::make_List_t(al, loc, x)) ASR::ttype_t *Tuple(std::vector tuple_type) { Vec m_tuple_type; m_tuple_type.reserve(al, 3); @@ -92,6 +115,7 @@ class ASRBuilder { } return TYPE(ASR::make_Tuple_t(al, loc, m_tuple_type.p, m_tuple_type.n)); } + ASR::ttype_t *Array(std::vector dims, ASR::ttype_t *type) { Vec m_dims; m_dims.reserve(al, 1); for (auto &x: dims) { @@ -109,11 +133,77 @@ class ASRBuilder { return make_Array_t_util(al, loc, type, m_dims.p, m_dims.n); } + ASR::ttype_t* CPtr() { + return TYPE(ASR::make_CPtr_t(al, loc)); + } + // Expressions ------------------------------------------------------------- - inline ASR::expr_t* i(int64_t x, ASR::ttype_t* t) { + ASR::expr_t* Var(ASR::symbol_t* sym) { + return ASRUtils::EXPR(ASR::make_Var_t(al, loc, sym)); + } + + ASR::expr_t* ArrayUBound(ASR::expr_t* x, int64_t dim) { + ASR::expr_t* value = nullptr; + ASR::ttype_t* type = ASRUtils::expr_type(x); + if ( ASRUtils::is_array(type) ) { + ASR::Array_t* array_type = ASR::down_cast(ASRUtils::type_get_past_pointer(ASRUtils::type_get_past_allocatable(type))); + ASR::dimension_t* dims = array_type->m_dims; + ASRUtils::extract_dimensions_from_ttype(type, dims); + int new_dim = dim - 1; + if( dims[new_dim].m_start && dims[new_dim].m_length ) { + ASR::expr_t* start = ASRUtils::expr_value(dims[new_dim].m_start); + ASR::expr_t* length = ASRUtils::expr_value(dims[new_dim].m_length); + if( ASRUtils::is_value_constant(start) && + ASRUtils::is_value_constant(length) ) { + int64_t const_lbound = -1; + if( !ASRUtils::extract_value(start, const_lbound) ) { + LCOMPILERS_ASSERT(false); + } + int64_t const_length = -1; + if( !ASRUtils::extract_value(length, const_length) ) { + LCOMPILERS_ASSERT(false); + } + value = i32(const_lbound + const_length - 1); + } + } + } + return ASRUtils::EXPR(ASR::make_ArrayBound_t(al, loc, x, i32(dim), int32, ASR::arrayboundType::UBound, value)); + } + + ASR::expr_t* ArrayLBound(ASR::expr_t* x, int64_t dim) { + ASR::expr_t* value = nullptr; + ASR::ttype_t* type = ASRUtils::expr_type(x); + if ( ASRUtils::is_array(type) ) { + ASR::Array_t* array_type = ASR::down_cast(ASRUtils::type_get_past_pointer(ASRUtils::type_get_past_allocatable(type))); + ASR::dimension_t* dims = array_type->m_dims; + ASRUtils::extract_dimensions_from_ttype(type, dims); + int new_dim = dim - 1; + if( dims[new_dim].m_start ) { + ASR::expr_t* start = ASRUtils::expr_value(dims[new_dim].m_start); + if( ASRUtils::is_value_constant(start) ) { + int64_t const_lbound = -1; + if( !ASRUtils::extract_value(start, const_lbound) ) { + LCOMPILERS_ASSERT(false); + } + value = i32(const_lbound); + } + } + } + return ASRUtils::EXPR(ASR::make_ArrayBound_t(al, loc, x, i32(dim), int32, ASR::arrayboundType::LBound, value)); + } + + inline ASR::expr_t* i_t(int64_t x, ASR::ttype_t* t) { return EXPR(ASR::make_IntegerConstant_t(al, loc, x, t)); } + inline ASR::expr_t* logical_true() { + return EXPR(ASR::make_LogicalConstant_t(al, loc, true, logical)); + } + + inline ASR::expr_t* logical_false() { + return EXPR(ASR::make_LogicalConstant_t(al, loc, false, logical)); + } + inline ASR::expr_t* i32(int64_t x) { return EXPR(ASR::make_IntegerConstant_t(al, loc, x, int32)); } @@ -122,15 +212,11 @@ class ASRBuilder { return EXPR(ASR::make_IntegerConstant_t(al, loc, x, int64)); } - inline ASR::expr_t* i32_n(int64_t x) { - return EXPR(ASR::make_IntegerUnaryMinus_t(al, loc, i32(abs(x)), int32, i32(x))); - } - - inline ASR::expr_t* i32_neg(ASR::expr_t* x, ASR::ttype_t* t) { + inline ASR::expr_t* i_neg(ASR::expr_t* x, ASR::ttype_t* t) { return EXPR(ASR::make_IntegerUnaryMinus_t(al, loc, x, t, nullptr)); } - inline ASR::expr_t* f(double x, ASR::ttype_t* t) { + inline ASR::expr_t* f_t(double x, ASR::ttype_t* t) { return EXPR(ASR::make_RealConstant_t(al, loc, x, t)); } @@ -138,19 +224,19 @@ class ASRBuilder { return EXPR(ASR::make_RealConstant_t(al, loc, x, real32)); } - inline ASR::expr_t* f32_neg(ASR::expr_t* x, ASR::ttype_t* t) { - return EXPR(ASR::make_RealUnaryMinus_t(al, loc, x, t, nullptr)); + inline ASR::expr_t* f64(double x) { + return EXPR(ASR::make_RealConstant_t(al, loc, x, real64)); } - inline ASR::expr_t* bool32(bool x) { - return EXPR(ASR::make_LogicalConstant_t(al, loc, x, logical)); + inline ASR::expr_t* f_neg(ASR::expr_t* x, ASR::ttype_t* t) { + return EXPR(ASR::make_RealUnaryMinus_t(al, loc, x, t, nullptr)); } inline ASR::expr_t* bool_t(bool x, ASR::ttype_t* t) { return EXPR(ASR::make_LogicalConstant_t(al, loc, x, t)); } - inline ASR::expr_t* complex(double x, double y, ASR::ttype_t* t) { + inline ASR::expr_t* complex_t(double x, double y, ASR::ttype_t* t) { return EXPR(ASR::make_ComplexConstant_t(al, loc, x, y, t)); } @@ -158,6 +244,28 @@ class ASRBuilder { return EXPR(ASR::make_ComplexConstant_t(al, loc, x, y, complex32)); } + inline ASR::expr_t* c64(double x, double y) { + return EXPR(ASR::make_ComplexConstant_t(al, loc, x, y, complex64)); + } + + inline ASR::expr_t* constant_t(double x, ASR::ttype_t* t, double y = 0.0) { + if (ASRUtils::is_integer(*t)) { + return i_t(x, t); + } else if (ASRUtils::is_real(*t)) { + return f_t(x, t); + } else if (ASRUtils::is_complex(*t)) { + return complex_t(x, y, t); + } else if (ASRUtils::is_logical(*t)) { + if (x == 0.0) { + return bool_t(false, t); + } else { + return bool_t(true, t); + } + } else { + throw LCompilersException("Type not supported"); + } + } + inline ASR::expr_t* ListItem(ASR::expr_t* x, ASR::expr_t* pos, ASR::ttype_t* type) { return EXPR(ASR::make_ListItem_t(al, loc, x, pos, type, nullptr)); } @@ -187,7 +295,7 @@ class ASRBuilder { } inline ASR::expr_t* ArraySize(ASR::expr_t* x, ASR::expr_t* dim, ASR::ttype_t* t) { - return EXPR(ASR::make_ArraySize_t(al, loc, x, dim, t, nullptr)); + return EXPR(make_ArraySize_t_util(al, loc, x, dim, t, nullptr)); } inline ASR::expr_t* Ichar(std::string s, ASR::ttype_t* type, ASR::ttype_t* t) { @@ -195,260 +303,182 @@ class ASRBuilder { EXPR(ASR::make_StringConstant_t(al, loc, s2c(al, s), type)), t, nullptr)); } - // Cast -------------------------------------------------------------------- - - inline ASR::expr_t* r2i8(ASR::expr_t* x) { - return EXPR(ASR::make_Cast_t(al, loc, x, ASR::cast_kindType::RealToInteger, int8, nullptr)); - } - - inline ASR::expr_t* r2i16(ASR::expr_t* x) { - return EXPR(ASR::make_Cast_t(al, loc, x, ASR::cast_kindType::RealToInteger, int16, nullptr)); - } - - inline ASR::expr_t* r2i32(ASR::expr_t* x) { - return EXPR(ASR::make_Cast_t(al, loc, x, ASR::cast_kindType::RealToInteger, int32, nullptr)); - } - - inline ASR::expr_t* r2i64(ASR::expr_t* x) { - return EXPR(ASR::make_Cast_t(al, loc, x, ASR::cast_kindType::RealToInteger, int64, nullptr)); + inline ASR::expr_t* PointerToCPtr(ASR::expr_t* x, ASR::ttype_t* t) { + return EXPR(ASR::make_PointerToCPtr_t(al, loc, x, t, nullptr)); } - inline ASR::expr_t* i2r32(ASR::expr_t* x) { - return EXPR(ASR::make_Cast_t(al, loc, x, ASR::cast_kindType::IntegerToReal, real32, nullptr)); - } - - inline ASR::expr_t* i2r64(ASR::expr_t* x) { - return EXPR(ASR::make_Cast_t(al, loc, x, ASR::cast_kindType::IntegerToReal, real64, nullptr)); - } + // Cast -------------------------------------------------------------------- - inline ASR::expr_t* i2i(ASR::expr_t* x, ASR::ttype_t* t) { - return EXPR(ASR::make_Cast_t(al, loc, x, ASR::cast_kindType::IntegerToInteger, t, nullptr)); - } + #define avoid_cast(x, t) if( ASRUtils::extract_kind_from_ttype_t(t) <= \ + ASRUtils::extract_kind_from_ttype_t(ASRUtils::expr_type(x)) ) { \ + return x; \ + } \ - inline ASR::expr_t* i2i64(ASR::expr_t* x) { - return EXPR(ASR::make_Cast_t(al, loc, x, ASR::cast_kindType::IntegerToInteger, int64, nullptr)); + inline ASR::expr_t* r2i_t(ASR::expr_t* x, ASR::ttype_t* t) { + ASR::expr_t* value = ASRUtils::expr_value(x); + if ( value != nullptr ) { + double val = ASR::down_cast(value)->m_r; + value = i_t(val, t); + } + return EXPR(ASR::make_Cast_t(al, loc, x, ASR::cast_kindType::RealToInteger, t, value)); } - inline ASR::expr_t* i2i32(ASR::expr_t* x) { - return EXPR(ASR::make_Cast_t(al, loc, x, ASR::cast_kindType::IntegerToInteger, int32, nullptr)); + inline ASR::expr_t* c2i_t(ASR::expr_t* x, ASR::ttype_t* t) { + // TODO: handle value + return EXPR(ASR::make_Cast_t(al, loc, x, ASR::cast_kindType::ComplexToInteger, t, nullptr)); } - inline ASR::expr_t* r2r32(ASR::expr_t* x) { - return EXPR(ASR::make_Cast_t(al, loc, x, ASR::cast_kindType::RealToReal, real32, nullptr)); + inline ASR::expr_t* i2r_t(ASR::expr_t* x, ASR::ttype_t* t) { + ASR::expr_t* value = ASRUtils::expr_value(x); + if ( value != nullptr ) { + int64_t val = ASR::down_cast(value)->m_n; + value = f_t(val, t); + } + return EXPR(ASR::make_Cast_t(al, loc, x, ASR::cast_kindType::IntegerToReal, t, value)); } - inline ASR::expr_t* r2r64(ASR::expr_t* x) { - return EXPR(ASR::make_Cast_t(al, loc, x, ASR::cast_kindType::RealToReal, real64, nullptr)); + inline ASR::expr_t* i2i_t(ASR::expr_t* x, ASR::ttype_t* t) { + // avoid_cast(x, t); // TODO: adding this makes intrinsics_61 fail, that shall not happen, add a flag for force casting + ASR::expr_t* value = ASRUtils::expr_value(x); + if ( value != nullptr ) { + int64_t val = ASR::down_cast(value)->m_n; + value = i_t(val, t); + } + return EXPR(ASR::make_Cast_t(al, loc, x, ASR::cast_kindType::IntegerToInteger, t, value)); } - inline ASR::expr_t* r2r(ASR::expr_t* x, ASR::ttype_t* t) { - return EXPR(ASR::make_Cast_t(al, loc, x, ASR::cast_kindType::RealToReal, t, nullptr)); + inline ASR::expr_t* r2r_t(ASR::expr_t* x, ASR::ttype_t* t) { + int kind_x = ASRUtils::extract_kind_from_ttype_t(ASRUtils::expr_type(x)); + int kind_t = ASRUtils::extract_kind_from_ttype_t(t); + if (kind_x == kind_t) { + return x; + } + ASR::expr_t* value = ASRUtils::expr_value(x); + if ( value != nullptr ) { + double val = ASR::down_cast(value)->m_r; + value = f_t(val, t); + } + return EXPR(ASR::make_Cast_t(al, loc, x, ASR::cast_kindType::RealToReal, t, value)); } - inline ASR::expr_t* r2i(ASR::expr_t* x, ASR::ttype_t* t) { - return EXPR(ASR::make_Cast_t(al, loc, x, ASR::cast_kindType::RealToInteger, t, nullptr)); + inline ASR::expr_t* c2r_t(ASR::expr_t* x, ASR::ttype_t* t) { + // TODO: handle value + return EXPR(ASR::make_Cast_t(al, loc, x, ASR::cast_kindType::ComplexToReal, t, nullptr)); } - inline ASR::expr_t* i2r(ASR::expr_t* x, ASR::ttype_t* t) { - return EXPR(ASR::make_Cast_t(al, loc, x, ASR::cast_kindType::IntegerToReal, t, nullptr)); + inline ASR::expr_t* t2t(ASR::expr_t* x, ASR::ttype_t* t1, ASR::ttype_t* t2) { + // TODO: improve this function to handle all types + if (ASRUtils::is_real(*t1)) { + if (ASRUtils::is_real(*t2)) { + return r2r_t(x, t2); + } else if (ASRUtils::is_integer(*t2)) { + return r2i_t(x, t2); + } else { + throw LCompilersException("Type not supported"); + } + } else if (ASRUtils::is_integer(*t1)) { + if (ASRUtils::is_real(*t2)) { + return i2r_t(x, t2); + } else if (ASRUtils::is_integer(*t2)) { + return i2i_t(x, t2); + } else { + throw LCompilersException("Type not supported"); + } + } else if (ASRUtils::is_complex(*t1)) { + if (ASRUtils::is_real(*t2)) { + return c2r_t(x, t2); + } else if (ASRUtils::is_integer(*t2)) { + return c2i_t(x, t2); + } else { + throw LCompilersException("Type not supported"); + } + } else { + throw LCompilersException("Type not supported"); + } } // Binop ------------------------------------------------------------------- - inline ASR::expr_t* iAdd(ASR::expr_t* left, ASR::expr_t* right) { - return EXPR(ASR::make_IntegerBinOp_t(al, loc, left, ASR::binopType::Add, right, ASRUtils::int32, nullptr)); - } - - inline ASR::expr_t* i8Add(ASR::expr_t* left, ASR::expr_t* right) { - return EXPR(ASR::make_IntegerBinOp_t(al, loc, left, ASR::binopType::Add, right, ASRUtils::int8, nullptr)); - } - - inline ASR::expr_t* i16Add(ASR::expr_t* left, ASR::expr_t* right) { - return EXPR(ASR::make_IntegerBinOp_t(al, loc, left, ASR::binopType::Add, right, ASRUtils::int16, nullptr)); - } - - inline ASR::expr_t* i64Add(ASR::expr_t* left, ASR::expr_t* right) { - return EXPR(ASR::make_IntegerBinOp_t(al, loc, left, ASR::binopType::Add, right, ASRUtils::int64, nullptr)); - } - - inline ASR::expr_t* rAdd(ASR::expr_t* left, ASR::expr_t* right, ASR::ttype_t* t) { - return EXPR(ASR::make_RealBinOp_t(al, loc, left, ASR::binopType::Add, right, t, nullptr)); - } - - inline ASR::expr_t* r32Add(ASR::expr_t* left, ASR::expr_t* right) { - return EXPR(ASR::make_RealBinOp_t(al, loc, left, ASR::binopType::Add, right, ASRUtils::real32, nullptr)); - } - - inline ASR::expr_t* r64Add(ASR::expr_t* left, ASR::expr_t* right) { - return EXPR(ASR::make_RealBinOp_t(al, loc, left, ASR::binopType::Add, right, ASRUtils::real64, nullptr)); - } - - inline ASR::expr_t* i_tAdd(ASR::expr_t* left, ASR::expr_t* right, ASR::ttype_t* t) { - return EXPR(ASR::make_IntegerBinOp_t(al, loc, left, ASR::binopType::Add, right, t, nullptr)); - } - - inline ASR::expr_t* r_tAdd(ASR::expr_t* left, ASR::expr_t* right, ASR::ttype_t* t) { - return EXPR(ASR::make_RealBinOp_t(al, loc, left, ASR::binopType::Add, right, t, nullptr)); - } - - inline ASR::expr_t* iSub(ASR::expr_t* left, ASR::expr_t* right) { - return EXPR(ASR::make_IntegerBinOp_t(al, loc, left, ASR::binopType::Sub, right, ASRUtils::int32, nullptr)); - } - - inline ASR::expr_t* i_vSub(ASR::expr_t* left, ASR::expr_t* right, ASR::expr_t* value) { - return EXPR(ASR::make_IntegerBinOp_t(al, loc, left, ASR::binopType::Sub, right, ASRUtils::int32, value)); - } - - inline ASR::expr_t* i8Sub(ASR::expr_t* left, ASR::expr_t* right) { - return EXPR(ASR::make_IntegerBinOp_t(al, loc, left, ASR::binopType::Sub, right, int8, nullptr)); - } - - inline ASR::expr_t* i16Sub(ASR::expr_t* left, ASR::expr_t* right) { - return EXPR(ASR::make_IntegerBinOp_t(al, loc, left, ASR::binopType::Sub, right, int16, nullptr)); - } - - inline ASR::expr_t* i64Sub(ASR::expr_t* left, ASR::expr_t* right) { - return EXPR(ASR::make_IntegerBinOp_t(al, loc, left, ASR::binopType::Sub, right, int64, nullptr)); - } - - inline ASR::expr_t* rSub(ASR::expr_t* left, ASR::expr_t* right, ASR::ttype_t* t) { - return EXPR(ASR::make_RealBinOp_t(al, loc, left, ASR::binopType::Sub, right, t, nullptr)); - } - - inline ASR::expr_t* r32Sub(ASR::expr_t* left, ASR::expr_t* right) { - return EXPR(ASR::make_RealBinOp_t(al, loc, left, ASR::binopType::Sub, right, ASRUtils::real32, nullptr)); - } - - inline ASR::expr_t* r64Sub(ASR::expr_t* left, ASR::expr_t* right) { - return EXPR(ASR::make_RealBinOp_t(al, loc, left, ASR::binopType::Sub, right, ASRUtils::real64, nullptr)); - } - - inline ASR::expr_t* i_tSub(ASR::expr_t* left, ASR::expr_t* right, ASR::ttype_t* t) { - return EXPR(ASR::make_IntegerBinOp_t(al, loc, left, ASR::binopType::Sub, right, t, nullptr)); - } - - inline ASR::expr_t* r_tSub(ASR::expr_t* left, ASR::expr_t* right, ASR::ttype_t* t) { - return EXPR(ASR::make_RealBinOp_t(al, loc, left, ASR::binopType::Sub, right, t, nullptr)); - } - - inline ASR::expr_t* iDiv(ASR::expr_t* left, ASR::expr_t* right) { - return EXPR(ASR::make_IntegerBinOp_t(al, loc, left, ASR::binopType::Div, right, ASRUtils::int32, nullptr)); - } - - inline ASR::expr_t* i8Div(ASR::expr_t* left, ASR::expr_t* right) { - return EXPR(ASR::make_IntegerBinOp_t(al, loc, left, ASR::binopType::Div, right, ASRUtils::int8, nullptr)); - } - - inline ASR::expr_t* i16Div(ASR::expr_t* left, ASR::expr_t* right) { - return EXPR(ASR::make_IntegerBinOp_t(al, loc, left, ASR::binopType::Div, right, ASRUtils::int16, nullptr)); - } - - inline ASR::expr_t* i64Div(ASR::expr_t* left, ASR::expr_t* right) { - return EXPR(ASR::make_IntegerBinOp_t(al, loc, left, ASR::binopType::Div, right, ASRUtils::int64, nullptr)); - } - - inline ASR::expr_t* rDiv(ASR::expr_t* left, ASR::expr_t* right, ASR::ttype_t* t) { - return EXPR(ASR::make_RealBinOp_t(al, loc, left, ASR::binopType::Div, right, t, nullptr)); - } - - inline ASR::expr_t* r32Div(ASR::expr_t* left, ASR::expr_t* right) { - return EXPR(ASR::make_RealBinOp_t(al, loc, left, ASR::binopType::Div, right, ASRUtils::real32, nullptr)); - } - - inline ASR::expr_t* r64Div(ASR::expr_t* left, ASR::expr_t* right) { - return EXPR(ASR::make_RealBinOp_t(al, loc, left, ASR::binopType::Div, right, ASRUtils::real64, nullptr)); - } - - inline ASR::expr_t* i_tDiv(ASR::expr_t* left, ASR::expr_t* right, ASR::ttype_t* t) { - return EXPR(ASR::make_IntegerBinOp_t(al, loc, left, ASR::binopType::Div, right, t, nullptr)); - } - - inline ASR::expr_t* iMul(ASR::expr_t* left, ASR::expr_t* right) { - return EXPR(ASR::make_IntegerBinOp_t(al, loc, left, ASR::binopType::Mul, right, ASRUtils::int32, nullptr)); - } - - inline ASR::expr_t* i8Mul(ASR::expr_t* left, ASR::expr_t* right) { - return EXPR(ASR::make_IntegerBinOp_t(al, loc, left, ASR::binopType::Mul, right, ASRUtils::int8, nullptr)); - } - - inline ASR::expr_t* i16Mul(ASR::expr_t* left, ASR::expr_t* right) { - return EXPR(ASR::make_IntegerBinOp_t(al, loc, left, ASR::binopType::Mul, right, ASRUtils::int16, nullptr)); - } - - inline ASR::expr_t* i64Mul(ASR::expr_t* left, ASR::expr_t* right) { - return EXPR(ASR::make_IntegerBinOp_t(al, loc, left, ASR::binopType::Mul, right, ASRUtils::int64, nullptr)); - } - - inline ASR::expr_t* rMul(ASR::expr_t* left, ASR::expr_t* right, ASR::ttype_t* t) { - return EXPR(ASR::make_RealBinOp_t(al, loc, left, ASR::binopType::Mul, right, t, nullptr)); - } - - inline ASR::expr_t* r32Mul(ASR::expr_t* left, ASR::expr_t* right) { - return EXPR(ASR::make_RealBinOp_t(al, loc, left, ASR::binopType::Mul, right, ASRUtils::real32, nullptr)); - } - - inline ASR::expr_t* r64Mul(ASR::expr_t* left, ASR::expr_t* right) { - return EXPR(ASR::make_RealBinOp_t(al, loc, left, ASR::binopType::Mul, right, ASRUtils::real64, nullptr)); - } - - inline ASR::expr_t* i_tMul(ASR::expr_t* left, ASR::expr_t* right, ASR::ttype_t* t) { - return EXPR(ASR::make_IntegerBinOp_t(al, loc, left, ASR::binopType::Mul, right, t, nullptr)); - } - - inline ASR::expr_t* i_tAnd(ASR::expr_t* left, ASR::expr_t* right, ASR::ttype_t* t) { - return EXPR(ASR::make_IntegerBinOp_t(al, loc, left, ASR::binopType::BitAnd, right, t, nullptr)); - } - - inline ASR::expr_t* r_tMul(ASR::expr_t* left, ASR::expr_t* right, ASR::ttype_t* t) { - return EXPR(ASR::make_RealBinOp_t(al, loc, left, ASR::binopType::Mul, right, t, nullptr)); - } - - inline ASR::expr_t* iPow(ASR::expr_t* left, ASR::expr_t* right, ASR::ttype_t* t) { - return EXPR(ASR::make_IntegerBinOp_t(al, loc, left, ASR::binopType::Pow, right, t, nullptr)); - } - - inline ASR::expr_t* rPow(ASR::expr_t* left, ASR::expr_t* right, ASR::ttype_t* t) { - return EXPR(ASR::make_RealBinOp_t(al, loc, left, ASR::binopType::Pow, right, t, nullptr)); - } - - inline ASR::expr_t* And(ASR::expr_t* x, ASR::expr_t* y) { - return EXPR(ASR::make_LogicalBinOp_t(al, loc, x, ASR::logicalbinopType::And, y, logical, nullptr)); - } - - inline ASR::expr_t* Or(ASR::expr_t* x, ASR::expr_t* y) { - return EXPR(ASR::make_LogicalBinOp_t(al, loc, x, ASR::logicalbinopType::Or, y, logical, nullptr)); - } - - inline ASR::expr_t* Not(ASR::expr_t* x) { - return EXPR(ASR::make_LogicalNot_t(al, loc, x, logical, nullptr)); - } - - inline ASR::expr_t* i_BitRshift(ASR::expr_t* n, ASR::expr_t* bits, ASR::ttype_t* t) { + inline ASR::expr_t* BitRshift(ASR::expr_t* n, ASR::expr_t* bits, ASR::ttype_t* t) { return EXPR(ASR::make_IntegerBinOp_t(al, loc, n, ASR::binopType::BitRShift, bits, t, nullptr)); } - inline ASR::expr_t* i_BitLshift(ASR::expr_t* n, ASR::expr_t* bits, ASR::ttype_t* t) { + inline ASR::expr_t* BitLshift(ASR::expr_t* n, ASR::expr_t* bits, ASR::ttype_t* t) { return EXPR(ASR::make_IntegerBinOp_t(al, loc, n, ASR::binopType::BitLShift, bits, t, nullptr)); } - inline ASR::expr_t* i_BitNot(ASR::expr_t* x, ASR::ttype_t* t) { - return EXPR(ASR::make_IntegerBitNot_t(al, loc, x, t, nullptr)); - } - - inline ASR::expr_t* i_BitAnd(ASR::expr_t* i, ASR::expr_t* j, ASR::ttype_t* t) { - return EXPR(ASR::make_IntegerBinOp_t(al, loc, i, ASR::binopType::BitAnd, j, t, nullptr)); + ASR::expr_t *And(ASR::expr_t *left, ASR::expr_t *right) { + LCOMPILERS_ASSERT(check_equal_type(expr_type(left), expr_type(right))); + ASR::ttype_t *type = expr_type(left); + ASRUtils::make_ArrayBroadcast_t_util(al, loc, left, right); + switch (type->type) { + case ASR::ttypeType::Integer: { + return EXPR(ASR::make_IntegerBinOp_t(al, loc, left, ASR::binopType::BitAnd, right, type, nullptr)); + } + case ASR::ttypeType::Logical: { + return EXPR(ASR::make_LogicalBinOp_t(al, loc, left, ASR::logicalbinopType::And, right, logical, nullptr)); + } + default: { + throw LCompilersException("Expression type, " + + ASRUtils::type_to_str_python(expr_type(left)) + " not yet supported"); + return nullptr; + } + } } - inline ASR::expr_t* i_BitOr(ASR::expr_t* i, ASR::expr_t* j, ASR::ttype_t* t) { - return EXPR(ASR::make_IntegerBinOp_t(al, loc, i, ASR::binopType::BitOr, j, t, nullptr)); + ASR::expr_t *Or(ASR::expr_t *left, ASR::expr_t *right) { + LCOMPILERS_ASSERT(check_equal_type(expr_type(left), expr_type(right))); + ASR::ttype_t *type = expr_type(left); + ASRUtils::make_ArrayBroadcast_t_util(al, loc, left, right); + switch (type->type) { + case ASR::ttypeType::Integer: { + return EXPR(ASR::make_IntegerBinOp_t(al, loc, left, ASR::binopType::BitOr, right, type, nullptr)); + } + case ASR::ttypeType::Logical: { + return EXPR(ASR::make_LogicalBinOp_t(al, loc, left, ASR::logicalbinopType::Or, right, logical, nullptr)); + } + default: { + throw LCompilersException("Expression type, " + + ASRUtils::type_to_str_python(expr_type(left)) + " not yet supported"); + return nullptr; + } + } } - inline ASR::expr_t* i_BitXor(ASR::expr_t* i, ASR::expr_t* j, ASR::ttype_t* t) { - return EXPR(ASR::make_IntegerBinOp_t(al, loc, i, ASR::binopType::BitXor, j, t, nullptr)); + ASR::expr_t *Xor(ASR::expr_t *left, ASR::expr_t *right) { + LCOMPILERS_ASSERT(check_equal_type(expr_type(left), expr_type(right))); + ASR::ttype_t *type = expr_type(left); + ASRUtils::make_ArrayBroadcast_t_util(al, loc, left, right); + switch (type->type) { + case ASR::ttypeType::Integer: { + return EXPR(ASR::make_IntegerBinOp_t(al, loc, left, ASR::binopType::BitXor, right, type, nullptr)); + } + case ASR::ttypeType::Logical: { + return EXPR(ASR::make_LogicalBinOp_t(al, loc, left, ASR::logicalbinopType::Xor, right, logical, nullptr)); + } + default: { + throw LCompilersException("Expression type, " + + ASRUtils::type_to_str_python(expr_type(left)) + " not yet supported"); + return nullptr; + } + } } - inline ASR::expr_t* sConstant(std::string s, ASR::ttype_t* type) { - return EXPR(ASR::make_StringConstant_t(al, loc, s2c(al, s), type)); + ASR::expr_t *Not(ASR::expr_t *x) { + ASR::ttype_t *type = expr_type(x); + switch (type->type) { + case ASR::ttypeType::Integer: { + return EXPR(ASR::make_IntegerBitNot_t(al, loc, x, type, nullptr)); + } + case ASR::ttypeType::Logical: { + return EXPR(ASR::make_LogicalNot_t(al, loc, x, logical, nullptr)); + } + default: { + throw LCompilersException("Expression type, " + + ASRUtils::type_to_str_python(expr_type(x)) + " not yet supported"); + return nullptr; + } + } } ASR::expr_t *Add(ASR::expr_t *left, ASR::expr_t *right) { @@ -459,24 +489,47 @@ class ASRBuilder { case ASR::ttypeType::Integer : { return EXPR(ASR::make_IntegerBinOp_t(al, loc, left, ASR::binopType::Add, right, type, nullptr)); - break; } case ASR::ttypeType::Real : { return EXPR(ASR::make_RealBinOp_t(al, loc, left, ASR::binopType::Add, right, type, nullptr)); - break; } - case ASR::ttypeType::Character : { + case ASR::ttypeType::String : { return EXPR(ASR::make_StringConcat_t(al, loc, left, right, type, nullptr)); - break; } case ASR::ttypeType::Complex : { return EXPR(ASR::make_ComplexBinOp_t(al, loc, left, ASR::binopType::Add, right, type, nullptr)); } default: { - LCOMPILERS_ASSERT(false); + throw LCompilersException("Expression type, " + + ASRUtils::type_to_str_python(expr_type(left)) + " not yet supported"); + return nullptr; + } + } + } + + ASR::expr_t *Sub(ASR::expr_t *left, ASR::expr_t *right, ASR::expr_t* value = nullptr) { + LCOMPILERS_ASSERT(check_equal_type(expr_type(left), expr_type(right))); + ASR::ttype_t *type = expr_type(left); + ASRUtils::make_ArrayBroadcast_t_util(al, loc, left, right); + switch (type->type) { + case ASR::ttypeType::Integer: { + return EXPR(ASR::make_IntegerBinOp_t(al, loc, left, + ASR::binopType::Sub, right, type, value)); + } + case ASR::ttypeType::Real: { + return EXPR(ASR::make_RealBinOp_t(al, loc, left, + ASR::binopType::Sub, right, type, value)); + } + case ASR::ttypeType::Complex: { + return EXPR(ASR::make_ComplexBinOp_t(al, loc, left, + ASR::binopType::Sub, right, type, value)); + } + default: { + throw LCompilersException("Expression type, " + + ASRUtils::type_to_str_python(expr_type(left)) + " not yet supported"); return nullptr; } } @@ -487,27 +540,98 @@ class ASRBuilder { ASR::ttype_t *type = expr_type(left); ASRUtils::make_ArrayBroadcast_t_util(al, loc, left, right); switch (type->type) { - case ASR::ttypeType::Integer : { + case ASR::ttypeType::Integer: { + int64_t left_value = 0, right_value = 0; + ASR::expr_t* value = nullptr; + if( ASRUtils::extract_value(left, left_value) && + ASRUtils::extract_value(right, right_value) ) { + int64_t mul_value = left_value * right_value; + value = ASRUtils::EXPR(ASR::make_IntegerConstant_t(al, loc, mul_value, type)); + } return EXPR(ASR::make_IntegerBinOp_t(al, loc, left, - ASR::binopType::Mul, right, type, nullptr)); - break; + ASR::binopType::Mul, right, type, value)); } - case ASR::ttypeType::Real : { + case ASR::ttypeType::Real: { + double left_value = 0, right_value = 0; + ASR::expr_t* value = nullptr; + if( ASRUtils::extract_value(left, left_value) && + ASRUtils::extract_value(right, right_value) ) { + double mul_value = left_value * right_value; + value = ASRUtils::EXPR(ASR::make_RealConstant_t(al, loc, mul_value, type)); + } return EXPR(ASR::make_RealBinOp_t(al, loc, left, - ASR::binopType::Mul, right, type, nullptr)); - break; + ASR::binopType::Mul, right, type, value)); } - case ASR::ttypeType::Complex : { + case ASR::ttypeType::Complex: { return EXPR(ASR::make_ComplexBinOp_t(al, loc, left, ASR::binopType::Mul, right, type, nullptr)); } default: { - LCOMPILERS_ASSERT(false); + throw LCompilersException("Expression type, " + + ASRUtils::type_to_str_python(expr_type(left)) + " not yet supported"); + return nullptr; + } + } + } + + ASR::expr_t *Div(ASR::expr_t *left, ASR::expr_t *right) { + LCOMPILERS_ASSERT(check_equal_type(expr_type(left), expr_type(right))); + ASR::ttype_t *type = expr_type(left); + ASRUtils::make_ArrayBroadcast_t_util(al, loc, left, right); + switch (type->type) { + case ASR::ttypeType::Integer: { + return EXPR(ASR::make_IntegerBinOp_t(al, loc, left, + ASR::binopType::Div, right, type, nullptr)); + } + case ASR::ttypeType::Real: { + return EXPR(ASR::make_RealBinOp_t(al, loc, left, + ASR::binopType::Div, right, type, nullptr)); + } + case ASR::ttypeType::Complex: { + return EXPR(ASR::make_ComplexBinOp_t(al, loc, left, + ASR::binopType::Div, right, type, nullptr)); + } + default: { + throw LCompilersException("Expression type, " + + ASRUtils::type_to_str_python(expr_type(left)) + " not yet supported"); + return nullptr; + } + } + } + + ASR::expr_t *Pow(ASR::expr_t *left, ASR::expr_t *right) { + LCOMPILERS_ASSERT(check_equal_type(expr_type(left), expr_type(right))); + ASR::ttype_t *type = expr_type(left); + ASRUtils::make_ArrayBroadcast_t_util(al, loc, left, right); + switch (type->type) { + case ASR::ttypeType::Integer: { + return EXPR(ASR::make_IntegerBinOp_t(al, loc, left, + ASR::binopType::Pow, right, type, nullptr)); + } + case ASR::ttypeType::Real: { + return EXPR(ASR::make_RealBinOp_t(al, loc, left, + ASR::binopType::Pow, right, type, nullptr)); + } + case ASR::ttypeType::Complex: { + return EXPR(ASR::make_ComplexBinOp_t(al, loc, left, + ASR::binopType::Pow, right, type, nullptr)); + } + default: { + throw LCompilersException("Expression type, " + + ASRUtils::type_to_str_python(expr_type(left)) + " not yet supported"); return nullptr; } } } + ASR::expr_t* Max(ASR::expr_t* left, ASR::expr_t* right) { + return ASRUtils::EXPR(ASR::make_IfExp_t(al, loc, Gt(left, right), left, right, ASRUtils::expr_type(left), nullptr)); + } + + ASR::expr_t* Min(ASR::expr_t* left, ASR::expr_t* right) { + return ASRUtils::EXPR(ASR::make_IfExp_t(al, loc, Lt(left, right), left, right, ASRUtils::expr_type(left), nullptr)); + } + ASR::stmt_t* CallIntrinsicSubroutine(SymbolTable* scope, std::vector types, std::vector args, int64_t overload_id, ASR::stmt_t* (*intrinsic_subroutine)(Allocator &, const Location &, SymbolTable *, @@ -541,265 +665,184 @@ class ASRBuilder { } // Compare ----------------------------------------------------------------- - inline ASR::expr_t* iEq(ASR::expr_t* x, ASR::expr_t* y) { - return EXPR(ASR::make_IntegerCompare_t(al, loc, x, ASR::cmpopType::Eq, y, logical, nullptr)); - } - inline ASR::expr_t* iNotEq(ASR::expr_t* x, ASR::expr_t* y) { - return EXPR(ASR::make_IntegerCompare_t(al, loc, x, ASR::cmpopType::NotEq, y, logical, nullptr)); - } - inline ASR::expr_t* iLt(ASR::expr_t* x, ASR::expr_t* y) { - return EXPR(ASR::make_IntegerCompare_t(al, loc, x, ASR::cmpopType::Lt, y, logical, nullptr)); - } - inline ASR::expr_t* iLtE(ASR::expr_t* x, ASR::expr_t* y) { - return EXPR(ASR::make_IntegerCompare_t(al, loc, x, ASR::cmpopType::LtE, y, logical, nullptr)); - } - inline ASR::expr_t* iGtE(ASR::expr_t* x, ASR::expr_t* y) { - return EXPR(ASR::make_IntegerCompare_t(al, loc, x, ASR::cmpopType::GtE, y, logical, nullptr)); - } - inline ASR::expr_t* iGt(ASR::expr_t* x, ASR::expr_t* y) { - return EXPR(ASR::make_IntegerCompare_t(al, loc, x, ASR::cmpopType::Gt, y, logical, nullptr)); - } - inline ASR::expr_t* ArraySize_1(ASR::expr_t* x, ASR::expr_t* dim) { - return EXPR(make_ArraySize_t_util(al, loc, x, dim, int32, nullptr)); - } - inline ASR::expr_t* ArraySize_2(ASR::expr_t* x, ASR::expr_t* dim, ASR::ttype_t* t) { - return EXPR(make_ArraySize_t_util(al, loc, x, dim, t, nullptr)); - } - inline ASR::expr_t* fEq(ASR::expr_t* x, ASR::expr_t* y) { - return EXPR(ASR::make_RealCompare_t(al, loc, x, ASR::cmpopType::Eq, y, logical, nullptr)); - } - inline ASR::expr_t* fGtE(ASR::expr_t* x, ASR::expr_t* y) { - return EXPR(ASR::make_RealCompare_t(al, loc, x, ASR::cmpopType::GtE, y, logical, nullptr)); - } - inline ASR::expr_t* fLtE(ASR::expr_t* x, ASR::expr_t* y) { - return EXPR(ASR::make_RealCompare_t(al, loc, x, ASR::cmpopType::LtE, y, logical, nullptr)); - } - inline ASR::expr_t* fLt(ASR::expr_t* x, ASR::expr_t* y) { - return EXPR(ASR::make_RealCompare_t(al, loc, x, ASR::cmpopType::Lt, y, logical, nullptr)); - } - inline ASR::expr_t* fGt(ASR::expr_t* x, ASR::expr_t* y) { - return EXPR(ASR::make_RealCompare_t(al, loc, x, ASR::cmpopType::Gt, y, logical, nullptr)); - } - inline ASR::expr_t* fNotEq(ASR::expr_t* x, ASR::expr_t* y) { - return EXPR(ASR::make_RealCompare_t(al, loc, x, ASR::cmpopType::NotEq, y, logical, nullptr)); - } - inline ASR::expr_t* boolEq(ASR::expr_t* x, ASR::expr_t* y) { - return EXPR(ASR::make_LogicalCompare_t(al, loc, x, ASR::cmpopType::Eq, y, logical, nullptr)); - } - inline ASR::expr_t* sEq(ASR::expr_t* x, ASR::expr_t* y) { - return EXPR(ASR::make_StringCompare_t(al, loc, x, ASR::cmpopType::Eq, y, logical, nullptr)); - } - inline ASR::expr_t* sNotEq(ASR::expr_t* x, ASR::expr_t* y) { - return EXPR(ASR::make_StringCompare_t(al, loc, x, ASR::cmpopType::NotEq, y, logical, nullptr)); - } - inline ASR::expr_t* sLt(ASR::expr_t* x, ASR::expr_t* y) { - return EXPR(ASR::make_StringCompare_t(al, loc, x, ASR::cmpopType::Lt, y, logical, nullptr)); - } - inline ASR::expr_t* sLtE(ASR::expr_t* x, ASR::expr_t* y) { - return EXPR(ASR::make_StringCompare_t(al, loc, x, ASR::cmpopType::LtE, y, logical, nullptr)); - } - inline ASR::expr_t* sGt(ASR::expr_t* x, ASR::expr_t* y) { - return EXPR(ASR::make_StringCompare_t(al, loc, x, ASR::cmpopType::Gt, y, logical, nullptr)); - } - inline ASR::expr_t* sGtE(ASR::expr_t* x, ASR::expr_t* y) { - return EXPR(ASR::make_StringCompare_t(al, loc, x, ASR::cmpopType::GtE, y, logical, nullptr)); - } - ASR::expr_t *Gt(ASR::expr_t *left, ASR::expr_t *right) { LCOMPILERS_ASSERT(check_equal_type(expr_type(left), expr_type(right))); - if (is_real(*expr_type(left))) { - return fGt(left, right); - } else if (is_integer(*expr_type(left))) { - return iGt(left, right); - } else { - LCOMPILERS_ASSERT(false); - return nullptr; - } - } - - ASR::expr_t *Lt(ASR::expr_t *left, ASR::expr_t *right) { - LCOMPILERS_ASSERT(check_equal_type(expr_type(left), expr_type(right))); - if (is_real(*expr_type(left))) { - return fLt(left, right); - } else if (is_integer(*expr_type(left))) { - return iLt(left, right); - } else { - LCOMPILERS_ASSERT(false); - return nullptr; - } - } - - ASR::stmt_t *If(ASR::expr_t *a_test, std::vector if_body, - std::vector else_body) { - Vec m_if_body; m_if_body.reserve(al, 1); - for (auto &x: if_body) m_if_body.push_back(al, x); - - Vec m_else_body; m_else_body.reserve(al, 1); - for (auto &x: else_body) m_else_body.push_back(al, x); - - return STMT(ASR::make_If_t(al, loc, a_test, m_if_body.p, m_if_body.n, - m_else_body.p, m_else_body.n)); - } - - ASR::stmt_t *While(ASR::expr_t *a_test, std::vector body) { - Vec m_body; m_body.reserve(al, 1); - for (auto &x: body) m_body.push_back(al, x); - - return STMT(ASR::make_WhileLoop_t(al, loc, nullptr, a_test, - m_body.p, m_body.n, nullptr, 0)); - } - - ASR::stmt_t *Exit(char* loop_name) { - return STMT(ASR::make_Exit_t(al, loc, loop_name)); - } - - ASR::expr_t *TupleConstant(std::vector ele, ASR::ttype_t *type) { - Vec m_ele; m_ele.reserve(al, 3); - for (auto &x: ele) m_ele.push_back(al, x); - return EXPR(ASR::make_TupleConstant_t(al, loc, m_ele.p, m_ele.n, type)); - } - - #define make_Compare(Constructor, left, op, right) ASRUtils::EXPR(ASR::Constructor( \ - al, loc, left, ASR::cmpopType::op, right, \ - ASRUtils::TYPE(ASR::make_Logical_t( \ - al, loc, 4)), nullptr)); \ - - #define create_ElementalBinOp(OpType, BinOpName, OpName, value) case ASR::ttypeType::OpType: { \ - return ASRUtils::EXPR(ASR::BinOpName(al, loc, \ - left, ASR::binopType::OpName, right, \ - ASRUtils::expr_type(left), value)); \ - } \ - - ASR::expr_t* ElementalAdd(ASR::expr_t* left, ASR::expr_t* right, - const Location& loc, ASR::expr_t* value=nullptr) { - ASR::ttype_t *left_type = ASRUtils::expr_type(left); - left_type = ASRUtils::type_get_past_pointer(left_type); - switch (left_type->type) { - create_ElementalBinOp(Real, make_RealBinOp_t, Add, value) - create_ElementalBinOp(Integer, make_IntegerBinOp_t, Add, value) - create_ElementalBinOp(Complex, make_ComplexBinOp_t, Add, value) - default: { - throw LCompilersException("Expression type, " + - std::to_string(left_type->type) + - " not yet supported"); + ASR::ttype_t *type = expr_type(left); + switch(type->type){ + case ASR::ttypeType::Integer: { + return EXPR(ASR::make_IntegerCompare_t(al, loc, left, ASR::cmpopType::Gt, right, logical, nullptr)); + } + case ASR::ttypeType::Real: { + return EXPR(ASR::make_RealCompare_t(al, loc, left, ASR::cmpopType::Gt, right, logical, nullptr)); + } + case ASR::ttypeType::String: { + return EXPR(ASR::make_StringCompare_t(al, loc, left, ASR::cmpopType::Gt, right, logical, nullptr)); + } + case ASR::ttypeType::Logical: { + return EXPR(ASR::make_LogicalCompare_t(al, loc, left, ASR::cmpopType::Gt, right, logical, nullptr)); } - } - } - - ASR::expr_t* ElementalSub(ASR::expr_t* left, ASR::expr_t* right, - const Location& loc, ASR::expr_t* value=nullptr) { - switch (ASRUtils::expr_type(left)->type) { - create_ElementalBinOp(Real, make_RealBinOp_t, Sub, value) - create_ElementalBinOp(Integer, make_IntegerBinOp_t, Sub, value) - create_ElementalBinOp(Complex, make_ComplexBinOp_t, Sub, value) default: { throw LCompilersException("Expression type, " + - std::to_string(expr_type(left)->type) + - " not yet supported"); + ASRUtils::type_to_str_python(expr_type(left)) + " not yet supported"); + return nullptr; } } } - ASR::expr_t* ElementalDiv(ASR::expr_t* left, ASR::expr_t* right, - const Location& loc, ASR::expr_t* value=nullptr) { - switch (ASRUtils::expr_type(left)->type) { - create_ElementalBinOp(Real, make_RealBinOp_t, Div, value) - create_ElementalBinOp(Integer, make_IntegerBinOp_t, Div, value) - create_ElementalBinOp(Complex, make_ComplexBinOp_t, Div, value) + ASR::expr_t *Lt(ASR::expr_t *left, ASR::expr_t *right) { + LCOMPILERS_ASSERT(check_equal_type(expr_type(left), expr_type(right))); + ASR::ttype_t *type = expr_type(left); + switch(type->type){ + case ASR::ttypeType::Integer: { + return EXPR(ASR::make_IntegerCompare_t(al, loc, left, ASR::cmpopType::Lt, right, logical, nullptr)); + } + case ASR::ttypeType::Real: { + return EXPR(ASR::make_RealCompare_t(al, loc, left, ASR::cmpopType::Lt, right, logical, nullptr)); + } + case ASR::ttypeType::String: { + return EXPR(ASR::make_StringCompare_t(al, loc, left, ASR::cmpopType::Lt, right, logical, nullptr)); + } + case ASR::ttypeType::Logical: { + return EXPR(ASR::make_LogicalCompare_t(al, loc, left, ASR::cmpopType::Lt, right, logical, nullptr)); + } default: { throw LCompilersException("Expression type, " + - std::to_string(expr_type(left)->type) + - " not yet supported"); + ASRUtils::type_to_str_python(expr_type(left)) + " not yet supported"); + return nullptr; } } } - ASR::expr_t* ElementalMul(ASR::expr_t* left, ASR::expr_t* right, - const Location& loc, ASR::expr_t* value=nullptr) { - switch (ASRUtils::expr_type(left)->type) { - create_ElementalBinOp(Real, make_RealBinOp_t, Mul, value) - create_ElementalBinOp(Integer, make_IntegerBinOp_t, Mul, value) - create_ElementalBinOp(Complex, make_ComplexBinOp_t, Mul, value) + ASR::expr_t *GtE(ASR::expr_t *left, ASR::expr_t *right) { + LCOMPILERS_ASSERT(check_equal_type(expr_type(left), expr_type(right))); + ASR::ttype_t *type = expr_type(left); + switch(type->type){ + case ASR::ttypeType::Integer: { + return EXPR(ASR::make_IntegerCompare_t(al, loc, left, ASR::cmpopType::GtE, right, logical, nullptr)); + } + case ASR::ttypeType::Real: { + return EXPR(ASR::make_RealCompare_t(al, loc, left, ASR::cmpopType::GtE, right, logical, nullptr)); + } + case ASR::ttypeType::String: { + return EXPR(ASR::make_StringCompare_t(al, loc, left, ASR::cmpopType::GtE, right, logical, nullptr)); + } + case ASR::ttypeType::Logical: { + return EXPR(ASR::make_LogicalCompare_t(al, loc, left, ASR::cmpopType::GtE, right, logical, nullptr)); + } default: { throw LCompilersException("Expression type, " + - std::to_string(expr_type(left)->type) + - " not yet supported"); + ASRUtils::type_to_str_python(expr_type(left)) + " not yet supported"); + return nullptr; } } } - ASR::expr_t* ElementalPow(ASR::expr_t* left, ASR::expr_t* right, - const Location& loc, ASR::expr_t* value=nullptr) { - switch (ASRUtils::expr_type(left)->type) { - create_ElementalBinOp(Real, make_RealBinOp_t, Pow, value) - create_ElementalBinOp(Integer, make_IntegerBinOp_t, Pow, value) - create_ElementalBinOp(Complex, make_ComplexBinOp_t, Pow, value) + ASR::expr_t *LtE(ASR::expr_t *left, ASR::expr_t *right) { + LCOMPILERS_ASSERT(check_equal_type(expr_type(left), expr_type(right))); + ASR::ttype_t *type = expr_type(left); + switch(type->type){ + case ASR::ttypeType::Integer: { + return EXPR(ASR::make_IntegerCompare_t(al, loc, left, ASR::cmpopType::LtE, right, logical, nullptr)); + } + case ASR::ttypeType::Real: { + return EXPR(ASR::make_RealCompare_t(al, loc, left, ASR::cmpopType::LtE, right, logical, nullptr)); + } + case ASR::ttypeType::String: { + return EXPR(ASR::make_StringCompare_t(al, loc, left, ASR::cmpopType::LtE, right, logical, nullptr)); + } + case ASR::ttypeType::Logical: { + return EXPR(ASR::make_LogicalCompare_t(al, loc, left, ASR::cmpopType::LtE, right, logical, nullptr)); + } default: { throw LCompilersException("Expression type, " + - std::to_string(expr_type(left)->type) + - " not yet supported"); + ASRUtils::type_to_str_python(expr_type(left)) + " not yet supported"); + return nullptr; } } } - ASR::expr_t* ElementalMax(ASR::expr_t* left, ASR::expr_t* right, - const Location& loc, ASR::expr_t* value=nullptr) { - ASR::expr_t* test_condition = nullptr; - switch (ASRUtils::expr_type(left)->type) { + ASR::expr_t *Eq(ASR::expr_t *left, ASR::expr_t *right) { + LCOMPILERS_ASSERT(check_equal_type(expr_type(left), expr_type(right))); + ASR::ttype_t *type = expr_type(left); + switch(type->type){ case ASR::ttypeType::Integer: { - test_condition = make_Compare(make_IntegerCompare_t, left, Gt, right); - break; + return EXPR(ASR::make_IntegerCompare_t(al, loc, left, ASR::cmpopType::Eq, right, logical, nullptr)); } case ASR::ttypeType::Real: { - test_condition = make_Compare(make_RealCompare_t, left, Gt, right); - break; + return EXPR(ASR::make_RealCompare_t(al, loc, left, ASR::cmpopType::Eq, right, logical, nullptr)); + } + case ASR::ttypeType::String: { + return EXPR(ASR::make_StringCompare_t(al, loc, left, ASR::cmpopType::Eq, right, logical, nullptr)); + } + case ASR::ttypeType::Logical: { + return EXPR(ASR::make_LogicalCompare_t(al, loc, left, ASR::cmpopType::Eq, right, logical, nullptr)); + } + case ASR::ttypeType::Complex: { + return EXPR(ASR::make_ComplexCompare_t(al, loc, left, ASR::cmpopType::Eq, right, logical, nullptr)); } default: { throw LCompilersException("Expression type, " + - std::to_string(expr_type(left)->type) + " not yet supported"); + ASRUtils::type_to_str_python(expr_type(left)) + " not yet supported"); + return nullptr; } } - return ASRUtils::EXPR(ASR::make_IfExp_t(al, loc, test_condition, left, right, ASRUtils::expr_type(left), value)); } - ASR::expr_t* ElementalMin(ASR::expr_t* left, ASR::expr_t* right, - const Location& loc, ASR::expr_t* value=nullptr) { - ASR::expr_t* test_condition = nullptr; - switch (ASRUtils::expr_type(left)->type) { + ASR::expr_t *NotEq(ASR::expr_t *left, ASR::expr_t *right) { + LCOMPILERS_ASSERT(check_equal_type(expr_type(left), expr_type(right))); + ASR::ttype_t *type = expr_type(left); + switch(type->type){ case ASR::ttypeType::Integer: { - test_condition = make_Compare(make_IntegerCompare_t, left, Lt, right); - break; + return EXPR(ASR::make_IntegerCompare_t(al, loc, left, ASR::cmpopType::NotEq, right, logical, nullptr)); } case ASR::ttypeType::Real: { - test_condition = make_Compare(make_RealCompare_t, left, Lt, right); - break; + return EXPR(ASR::make_RealCompare_t(al, loc, left, ASR::cmpopType::NotEq, right, logical, nullptr)); + } + case ASR::ttypeType::String: { + return EXPR(ASR::make_StringCompare_t(al, loc, left, ASR::cmpopType::NotEq, right, logical, nullptr)); + } + case ASR::ttypeType::Logical: { + return EXPR(ASR::make_LogicalCompare_t(al, loc, left, ASR::cmpopType::NotEq, right, logical, nullptr)); } default: { throw LCompilersException("Expression type, " + - std::to_string(expr_type(left)->type) + " not yet supported"); + ASRUtils::type_to_str_python(expr_type(left)) + " not yet supported"); + return nullptr; } } - return ASRUtils::EXPR(ASR::make_IfExp_t(al, loc, test_condition, left, right, ASRUtils::expr_type(left), value)); } - ASR::expr_t* ElementalOr(ASR::expr_t* left, ASR::expr_t* right, - const Location& loc) { - return ASRUtils::EXPR(ASR::make_LogicalBinOp_t(al, loc, - left, ASR::Or, right, - ASRUtils::TYPE(ASR::make_Logical_t( al, loc, 4)), nullptr)); + ASR::stmt_t *If(ASR::expr_t *a_test, std::vector if_body, + std::vector else_body) { + Vec m_if_body; m_if_body.reserve(al, 1); + for (auto &x: if_body) m_if_body.push_back(al, x); + + Vec m_else_body; m_else_body.reserve(al, 1); + for (auto &x: else_body) m_else_body.push_back(al, x); + + return STMT(ASR::make_If_t(al, loc, a_test, m_if_body.p, m_if_body.n, + m_else_body.p, m_else_body.n)); + } + + ASR::stmt_t *While(ASR::expr_t *a_test, std::vector body) { + Vec m_body; m_body.reserve(al, 1); + for (auto &x: body) m_body.push_back(al, x); + + return STMT(ASR::make_WhileLoop_t(al, loc, nullptr, a_test, + m_body.p, m_body.n, nullptr, 0)); } - ASR::expr_t* LogicalOr(ASR::expr_t* left, ASR::expr_t* right, - const Location& loc) { - return ASRUtils::EXPR(ASR::make_LogicalBinOp_t(al, loc, - left, ASR::Or, right, ASRUtils::expr_type(left), - nullptr)); + ASR::expr_t *TupleConstant(std::vector ele, ASR::ttype_t *type) { + Vec m_ele; m_ele.reserve(al, 3); + for (auto &x: ele) m_ele.push_back(al, x); + return EXPR(ASR::make_TupleConstant_t(al, loc, m_ele.p, m_ele.n, type)); } ASR::expr_t* Call(ASR::symbol_t* s, Vec& args, ASR::ttype_t* return_type) { return ASRUtils::EXPR(ASRUtils::make_FunctionCall_t_util(al, loc, - s, s, args.p, args.size(), return_type, nullptr, nullptr)); + s, s, args.p, args.size(), return_type, nullptr, nullptr, + false)); } ASR::expr_t* Call(ASR::symbol_t* s, Vec& args, @@ -807,13 +850,15 @@ class ASRBuilder { Vec args_; args_.reserve(al, 2); visit_expr_list(al, args, args_); return ASRUtils::EXPR(ASRUtils::make_FunctionCall_t_util(al, loc, - s, s, args_.p, args_.size(), return_type, nullptr, nullptr)); + s, s, args_.p, args_.size(), return_type, nullptr, nullptr, + false)); } ASR::expr_t* Call(ASR::symbol_t* s, Vec& args, ASR::ttype_t* return_type, ASR::expr_t* value) { return ASRUtils::EXPR(ASRUtils::make_FunctionCall_t_util(al, loc, - s, s, args.p, args.size(), return_type, value, nullptr)); + s, s, args.p, args.size(), return_type, value, nullptr, + false)); } ASR::stmt_t* SubroutineCall(ASR::symbol_t* s, Vec& args) { @@ -838,7 +883,7 @@ class ASRBuilder { for (auto &x: elements) m_eles.push_back(al, x); ASR::ttype_t *fixed_size_type = Array({(int64_t) elements.size()}, base_type); - ASR::expr_t *arr_constant = EXPR(ASR::make_ArrayConstant_t(al, loc, + ASR::expr_t *arr_constant = EXPR(ASRUtils::make_ArrayConstructor_t_util(al, loc, m_eles.p, m_eles.n, fixed_size_type, ASR::arraystorageType::ColMajor)); if (cast2descriptor) { @@ -857,25 +902,36 @@ class ASRBuilder { } // Statements -------------------------------------------------------------- - #define Return() STMT(ASR::make_Return_t(al, loc)) + ASR::stmt_t *Exit() { + return STMT(ASR::make_Exit_t(al, loc, nullptr)); + } + + ASR::stmt_t *Return() { + return STMT(ASR::make_Return_t(al, loc)); + } ASR::stmt_t *Assignment(ASR::expr_t *lhs, ASR::expr_t *rhs) { - LCOMPILERS_ASSERT(check_equal_type(expr_type(lhs), expr_type(rhs))); + LCOMPILERS_ASSERT_MSG(check_equal_type(expr_type(lhs), expr_type(rhs)), + type_to_str_python(expr_type(lhs)) + ", " + type_to_str_python(expr_type(rhs))); return STMT(ASR::make_Assignment_t(al, loc, lhs, rhs, nullptr)); } + ASR::stmt_t* CPtrToPointer(ASR::expr_t* cptr, ASR::expr_t* ptr, ASR::expr_t* shape = nullptr, ASR::expr_t* lower_bounds = nullptr) { + return STMT(ASR::make_CPtrToPointer_t(al, loc, cptr, ptr, shape, lower_bounds)); + } + template ASR::stmt_t *Assign_Constant(ASR::expr_t *lhs, T init_value) { ASR::ttype_t *type = expr_type(lhs); switch(type->type) { case ASR::ttypeType::Integer : { - return Assignment(lhs, i(init_value, type)); + return Assignment(lhs, i_t(init_value, type)); } case ASR::ttypeType::Real : { - return Assignment(lhs, f(init_value, type)); + return Assignment(lhs, f_t(init_value, type)); } case ASR::ttypeType::Complex : { - return Assignment(lhs, complex(init_value, init_value, type)); + return Assignment(lhs, complex_t(init_value, init_value, type)); } default : { LCOMPILERS_ASSERT(false); @@ -898,6 +954,21 @@ class ASRBuilder { nullptr, nullptr, nullptr)); } + ASR::stmt_t *Allocate(ASR::expr_t *m_a, ASR::dimension_t* m_dims, size_t n_dims) { + Vec alloc_args; alloc_args.reserve(al, 1); + ASR::alloc_arg_t alloc_arg; + alloc_arg.loc = loc; + alloc_arg.m_a = m_a; + alloc_arg.m_dims = m_dims; + alloc_arg.n_dims = n_dims; + alloc_arg.m_type = nullptr; + alloc_arg.m_len_expr = nullptr; + alloc_args.push_back(al, alloc_arg); + return STMT(ASR::make_Allocate_t(al, loc, alloc_args.p, 1, + nullptr, nullptr, nullptr)); + } + + #define UBound(arr, dim) PassUtils::get_bound(arr, dim, "ubound", al) #define LBound(arr, dim) PassUtils::get_bound(arr, dim, "lbound", al) @@ -914,6 +985,25 @@ class ASRBuilder { return STMT(ASR::make_DoLoop_t(al, loc, nullptr, head, body.p, body.n, nullptr, 0)); } + /* + if loop_body contains A(i, j, k) then set idx_vars=(k, j, i) + in order to iterate on the array left to right, the inner-most + loop on the fastest index on the left, as is common in Fortran + ``` + idx_vars=(k, j, i) + body A(i, j, k) + + produces + + do k = 1, n + do j = 1, n + do i = 1, n + A(i, j, k) + end do + end do + end do + ``` + */ template ASR::stmt_t* create_do_loop( const Location& loc, int rank, ASR::expr_t* array, @@ -922,7 +1012,7 @@ class ASRBuilder { PassUtils::create_idx_vars(idx_vars, rank, loc, al, scope, "_i"); ASR::stmt_t* doloop = nullptr; - for( int i = (int) idx_vars.size() - 1; i >= 0; i-- ) { + for ( int i = 0; i < (int) idx_vars.size(); i++ ) { ASR::do_loop_head_t head; head.m_v = idx_vars[i]; head.m_start = PassUtils::get_bound(array, i + 1, "lbound", al); @@ -949,7 +1039,7 @@ class ASRBuilder { Vec& doloop_body, LOOP_BODY loop_body) { ASR::stmt_t* doloop = nullptr; - for( int i = (int) loop_vars.size() - 1; i >= 0; i-- ) { + for ( int i = 0; i < (int) loop_vars.size(); i++ ) { ASR::do_loop_head_t head; head.m_v = loop_vars[i]; head.m_start = PassUtils::get_bound(array, loop_dims[i], "lbound", al); @@ -996,9 +1086,7 @@ class ASRBuilder { PassUtils::create_idx_vars(idx_vars, n_dims, loc, al, fn_scope, "_j"); for( int i = 1; i <= n_dims; i++ ) { ASR::expr_t* current_dim = i32(i); - ASR::expr_t* test_expr = make_Compare(make_IntegerCompare_t, dim, - Eq, current_dim); - + ASR::expr_t* test_expr = Eq(dim, current_dim); Vec loop_vars; std::vector loop_dims; loop_dims.reserve(n_dims); @@ -1036,8 +1124,41 @@ class ASRBuilder { // Used for debugging Vec x_exprs; x_exprs.from_pointer_n_copy(al, &items[0], items.size()); - return STMT(ASR::make_Print_t(al, loc, x_exprs.p, x_exprs.n, - nullptr, nullptr)); + return STMT(ASRUtils::make_print_t_util(al, loc, x_exprs.p, x_exprs.n)); + } + + ASR::symbol_t* create_c_func(std::string c_func_name, SymbolTable* fn_symtab, ASR::ttype_t* return_type, int n_args, Vec& arg_types) { + SymbolTable *fn_symtab_1 = al.make_new(fn_symtab); + Vec args_1; args_1.reserve(al, n_args); + for (int i = 0; i < n_args; i++) { + args_1.push_back(al, this->Variable(fn_symtab_1, "x_"+std::to_string(i), arg_types[i], + ASR::intentType::In, ASR::abiType::BindC, true)); + } + ASR::expr_t *return_var_1 = this->Variable(fn_symtab_1, c_func_name, + return_type, ASRUtils::intent_return_var, ASR::abiType::BindC, false); + + SetChar dep_1; dep_1.reserve(al, 1); + Vec body_1; body_1.reserve(al, 1); + ASR::symbol_t *s = make_ASR_Function_t(c_func_name, fn_symtab_1, dep_1, args_1, + body_1, return_var_1, ASR::abiType::BindC, ASR::deftypeType::Interface, s2c(al, c_func_name)); + return s; + } + + ASR::symbol_t* create_c_func_subroutines(std::string c_func_name, SymbolTable* fn_symtab, int n_args, ASR::ttype_t* arg_types) { + SymbolTable *fn_symtab_1 = al.make_new(fn_symtab); + Vec args_1; args_1.reserve(al, 0); + for (int i = 0; i < n_args; i++) { + args_1.push_back(al, this->Variable(fn_symtab_1, "x_"+std::to_string(i), arg_types, + ASR::intentType::InOut, ASR::abiType::BindC, true)); + } + ASR::expr_t *return_var_1 = this->Variable(fn_symtab_1, c_func_name, + ASRUtils::type_get_past_array(ASRUtils::type_get_past_allocatable(arg_types)), + ASRUtils::intent_return_var, ASR::abiType::BindC, false); + SetChar dep_1; dep_1.reserve(al, 1); + Vec body_1; body_1.reserve(al, 1); + ASR::symbol_t *s = make_ASR_Function_t(c_func_name, fn_symtab_1, dep_1, args_1, + body_1, return_var_1, ASR::abiType::BindC, ASR::deftypeType::Interface, s2c(al, c_func_name)); + return s; } }; diff --git a/src/libasr/asr_deserialization_visitor.h b/src/libasr/asr_deserialization_visitor.h new file mode 100644 index 0000000000..7d1635be26 --- /dev/null +++ b/src/libasr/asr_deserialization_visitor.h @@ -0,0 +1,4688 @@ +#pragma once + +// Generated by grammar/asdl_cpp.py + +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace LCompilers::ASR { +/******************************************************************************/ +// Deserialization Visitor base class + +template +class DeserializationBaseVisitor : public BaseVisitor +{ +private: + StructType& self() { return static_cast(*this); } +public: + Allocator &al; + bool load_symtab_id; + uint32_t offset = 0; + std::map id_symtab_map; + DeserializationBaseVisitor(Allocator &al, bool load_symtab_id, uint32_t offset) : al{al}, load_symtab_id{load_symtab_id}, offset{offset} {} + asr_t* deserialize_node() { + uint8_t t = self().read_int8(); + ASR::asrType ty = static_cast(t); + switch (ty) { + case (ASR::asrType::unit) : return self().deserialize_unit(); + case (ASR::asrType::symbol) : return self().deserialize_symbol(); + case (ASR::asrType::stmt) : return self().deserialize_stmt(); + case (ASR::asrType::expr) : return self().deserialize_expr(); + case (ASR::asrType::ttype) : return self().deserialize_ttype(); + case (ASR::asrType::attribute) : return self().deserialize_attribute(); + case (ASR::asrType::tbind) : return self().deserialize_tbind(); + case (ASR::asrType::case_stmt) : return self().deserialize_case_stmt(); + case (ASR::asrType::type_stmt) : return self().deserialize_type_stmt(); + case (ASR::asrType::require_instantiation) : return self().deserialize_require_instantiation(); + default : throw LCompilersException("Unknown type in deserialize_node()"); + } + throw LCompilersException("Switch statement above was not exhaustive."); + } + asr_t* deserialize_TranslationUnit() { + size_t n_items; // Sequence + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + uint64_t m_symtab_counter = self().read_int64(); + LCOMPILERS_ASSERT(id_symtab_map.find(m_symtab_counter) == id_symtab_map.end()); + SymbolTable *m_symtab = al.make_new(nullptr); + if (load_symtab_id) m_symtab->counter = m_symtab_counter; + id_symtab_map[m_symtab_counter] = m_symtab; + { + size_t n = self().read_int64(); + for (size_t i=0; i(deserialize_symbol()); + self().symtab_insert_symbol(*m_symtab, name, sym); + } + } + n_items = self().read_int64(); + Vec v_items; + v_items.reserve(al, n_items); + for (size_t i=0; i(t); + switch (ty) { + case (ASR::unitType::TranslationUnit) : return self().deserialize_TranslationUnit(); + default : throw LCompilersException("Unknown type in deserialize_unit()"); + } + throw LCompilersException("Switch statement above was not exhaustive."); + } + asr_t* deserialize_Program() { + size_t n_dependencies; // Sequence + size_t n_body; // Sequence + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + uint64_t m_symtab_counter = self().read_int64(); + LCOMPILERS_ASSERT(id_symtab_map.find(m_symtab_counter) == id_symtab_map.end()); + SymbolTable *m_symtab = al.make_new(nullptr); + if (load_symtab_id) m_symtab->counter = m_symtab_counter; + id_symtab_map[m_symtab_counter] = m_symtab; + { + size_t n = self().read_int64(); + for (size_t i=0; i(deserialize_symbol()); + self().symtab_insert_symbol(*m_symtab, name, sym); + } + } + char *m_name; + m_name = self().read_cstring(); + n_dependencies = self().read_int64(); + Vec v_dependencies; + v_dependencies.reserve(al, n_dependencies); + for (size_t i=0; i v_body; + v_body.reserve(al, n_body); + for (size_t i=0; i(self().deserialize_stmt())); + } + Location* m_start_name; + m_start_name = al.make_new(); + m_start_name->first = self().read_int64(); + m_start_name->last = self().read_int64(); + Location* m_end_name; + m_end_name = al.make_new(); + m_end_name->first = self().read_int64(); + m_end_name->last = self().read_int64(); + return ASR::make_Program_t(al, loc, m_symtab, m_name, v_dependencies.p, v_dependencies.n, v_body.p, v_body.n, m_start_name, m_end_name); + } + asr_t* deserialize_Module() { + size_t n_dependencies; // Sequence + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + uint64_t m_symtab_counter = self().read_int64(); + LCOMPILERS_ASSERT(id_symtab_map.find(m_symtab_counter) == id_symtab_map.end()); + SymbolTable *m_symtab = al.make_new(nullptr); + if (load_symtab_id) m_symtab->counter = m_symtab_counter; + id_symtab_map[m_symtab_counter] = m_symtab; + { + size_t n = self().read_int64(); + for (size_t i=0; i(deserialize_symbol()); + self().symtab_insert_symbol(*m_symtab, name, sym); + } + } + char *m_name; + m_name = self().read_cstring(); + n_dependencies = self().read_int64(); + Vec v_dependencies; + v_dependencies.reserve(al, n_dependencies); + for (size_t i=0; i(); + m_start_name->first = self().read_int64(); + m_start_name->last = self().read_int64(); + Location* m_end_name; + m_end_name = al.make_new(); + m_end_name->first = self().read_int64(); + m_end_name->last = self().read_int64(); + return ASR::make_Module_t(al, loc, m_symtab, m_name, v_dependencies.p, v_dependencies.n, m_loaded_from_mod, m_intrinsic, m_start_name, m_end_name); + } + asr_t* deserialize_Function() { + size_t n_dependencies; // Sequence + size_t n_args; // Sequence + size_t n_body; // Sequence + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + uint64_t m_symtab_counter = self().read_int64(); + LCOMPILERS_ASSERT(id_symtab_map.find(m_symtab_counter) == id_symtab_map.end()); + SymbolTable *m_symtab = al.make_new(nullptr); + if (load_symtab_id) m_symtab->counter = m_symtab_counter; + id_symtab_map[m_symtab_counter] = m_symtab; + { + size_t n = self().read_int64(); + for (size_t i=0; i(deserialize_symbol()); + self().symtab_insert_symbol(*m_symtab, name, sym); + } + } + char *m_name; + m_name = self().read_cstring(); + ASR::ttype_t *m_function_signature; + m_function_signature = ASR::down_cast(self().deserialize_ttype()); + n_dependencies = self().read_int64(); + Vec v_dependencies; + v_dependencies.reserve(al, n_dependencies); + for (size_t i=0; i v_args; + v_args.reserve(al, n_args); + for (size_t i=0; i(self().deserialize_expr())); + } + n_body = self().read_int64(); + Vec v_body; + v_body.reserve(al, n_body); + for (size_t i=0; i(self().deserialize_stmt())); + } + ASR::expr_t *m_return_var; + if (self().read_bool()) { + m_return_var = ASR::down_cast(self().deserialize_expr()); + } else { + m_return_var = nullptr; + } + ASR::accessType m_access = self().deserialize_access(); + bool m_deterministic = self().read_bool(); + bool m_side_effect_free = self().read_bool(); + char *m_module_file; + bool m_module_file_present = self().read_bool(); + if (m_module_file_present) { + m_module_file = self().read_cstring(); + } else { + m_module_file = nullptr; + } + Location* m_start_name; + m_start_name = al.make_new(); + m_start_name->first = self().read_int64(); + m_start_name->last = self().read_int64(); + Location* m_end_name; + m_end_name = al.make_new(); + m_end_name->first = self().read_int64(); + m_end_name->last = self().read_int64(); + return ASR::make_Function_t(al, loc, m_symtab, m_name, m_function_signature, v_dependencies.p, v_dependencies.n, v_args.p, v_args.n, v_body.p, v_body.n, m_return_var, m_access, m_deterministic, m_side_effect_free, m_module_file, m_start_name, m_end_name); + } + asr_t* deserialize_GenericProcedure() { + size_t n_procs; // Sequence + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + uint64_t m_parent_symtab_counter = self().read_int64(); + LCOMPILERS_ASSERT(id_symtab_map.find(m_parent_symtab_counter) != id_symtab_map.end()); + SymbolTable *m_parent_symtab = id_symtab_map[m_parent_symtab_counter]; + char *m_name; + m_name = self().read_cstring(); + n_procs = self().read_int64(); + Vec v_procs; + v_procs.reserve(al, n_procs); + for (size_t i=0; i v_procs; + v_procs.reserve(al, n_procs); + for (size_t i=0; i v_scope_names; + v_scope_names.reserve(al, n_scope_names); + for (size_t i=0; i(nullptr); + if (load_symtab_id) m_symtab->counter = m_symtab_counter; + id_symtab_map[m_symtab_counter] = m_symtab; + { + size_t n = self().read_int64(); + for (size_t i=0; i(deserialize_symbol()); + self().symtab_insert_symbol(*m_symtab, name, sym); + } + } + char *m_name; + m_name = self().read_cstring(); + n_dependencies = self().read_int64(); + Vec v_dependencies; + v_dependencies.reserve(al, n_dependencies); + for (size_t i=0; i v_members; + v_members.reserve(al, n_members); + for (size_t i=0; i v_member_functions; + v_member_functions.reserve(al, n_member_functions); + for (size_t i=0; i v_initializers; + v_initializers.reserve(al, n_initializers); + for (size_t i=0; i(self().deserialize_expr()); + } else { + m_alignment = nullptr; + } + ASR::symbol_t *m_parent; + if (self().read_bool()) { + m_parent = self().read_symbol(); + } else { + m_parent = nullptr; + } + return ASR::make_Struct_t(al, loc, m_symtab, m_name, v_dependencies.p, v_dependencies.n, v_members.p, v_members.n, v_member_functions.p, v_member_functions.n, m_abi, m_access, m_is_packed, m_is_abstract, v_initializers.p, v_initializers.n, m_alignment, m_parent); + } + asr_t* deserialize_Enum() { + size_t n_dependencies; // Sequence + size_t n_members; // Sequence + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + uint64_t m_symtab_counter = self().read_int64(); + LCOMPILERS_ASSERT(id_symtab_map.find(m_symtab_counter) == id_symtab_map.end()); + SymbolTable *m_symtab = al.make_new(nullptr); + if (load_symtab_id) m_symtab->counter = m_symtab_counter; + id_symtab_map[m_symtab_counter] = m_symtab; + { + size_t n = self().read_int64(); + for (size_t i=0; i(deserialize_symbol()); + self().symtab_insert_symbol(*m_symtab, name, sym); + } + } + char *m_name; + m_name = self().read_cstring(); + n_dependencies = self().read_int64(); + Vec v_dependencies; + v_dependencies.reserve(al, n_dependencies); + for (size_t i=0; i v_members; + v_members.reserve(al, n_members); + for (size_t i=0; i(self().deserialize_ttype()); + ASR::symbol_t *m_parent; + if (self().read_bool()) { + m_parent = self().read_symbol(); + } else { + m_parent = nullptr; + } + return ASR::make_Enum_t(al, loc, m_symtab, m_name, v_dependencies.p, v_dependencies.n, v_members.p, v_members.n, m_abi, m_access, m_enum_value_type, m_type, m_parent); + } + asr_t* deserialize_Union() { + size_t n_dependencies; // Sequence + size_t n_members; // Sequence + size_t n_initializers; // Sequence + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + uint64_t m_symtab_counter = self().read_int64(); + LCOMPILERS_ASSERT(id_symtab_map.find(m_symtab_counter) == id_symtab_map.end()); + SymbolTable *m_symtab = al.make_new(nullptr); + if (load_symtab_id) m_symtab->counter = m_symtab_counter; + id_symtab_map[m_symtab_counter] = m_symtab; + { + size_t n = self().read_int64(); + for (size_t i=0; i(deserialize_symbol()); + self().symtab_insert_symbol(*m_symtab, name, sym); + } + } + char *m_name; + m_name = self().read_cstring(); + n_dependencies = self().read_int64(); + Vec v_dependencies; + v_dependencies.reserve(al, n_dependencies); + for (size_t i=0; i v_members; + v_members.reserve(al, n_members); + for (size_t i=0; i v_initializers; + v_initializers.reserve(al, n_initializers); + for (size_t i=0; i v_dependencies; + v_dependencies.reserve(al, n_dependencies); + for (size_t i=0; i(self().deserialize_expr()); + } else { + m_symbolic_value = nullptr; + } + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + ASR::storage_typeType m_storage = self().deserialize_storage_type(); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::symbol_t *m_type_declaration; + if (self().read_bool()) { + m_type_declaration = self().read_symbol(); + } else { + m_type_declaration = nullptr; + } + ASR::abiType m_abi = self().deserialize_abi(); + ASR::accessType m_access = self().deserialize_access(); + ASR::presenceType m_presence = self().deserialize_presence(); + bool m_value_attr = self().read_bool(); + bool m_target_attr = self().read_bool(); + return ASR::make_Variable_t(al, loc, m_parent_symtab, m_name, v_dependencies.p, v_dependencies.n, m_intent, m_symbolic_value, m_value, m_storage, m_type, m_type_declaration, m_abi, m_access, m_presence, m_value_attr, m_target_attr); + } + asr_t* deserialize_Class() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + uint64_t m_symtab_counter = self().read_int64(); + LCOMPILERS_ASSERT(id_symtab_map.find(m_symtab_counter) == id_symtab_map.end()); + SymbolTable *m_symtab = al.make_new(nullptr); + if (load_symtab_id) m_symtab->counter = m_symtab_counter; + id_symtab_map[m_symtab_counter] = m_symtab; + { + size_t n = self().read_int64(); + for (size_t i=0; i(deserialize_symbol()); + self().symtab_insert_symbol(*m_symtab, name, sym); + } + } + char *m_name; + m_name = self().read_cstring(); + ASR::abiType m_abi = self().deserialize_abi(); + ASR::accessType m_access = self().deserialize_access(); + return ASR::make_Class_t(al, loc, m_symtab, m_name, m_abi, m_access); + } + asr_t* deserialize_ClassProcedure() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + uint64_t m_parent_symtab_counter = self().read_int64(); + LCOMPILERS_ASSERT(id_symtab_map.find(m_parent_symtab_counter) != id_symtab_map.end()); + SymbolTable *m_parent_symtab = id_symtab_map[m_parent_symtab_counter]; + char *m_name; + m_name = self().read_cstring(); + char *m_self_argument; + bool m_self_argument_present = self().read_bool(); + if (m_self_argument_present) { + m_self_argument = self().read_cstring(); + } else { + m_self_argument = nullptr; + } + char *m_proc_name; + m_proc_name = self().read_cstring(); + ASR::symbol_t *m_proc; + m_proc = self().read_symbol(); + ASR::abiType m_abi = self().deserialize_abi(); + bool m_is_deferred = self().read_bool(); + bool m_is_nopass = self().read_bool(); + return ASR::make_ClassProcedure_t(al, loc, m_parent_symtab, m_name, m_self_argument, m_proc_name, m_proc, m_abi, m_is_deferred, m_is_nopass); + } + asr_t* deserialize_AssociateBlock() { + size_t n_body; // Sequence + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + uint64_t m_symtab_counter = self().read_int64(); + LCOMPILERS_ASSERT(id_symtab_map.find(m_symtab_counter) == id_symtab_map.end()); + SymbolTable *m_symtab = al.make_new(nullptr); + if (load_symtab_id) m_symtab->counter = m_symtab_counter; + id_symtab_map[m_symtab_counter] = m_symtab; + { + size_t n = self().read_int64(); + for (size_t i=0; i(deserialize_symbol()); + self().symtab_insert_symbol(*m_symtab, name, sym); + } + } + char *m_name; + m_name = self().read_cstring(); + n_body = self().read_int64(); + Vec v_body; + v_body.reserve(al, n_body); + for (size_t i=0; i(self().deserialize_stmt())); + } + return ASR::make_AssociateBlock_t(al, loc, m_symtab, m_name, v_body.p, v_body.n); + } + asr_t* deserialize_Block() { + size_t n_body; // Sequence + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + uint64_t m_symtab_counter = self().read_int64(); + LCOMPILERS_ASSERT(id_symtab_map.find(m_symtab_counter) == id_symtab_map.end()); + SymbolTable *m_symtab = al.make_new(nullptr); + if (load_symtab_id) m_symtab->counter = m_symtab_counter; + id_symtab_map[m_symtab_counter] = m_symtab; + { + size_t n = self().read_int64(); + for (size_t i=0; i(deserialize_symbol()); + self().symtab_insert_symbol(*m_symtab, name, sym); + } + } + char *m_name; + m_name = self().read_cstring(); + n_body = self().read_int64(); + Vec v_body; + v_body.reserve(al, n_body); + for (size_t i=0; i(self().deserialize_stmt())); + } + return ASR::make_Block_t(al, loc, m_symtab, m_name, v_body.p, v_body.n); + } + asr_t* deserialize_Requirement() { + size_t n_args; // Sequence + size_t n_requires; // Sequence + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + uint64_t m_symtab_counter = self().read_int64(); + LCOMPILERS_ASSERT(id_symtab_map.find(m_symtab_counter) == id_symtab_map.end()); + SymbolTable *m_symtab = al.make_new(nullptr); + if (load_symtab_id) m_symtab->counter = m_symtab_counter; + id_symtab_map[m_symtab_counter] = m_symtab; + { + size_t n = self().read_int64(); + for (size_t i=0; i(deserialize_symbol()); + self().symtab_insert_symbol(*m_symtab, name, sym); + } + } + char *m_name; + m_name = self().read_cstring(); + n_args = self().read_int64(); + Vec v_args; + v_args.reserve(al, n_args); + for (size_t i=0; i v_requires; + v_requires.reserve(al, n_requires); + for (size_t i=0; i(self().deserialize_require_instantiation())); + } + return ASR::make_Requirement_t(al, loc, m_symtab, m_name, v_args.p, v_args.n, v_requires.p, v_requires.n); + } + asr_t* deserialize_Template() { + size_t n_args; // Sequence + size_t n_requires; // Sequence + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + uint64_t m_symtab_counter = self().read_int64(); + LCOMPILERS_ASSERT(id_symtab_map.find(m_symtab_counter) == id_symtab_map.end()); + SymbolTable *m_symtab = al.make_new(nullptr); + if (load_symtab_id) m_symtab->counter = m_symtab_counter; + id_symtab_map[m_symtab_counter] = m_symtab; + { + size_t n = self().read_int64(); + for (size_t i=0; i(deserialize_symbol()); + self().symtab_insert_symbol(*m_symtab, name, sym); + } + } + char *m_name; + m_name = self().read_cstring(); + n_args = self().read_int64(); + Vec v_args; + v_args.reserve(al, n_args); + for (size_t i=0; i v_requires; + v_requires.reserve(al, n_requires); + for (size_t i=0; i(self().deserialize_require_instantiation())); + } + return ASR::make_Template_t(al, loc, m_symtab, m_name, v_args.p, v_args.n, v_requires.p, v_requires.n); + } + asr_t* deserialize_symbol() { + uint8_t t = self().read_int8(); + ASR::symbolType ty = static_cast(t); + switch (ty) { + case (ASR::symbolType::Program) : return self().deserialize_Program(); + case (ASR::symbolType::Module) : return self().deserialize_Module(); + case (ASR::symbolType::Function) : return self().deserialize_Function(); + case (ASR::symbolType::GenericProcedure) : return self().deserialize_GenericProcedure(); + case (ASR::symbolType::CustomOperator) : return self().deserialize_CustomOperator(); + case (ASR::symbolType::ExternalSymbol) : return self().deserialize_ExternalSymbol(); + case (ASR::symbolType::Struct) : return self().deserialize_Struct(); + case (ASR::symbolType::Enum) : return self().deserialize_Enum(); + case (ASR::symbolType::Union) : return self().deserialize_Union(); + case (ASR::symbolType::Variable) : return self().deserialize_Variable(); + case (ASR::symbolType::Class) : return self().deserialize_Class(); + case (ASR::symbolType::ClassProcedure) : return self().deserialize_ClassProcedure(); + case (ASR::symbolType::AssociateBlock) : return self().deserialize_AssociateBlock(); + case (ASR::symbolType::Block) : return self().deserialize_Block(); + case (ASR::symbolType::Requirement) : return self().deserialize_Requirement(); + case (ASR::symbolType::Template) : return self().deserialize_Template(); + default : throw LCompilersException("Unknown type in deserialize_symbol()"); + } + throw LCompilersException("Switch statement above was not exhaustive."); + } + asr_t* deserialize_Allocate() { + size_t n_args; // Sequence + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + n_args = self().read_int64(); + Vec v_args; + v_args.reserve(al, n_args); + for (size_t i=0; i(self().deserialize_expr()); + } else { + m_stat = nullptr; + } + ASR::expr_t *m_errmsg; + if (self().read_bool()) { + m_errmsg = ASR::down_cast(self().deserialize_expr()); + } else { + m_errmsg = nullptr; + } + ASR::expr_t *m_source; + if (self().read_bool()) { + m_source = ASR::down_cast(self().deserialize_expr()); + } else { + m_source = nullptr; + } + return ASR::make_Allocate_t(al, loc, v_args.p, v_args.n, m_stat, m_errmsg, m_source); + } + asr_t* deserialize_ReAlloc() { + size_t n_args; // Sequence + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + n_args = self().read_int64(); + Vec v_args; + v_args.reserve(al, n_args); + for (size_t i=0; i(self().deserialize_expr()); + ASR::expr_t *m_value; + m_value = ASR::down_cast(self().deserialize_expr()); + ASR::stmt_t *m_overloaded; + if (self().read_bool()) { + m_overloaded = ASR::down_cast(self().deserialize_stmt()); + } else { + m_overloaded = nullptr; + } + return ASR::make_Assignment_t(al, loc, m_target, m_value, m_overloaded); + } + asr_t* deserialize_Associate() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_target; + m_target = ASR::down_cast(self().deserialize_expr()); + ASR::expr_t *m_value; + m_value = ASR::down_cast(self().deserialize_expr()); + return ASR::make_Associate_t(al, loc, m_target, m_value); + } + asr_t* deserialize_Cycle() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + char *m_stmt_name; + bool m_stmt_name_present = self().read_bool(); + if (m_stmt_name_present) { + m_stmt_name = self().read_cstring(); + } else { + m_stmt_name = nullptr; + } + return ASR::make_Cycle_t(al, loc, m_stmt_name); + } + asr_t* deserialize_ExplicitDeallocate() { + size_t n_vars; // Sequence + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + n_vars = self().read_int64(); + Vec v_vars; + v_vars.reserve(al, n_vars); + for (size_t i=0; i(self().deserialize_expr())); + } + return ASR::make_ExplicitDeallocate_t(al, loc, v_vars.p, v_vars.n); + } + asr_t* deserialize_ImplicitDeallocate() { + size_t n_vars; // Sequence + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + n_vars = self().read_int64(); + Vec v_vars; + v_vars.reserve(al, n_vars); + for (size_t i=0; i(self().deserialize_expr())); + } + return ASR::make_ImplicitDeallocate_t(al, loc, v_vars.p, v_vars.n); + } + asr_t* deserialize_DoConcurrentLoop() { + size_t n_head; // Sequence + size_t n_shared; // Sequence + size_t n_local; // Sequence + size_t n_reduction; // Sequence + size_t n_body; // Sequence + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + n_head = self().read_int64(); + Vec v_head; + v_head.reserve(al, n_head); + for (size_t i=0; i v_shared; + v_shared.reserve(al, n_shared); + for (size_t i=0; i(self().deserialize_expr())); + } + n_local = self().read_int64(); + Vec v_local; + v_local.reserve(al, n_local); + for (size_t i=0; i(self().deserialize_expr())); + } + n_reduction = self().read_int64(); + Vec v_reduction; + v_reduction.reserve(al, n_reduction); + for (size_t i=0; i v_body; + v_body.reserve(al, n_body); + for (size_t i=0; i(self().deserialize_stmt())); + } + return ASR::make_DoConcurrentLoop_t(al, loc, v_head.p, v_head.n, v_shared.p, v_shared.n, v_local.p, v_local.n, v_reduction.p, v_reduction.n, v_body.p, v_body.n); + } + asr_t* deserialize_DoLoop() { + size_t n_body; // Sequence + size_t n_orelse; // Sequence + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + char *m_name; + bool m_name_present = self().read_bool(); + if (m_name_present) { + m_name = self().read_cstring(); + } else { + m_name = nullptr; + } + ASR::do_loop_head_t m_head = self().deserialize_do_loop_head(); + n_body = self().read_int64(); + Vec v_body; + v_body.reserve(al, n_body); + for (size_t i=0; i(self().deserialize_stmt())); + } + n_orelse = self().read_int64(); + Vec v_orelse; + v_orelse.reserve(al, n_orelse); + for (size_t i=0; i(self().deserialize_stmt())); + } + return ASR::make_DoLoop_t(al, loc, m_name, m_head, v_body.p, v_body.n, v_orelse.p, v_orelse.n); + } + asr_t* deserialize_ErrorStop() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_code; + if (self().read_bool()) { + m_code = ASR::down_cast(self().deserialize_expr()); + } else { + m_code = nullptr; + } + return ASR::make_ErrorStop_t(al, loc, m_code); + } + asr_t* deserialize_Exit() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + char *m_stmt_name; + bool m_stmt_name_present = self().read_bool(); + if (m_stmt_name_present) { + m_stmt_name = self().read_cstring(); + } else { + m_stmt_name = nullptr; + } + return ASR::make_Exit_t(al, loc, m_stmt_name); + } + asr_t* deserialize_ForAllSingle() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::do_loop_head_t m_head = self().deserialize_do_loop_head(); + ASR::stmt_t *m_assign_stmt; + m_assign_stmt = ASR::down_cast(self().deserialize_stmt()); + return ASR::make_ForAllSingle_t(al, loc, m_head, m_assign_stmt); + } + asr_t* deserialize_ForEach() { + size_t n_body; // Sequence + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_var; + m_var = ASR::down_cast(self().deserialize_expr()); + ASR::expr_t *m_container; + m_container = ASR::down_cast(self().deserialize_expr()); + n_body = self().read_int64(); + Vec v_body; + v_body.reserve(al, n_body); + for (size_t i=0; i(self().deserialize_stmt())); + } + return ASR::make_ForEach_t(al, loc, m_var, m_container, v_body.p, v_body.n); + } + asr_t* deserialize_GoTo() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + int64_t m_target_id = self().read_int64(); + char *m_name; + m_name = self().read_cstring(); + return ASR::make_GoTo_t(al, loc, m_target_id, m_name); + } + asr_t* deserialize_GoToTarget() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + int64_t m_id = self().read_int64(); + char *m_name; + m_name = self().read_cstring(); + return ASR::make_GoToTarget_t(al, loc, m_id, m_name); + } + asr_t* deserialize_If() { + size_t n_body; // Sequence + size_t n_orelse; // Sequence + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_test; + m_test = ASR::down_cast(self().deserialize_expr()); + n_body = self().read_int64(); + Vec v_body; + v_body.reserve(al, n_body); + for (size_t i=0; i(self().deserialize_stmt())); + } + n_orelse = self().read_int64(); + Vec v_orelse; + v_orelse.reserve(al, n_orelse); + for (size_t i=0; i(self().deserialize_stmt())); + } + return ASR::make_If_t(al, loc, m_test, v_body.p, v_body.n, v_orelse.p, v_orelse.n); + } + asr_t* deserialize_IfArithmetic() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_test; + m_test = ASR::down_cast(self().deserialize_expr()); + int64_t m_lt_label = self().read_int64(); + int64_t m_eq_label = self().read_int64(); + int64_t m_gt_label = self().read_int64(); + return ASR::make_IfArithmetic_t(al, loc, m_test, m_lt_label, m_eq_label, m_gt_label); + } + asr_t* deserialize_Print() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_text; + m_text = ASR::down_cast(self().deserialize_expr()); + return ASR::make_Print_t(al, loc, m_text); + } + asr_t* deserialize_FileOpen() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + int64_t m_label = self().read_int64(); + ASR::expr_t *m_newunit; + if (self().read_bool()) { + m_newunit = ASR::down_cast(self().deserialize_expr()); + } else { + m_newunit = nullptr; + } + ASR::expr_t *m_filename; + if (self().read_bool()) { + m_filename = ASR::down_cast(self().deserialize_expr()); + } else { + m_filename = nullptr; + } + ASR::expr_t *m_status; + if (self().read_bool()) { + m_status = ASR::down_cast(self().deserialize_expr()); + } else { + m_status = nullptr; + } + ASR::expr_t *m_form; + if (self().read_bool()) { + m_form = ASR::down_cast(self().deserialize_expr()); + } else { + m_form = nullptr; + } + return ASR::make_FileOpen_t(al, loc, m_label, m_newunit, m_filename, m_status, m_form); + } + asr_t* deserialize_FileClose() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + int64_t m_label = self().read_int64(); + ASR::expr_t *m_unit; + if (self().read_bool()) { + m_unit = ASR::down_cast(self().deserialize_expr()); + } else { + m_unit = nullptr; + } + ASR::expr_t *m_iostat; + if (self().read_bool()) { + m_iostat = ASR::down_cast(self().deserialize_expr()); + } else { + m_iostat = nullptr; + } + ASR::expr_t *m_iomsg; + if (self().read_bool()) { + m_iomsg = ASR::down_cast(self().deserialize_expr()); + } else { + m_iomsg = nullptr; + } + ASR::expr_t *m_err; + if (self().read_bool()) { + m_err = ASR::down_cast(self().deserialize_expr()); + } else { + m_err = nullptr; + } + ASR::expr_t *m_status; + if (self().read_bool()) { + m_status = ASR::down_cast(self().deserialize_expr()); + } else { + m_status = nullptr; + } + return ASR::make_FileClose_t(al, loc, m_label, m_unit, m_iostat, m_iomsg, m_err, m_status); + } + asr_t* deserialize_FileRead() { + size_t n_values; // Sequence + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + int64_t m_label = self().read_int64(); + ASR::expr_t *m_unit; + if (self().read_bool()) { + m_unit = ASR::down_cast(self().deserialize_expr()); + } else { + m_unit = nullptr; + } + ASR::expr_t *m_fmt; + if (self().read_bool()) { + m_fmt = ASR::down_cast(self().deserialize_expr()); + } else { + m_fmt = nullptr; + } + ASR::expr_t *m_iomsg; + if (self().read_bool()) { + m_iomsg = ASR::down_cast(self().deserialize_expr()); + } else { + m_iomsg = nullptr; + } + ASR::expr_t *m_iostat; + if (self().read_bool()) { + m_iostat = ASR::down_cast(self().deserialize_expr()); + } else { + m_iostat = nullptr; + } + ASR::expr_t *m_size; + if (self().read_bool()) { + m_size = ASR::down_cast(self().deserialize_expr()); + } else { + m_size = nullptr; + } + ASR::expr_t *m_id; + if (self().read_bool()) { + m_id = ASR::down_cast(self().deserialize_expr()); + } else { + m_id = nullptr; + } + n_values = self().read_int64(); + Vec v_values; + v_values.reserve(al, n_values); + for (size_t i=0; i(self().deserialize_expr())); + } + ASR::stmt_t *m_overloaded; + if (self().read_bool()) { + m_overloaded = ASR::down_cast(self().deserialize_stmt()); + } else { + m_overloaded = nullptr; + } + return ASR::make_FileRead_t(al, loc, m_label, m_unit, m_fmt, m_iomsg, m_iostat, m_size, m_id, v_values.p, v_values.n, m_overloaded); + } + asr_t* deserialize_FileBackspace() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + int64_t m_label = self().read_int64(); + ASR::expr_t *m_unit; + if (self().read_bool()) { + m_unit = ASR::down_cast(self().deserialize_expr()); + } else { + m_unit = nullptr; + } + ASR::expr_t *m_iostat; + if (self().read_bool()) { + m_iostat = ASR::down_cast(self().deserialize_expr()); + } else { + m_iostat = nullptr; + } + ASR::expr_t *m_err; + if (self().read_bool()) { + m_err = ASR::down_cast(self().deserialize_expr()); + } else { + m_err = nullptr; + } + return ASR::make_FileBackspace_t(al, loc, m_label, m_unit, m_iostat, m_err); + } + asr_t* deserialize_FileRewind() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + int64_t m_label = self().read_int64(); + ASR::expr_t *m_unit; + if (self().read_bool()) { + m_unit = ASR::down_cast(self().deserialize_expr()); + } else { + m_unit = nullptr; + } + ASR::expr_t *m_iostat; + if (self().read_bool()) { + m_iostat = ASR::down_cast(self().deserialize_expr()); + } else { + m_iostat = nullptr; + } + ASR::expr_t *m_err; + if (self().read_bool()) { + m_err = ASR::down_cast(self().deserialize_expr()); + } else { + m_err = nullptr; + } + return ASR::make_FileRewind_t(al, loc, m_label, m_unit, m_iostat, m_err); + } + asr_t* deserialize_FileInquire() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + int64_t m_label = self().read_int64(); + ASR::expr_t *m_unit; + if (self().read_bool()) { + m_unit = ASR::down_cast(self().deserialize_expr()); + } else { + m_unit = nullptr; + } + ASR::expr_t *m_file; + if (self().read_bool()) { + m_file = ASR::down_cast(self().deserialize_expr()); + } else { + m_file = nullptr; + } + ASR::expr_t *m_iostat; + if (self().read_bool()) { + m_iostat = ASR::down_cast(self().deserialize_expr()); + } else { + m_iostat = nullptr; + } + ASR::expr_t *m_err; + if (self().read_bool()) { + m_err = ASR::down_cast(self().deserialize_expr()); + } else { + m_err = nullptr; + } + ASR::expr_t *m_exist; + if (self().read_bool()) { + m_exist = ASR::down_cast(self().deserialize_expr()); + } else { + m_exist = nullptr; + } + ASR::expr_t *m_opened; + if (self().read_bool()) { + m_opened = ASR::down_cast(self().deserialize_expr()); + } else { + m_opened = nullptr; + } + ASR::expr_t *m_number; + if (self().read_bool()) { + m_number = ASR::down_cast(self().deserialize_expr()); + } else { + m_number = nullptr; + } + ASR::expr_t *m_named; + if (self().read_bool()) { + m_named = ASR::down_cast(self().deserialize_expr()); + } else { + m_named = nullptr; + } + ASR::expr_t *m_name; + if (self().read_bool()) { + m_name = ASR::down_cast(self().deserialize_expr()); + } else { + m_name = nullptr; + } + ASR::expr_t *m_access; + if (self().read_bool()) { + m_access = ASR::down_cast(self().deserialize_expr()); + } else { + m_access = nullptr; + } + ASR::expr_t *m_sequential; + if (self().read_bool()) { + m_sequential = ASR::down_cast(self().deserialize_expr()); + } else { + m_sequential = nullptr; + } + ASR::expr_t *m_direct; + if (self().read_bool()) { + m_direct = ASR::down_cast(self().deserialize_expr()); + } else { + m_direct = nullptr; + } + ASR::expr_t *m_form; + if (self().read_bool()) { + m_form = ASR::down_cast(self().deserialize_expr()); + } else { + m_form = nullptr; + } + ASR::expr_t *m_formatted; + if (self().read_bool()) { + m_formatted = ASR::down_cast(self().deserialize_expr()); + } else { + m_formatted = nullptr; + } + ASR::expr_t *m_unformatted; + if (self().read_bool()) { + m_unformatted = ASR::down_cast(self().deserialize_expr()); + } else { + m_unformatted = nullptr; + } + ASR::expr_t *m_recl; + if (self().read_bool()) { + m_recl = ASR::down_cast(self().deserialize_expr()); + } else { + m_recl = nullptr; + } + ASR::expr_t *m_nextrec; + if (self().read_bool()) { + m_nextrec = ASR::down_cast(self().deserialize_expr()); + } else { + m_nextrec = nullptr; + } + ASR::expr_t *m_blank; + if (self().read_bool()) { + m_blank = ASR::down_cast(self().deserialize_expr()); + } else { + m_blank = nullptr; + } + ASR::expr_t *m_position; + if (self().read_bool()) { + m_position = ASR::down_cast(self().deserialize_expr()); + } else { + m_position = nullptr; + } + ASR::expr_t *m_action; + if (self().read_bool()) { + m_action = ASR::down_cast(self().deserialize_expr()); + } else { + m_action = nullptr; + } + ASR::expr_t *m_read; + if (self().read_bool()) { + m_read = ASR::down_cast(self().deserialize_expr()); + } else { + m_read = nullptr; + } + ASR::expr_t *m_write; + if (self().read_bool()) { + m_write = ASR::down_cast(self().deserialize_expr()); + } else { + m_write = nullptr; + } + ASR::expr_t *m_readwrite; + if (self().read_bool()) { + m_readwrite = ASR::down_cast(self().deserialize_expr()); + } else { + m_readwrite = nullptr; + } + ASR::expr_t *m_delim; + if (self().read_bool()) { + m_delim = ASR::down_cast(self().deserialize_expr()); + } else { + m_delim = nullptr; + } + ASR::expr_t *m_pad; + if (self().read_bool()) { + m_pad = ASR::down_cast(self().deserialize_expr()); + } else { + m_pad = nullptr; + } + ASR::expr_t *m_flen; + if (self().read_bool()) { + m_flen = ASR::down_cast(self().deserialize_expr()); + } else { + m_flen = nullptr; + } + ASR::expr_t *m_blocksize; + if (self().read_bool()) { + m_blocksize = ASR::down_cast(self().deserialize_expr()); + } else { + m_blocksize = nullptr; + } + ASR::expr_t *m_convert; + if (self().read_bool()) { + m_convert = ASR::down_cast(self().deserialize_expr()); + } else { + m_convert = nullptr; + } + ASR::expr_t *m_carriagecontrol; + if (self().read_bool()) { + m_carriagecontrol = ASR::down_cast(self().deserialize_expr()); + } else { + m_carriagecontrol = nullptr; + } + ASR::expr_t *m_size; + if (self().read_bool()) { + m_size = ASR::down_cast(self().deserialize_expr()); + } else { + m_size = nullptr; + } + ASR::expr_t *m_iolength; + if (self().read_bool()) { + m_iolength = ASR::down_cast(self().deserialize_expr()); + } else { + m_iolength = nullptr; + } + return ASR::make_FileInquire_t(al, loc, m_label, m_unit, m_file, m_iostat, m_err, m_exist, m_opened, m_number, m_named, m_name, m_access, m_sequential, m_direct, m_form, m_formatted, m_unformatted, m_recl, m_nextrec, m_blank, m_position, m_action, m_read, m_write, m_readwrite, m_delim, m_pad, m_flen, m_blocksize, m_convert, m_carriagecontrol, m_size, m_iolength); + } + asr_t* deserialize_FileWrite() { + size_t n_values; // Sequence + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + int64_t m_label = self().read_int64(); + ASR::expr_t *m_unit; + if (self().read_bool()) { + m_unit = ASR::down_cast(self().deserialize_expr()); + } else { + m_unit = nullptr; + } + ASR::expr_t *m_iomsg; + if (self().read_bool()) { + m_iomsg = ASR::down_cast(self().deserialize_expr()); + } else { + m_iomsg = nullptr; + } + ASR::expr_t *m_iostat; + if (self().read_bool()) { + m_iostat = ASR::down_cast(self().deserialize_expr()); + } else { + m_iostat = nullptr; + } + ASR::expr_t *m_id; + if (self().read_bool()) { + m_id = ASR::down_cast(self().deserialize_expr()); + } else { + m_id = nullptr; + } + n_values = self().read_int64(); + Vec v_values; + v_values.reserve(al, n_values); + for (size_t i=0; i(self().deserialize_expr())); + } + ASR::expr_t *m_separator; + if (self().read_bool()) { + m_separator = ASR::down_cast(self().deserialize_expr()); + } else { + m_separator = nullptr; + } + ASR::expr_t *m_end; + if (self().read_bool()) { + m_end = ASR::down_cast(self().deserialize_expr()); + } else { + m_end = nullptr; + } + ASR::stmt_t *m_overloaded; + if (self().read_bool()) { + m_overloaded = ASR::down_cast(self().deserialize_stmt()); + } else { + m_overloaded = nullptr; + } + return ASR::make_FileWrite_t(al, loc, m_label, m_unit, m_iomsg, m_iostat, m_id, v_values.p, v_values.n, m_separator, m_end, m_overloaded); + } + asr_t* deserialize_Return() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + return ASR::make_Return_t(al, loc); + } + asr_t* deserialize_Select() { + size_t n_body; // Sequence + size_t n_default; // Sequence + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_test; + m_test = ASR::down_cast(self().deserialize_expr()); + n_body = self().read_int64(); + Vec v_body; + v_body.reserve(al, n_body); + for (size_t i=0; i(self().deserialize_case_stmt())); + } + n_default = self().read_int64(); + Vec v_default; + v_default.reserve(al, n_default); + for (size_t i=0; i(self().deserialize_stmt())); + } + bool m_enable_fall_through = self().read_bool(); + return ASR::make_Select_t(al, loc, m_test, v_body.p, v_body.n, v_default.p, v_default.n, m_enable_fall_through); + } + asr_t* deserialize_Stop() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_code; + if (self().read_bool()) { + m_code = ASR::down_cast(self().deserialize_expr()); + } else { + m_code = nullptr; + } + return ASR::make_Stop_t(al, loc, m_code); + } + asr_t* deserialize_Assert() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_test; + m_test = ASR::down_cast(self().deserialize_expr()); + ASR::expr_t *m_msg; + if (self().read_bool()) { + m_msg = ASR::down_cast(self().deserialize_expr()); + } else { + m_msg = nullptr; + } + return ASR::make_Assert_t(al, loc, m_test, m_msg); + } + asr_t* deserialize_SubroutineCall() { + size_t n_args; // Sequence + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::symbol_t *m_name; + m_name = self().read_symbol(); + ASR::symbol_t *m_original_name; + if (self().read_bool()) { + m_original_name = self().read_symbol(); + } else { + m_original_name = nullptr; + } + n_args = self().read_int64(); + Vec v_args; + v_args.reserve(al, n_args); + for (size_t i=0; i(self().deserialize_expr()); + } else { + m_dt = nullptr; + } + return ASR::make_SubroutineCall_t(al, loc, m_name, m_original_name, v_args.p, v_args.n, m_dt); + } + asr_t* deserialize_IntrinsicImpureSubroutine() { + size_t n_args; // Sequence + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + int64_t m_sub_intrinsic_id = self().read_int64(); + n_args = self().read_int64(); + Vec v_args; + v_args.reserve(al, n_args); + for (size_t i=0; i(self().deserialize_expr())); + } + int64_t m_overload_id = self().read_int64(); + return ASR::make_IntrinsicImpureSubroutine_t(al, loc, m_sub_intrinsic_id, v_args.p, v_args.n, m_overload_id); + } + asr_t* deserialize_Where() { + size_t n_body; // Sequence + size_t n_orelse; // Sequence + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_test; + m_test = ASR::down_cast(self().deserialize_expr()); + n_body = self().read_int64(); + Vec v_body; + v_body.reserve(al, n_body); + for (size_t i=0; i(self().deserialize_stmt())); + } + n_orelse = self().read_int64(); + Vec v_orelse; + v_orelse.reserve(al, n_orelse); + for (size_t i=0; i(self().deserialize_stmt())); + } + return ASR::make_Where_t(al, loc, m_test, v_body.p, v_body.n, v_orelse.p, v_orelse.n); + } + asr_t* deserialize_WhileLoop() { + size_t n_body; // Sequence + size_t n_orelse; // Sequence + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + char *m_name; + bool m_name_present = self().read_bool(); + if (m_name_present) { + m_name = self().read_cstring(); + } else { + m_name = nullptr; + } + ASR::expr_t *m_test; + m_test = ASR::down_cast(self().deserialize_expr()); + n_body = self().read_int64(); + Vec v_body; + v_body.reserve(al, n_body); + for (size_t i=0; i(self().deserialize_stmt())); + } + n_orelse = self().read_int64(); + Vec v_orelse; + v_orelse.reserve(al, n_orelse); + for (size_t i=0; i(self().deserialize_stmt())); + } + return ASR::make_WhileLoop_t(al, loc, m_name, m_test, v_body.p, v_body.n, v_orelse.p, v_orelse.n); + } + asr_t* deserialize_Nullify() { + size_t n_vars; // Sequence + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + n_vars = self().read_int64(); + Vec v_vars; + v_vars.reserve(al, n_vars); + for (size_t i=0; i(self().deserialize_expr())); + } + return ASR::make_Nullify_t(al, loc, v_vars.p, v_vars.n); + } + asr_t* deserialize_Flush() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + int64_t m_label = self().read_int64(); + ASR::expr_t *m_unit; + m_unit = ASR::down_cast(self().deserialize_expr()); + ASR::expr_t *m_err; + if (self().read_bool()) { + m_err = ASR::down_cast(self().deserialize_expr()); + } else { + m_err = nullptr; + } + ASR::expr_t *m_iomsg; + if (self().read_bool()) { + m_iomsg = ASR::down_cast(self().deserialize_expr()); + } else { + m_iomsg = nullptr; + } + ASR::expr_t *m_iostat; + if (self().read_bool()) { + m_iostat = ASR::down_cast(self().deserialize_expr()); + } else { + m_iostat = nullptr; + } + return ASR::make_Flush_t(al, loc, m_label, m_unit, m_err, m_iomsg, m_iostat); + } + asr_t* deserialize_ListAppend() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_a; + m_a = ASR::down_cast(self().deserialize_expr()); + ASR::expr_t *m_ele; + m_ele = ASR::down_cast(self().deserialize_expr()); + return ASR::make_ListAppend_t(al, loc, m_a, m_ele); + } + asr_t* deserialize_AssociateBlockCall() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::symbol_t *m_m; + m_m = self().read_symbol(); + return ASR::make_AssociateBlockCall_t(al, loc, m_m); + } + asr_t* deserialize_SelectType() { + size_t n_body; // Sequence + size_t n_default; // Sequence + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_selector; + m_selector = ASR::down_cast(self().deserialize_expr()); + n_body = self().read_int64(); + Vec v_body; + v_body.reserve(al, n_body); + for (size_t i=0; i(self().deserialize_type_stmt())); + } + n_default = self().read_int64(); + Vec v_default; + v_default.reserve(al, n_default); + for (size_t i=0; i(self().deserialize_stmt())); + } + return ASR::make_SelectType_t(al, loc, m_selector, v_body.p, v_body.n, v_default.p, v_default.n); + } + asr_t* deserialize_CPtrToPointer() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_cptr; + m_cptr = ASR::down_cast(self().deserialize_expr()); + ASR::expr_t *m_ptr; + m_ptr = ASR::down_cast(self().deserialize_expr()); + ASR::expr_t *m_shape; + if (self().read_bool()) { + m_shape = ASR::down_cast(self().deserialize_expr()); + } else { + m_shape = nullptr; + } + ASR::expr_t *m_lower_bounds; + if (self().read_bool()) { + m_lower_bounds = ASR::down_cast(self().deserialize_expr()); + } else { + m_lower_bounds = nullptr; + } + return ASR::make_CPtrToPointer_t(al, loc, m_cptr, m_ptr, m_shape, m_lower_bounds); + } + asr_t* deserialize_BlockCall() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + int64_t m_label = self().read_int64(); + ASR::symbol_t *m_m; + m_m = self().read_symbol(); + return ASR::make_BlockCall_t(al, loc, m_label, m_m); + } + asr_t* deserialize_SetInsert() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_a; + m_a = ASR::down_cast(self().deserialize_expr()); + ASR::expr_t *m_ele; + m_ele = ASR::down_cast(self().deserialize_expr()); + return ASR::make_SetInsert_t(al, loc, m_a, m_ele); + } + asr_t* deserialize_SetRemove() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_a; + m_a = ASR::down_cast(self().deserialize_expr()); + ASR::expr_t *m_ele; + m_ele = ASR::down_cast(self().deserialize_expr()); + return ASR::make_SetRemove_t(al, loc, m_a, m_ele); + } + asr_t* deserialize_SetDiscard() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_a; + m_a = ASR::down_cast(self().deserialize_expr()); + ASR::expr_t *m_ele; + m_ele = ASR::down_cast(self().deserialize_expr()); + return ASR::make_SetDiscard_t(al, loc, m_a, m_ele); + } + asr_t* deserialize_ListInsert() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_a; + m_a = ASR::down_cast(self().deserialize_expr()); + ASR::expr_t *m_pos; + m_pos = ASR::down_cast(self().deserialize_expr()); + ASR::expr_t *m_ele; + m_ele = ASR::down_cast(self().deserialize_expr()); + return ASR::make_ListInsert_t(al, loc, m_a, m_pos, m_ele); + } + asr_t* deserialize_ListRemove() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_a; + m_a = ASR::down_cast(self().deserialize_expr()); + ASR::expr_t *m_ele; + m_ele = ASR::down_cast(self().deserialize_expr()); + return ASR::make_ListRemove_t(al, loc, m_a, m_ele); + } + asr_t* deserialize_ListClear() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_a; + m_a = ASR::down_cast(self().deserialize_expr()); + return ASR::make_ListClear_t(al, loc, m_a); + } + asr_t* deserialize_DictInsert() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_a; + m_a = ASR::down_cast(self().deserialize_expr()); + ASR::expr_t *m_key; + m_key = ASR::down_cast(self().deserialize_expr()); + ASR::expr_t *m_value; + m_value = ASR::down_cast(self().deserialize_expr()); + return ASR::make_DictInsert_t(al, loc, m_a, m_key, m_value); + } + asr_t* deserialize_DictClear() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_a; + m_a = ASR::down_cast(self().deserialize_expr()); + return ASR::make_DictClear_t(al, loc, m_a); + } + asr_t* deserialize_SetClear() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_a; + m_a = ASR::down_cast(self().deserialize_expr()); + return ASR::make_SetClear_t(al, loc, m_a); + } + asr_t* deserialize_Expr() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_expression; + m_expression = ASR::down_cast(self().deserialize_expr()); + return ASR::make_Expr_t(al, loc, m_expression); + } + asr_t* deserialize_stmt() { + uint8_t t = self().read_int8(); + ASR::stmtType ty = static_cast(t); + switch (ty) { + case (ASR::stmtType::Allocate) : return self().deserialize_Allocate(); + case (ASR::stmtType::ReAlloc) : return self().deserialize_ReAlloc(); + case (ASR::stmtType::Assign) : return self().deserialize_Assign(); + case (ASR::stmtType::Assignment) : return self().deserialize_Assignment(); + case (ASR::stmtType::Associate) : return self().deserialize_Associate(); + case (ASR::stmtType::Cycle) : return self().deserialize_Cycle(); + case (ASR::stmtType::ExplicitDeallocate) : return self().deserialize_ExplicitDeallocate(); + case (ASR::stmtType::ImplicitDeallocate) : return self().deserialize_ImplicitDeallocate(); + case (ASR::stmtType::DoConcurrentLoop) : return self().deserialize_DoConcurrentLoop(); + case (ASR::stmtType::DoLoop) : return self().deserialize_DoLoop(); + case (ASR::stmtType::ErrorStop) : return self().deserialize_ErrorStop(); + case (ASR::stmtType::Exit) : return self().deserialize_Exit(); + case (ASR::stmtType::ForAllSingle) : return self().deserialize_ForAllSingle(); + case (ASR::stmtType::ForEach) : return self().deserialize_ForEach(); + case (ASR::stmtType::GoTo) : return self().deserialize_GoTo(); + case (ASR::stmtType::GoToTarget) : return self().deserialize_GoToTarget(); + case (ASR::stmtType::If) : return self().deserialize_If(); + case (ASR::stmtType::IfArithmetic) : return self().deserialize_IfArithmetic(); + case (ASR::stmtType::Print) : return self().deserialize_Print(); + case (ASR::stmtType::FileOpen) : return self().deserialize_FileOpen(); + case (ASR::stmtType::FileClose) : return self().deserialize_FileClose(); + case (ASR::stmtType::FileRead) : return self().deserialize_FileRead(); + case (ASR::stmtType::FileBackspace) : return self().deserialize_FileBackspace(); + case (ASR::stmtType::FileRewind) : return self().deserialize_FileRewind(); + case (ASR::stmtType::FileInquire) : return self().deserialize_FileInquire(); + case (ASR::stmtType::FileWrite) : return self().deserialize_FileWrite(); + case (ASR::stmtType::Return) : return self().deserialize_Return(); + case (ASR::stmtType::Select) : return self().deserialize_Select(); + case (ASR::stmtType::Stop) : return self().deserialize_Stop(); + case (ASR::stmtType::Assert) : return self().deserialize_Assert(); + case (ASR::stmtType::SubroutineCall) : return self().deserialize_SubroutineCall(); + case (ASR::stmtType::IntrinsicImpureSubroutine) : return self().deserialize_IntrinsicImpureSubroutine(); + case (ASR::stmtType::Where) : return self().deserialize_Where(); + case (ASR::stmtType::WhileLoop) : return self().deserialize_WhileLoop(); + case (ASR::stmtType::Nullify) : return self().deserialize_Nullify(); + case (ASR::stmtType::Flush) : return self().deserialize_Flush(); + case (ASR::stmtType::ListAppend) : return self().deserialize_ListAppend(); + case (ASR::stmtType::AssociateBlockCall) : return self().deserialize_AssociateBlockCall(); + case (ASR::stmtType::SelectType) : return self().deserialize_SelectType(); + case (ASR::stmtType::CPtrToPointer) : return self().deserialize_CPtrToPointer(); + case (ASR::stmtType::BlockCall) : return self().deserialize_BlockCall(); + case (ASR::stmtType::SetInsert) : return self().deserialize_SetInsert(); + case (ASR::stmtType::SetRemove) : return self().deserialize_SetRemove(); + case (ASR::stmtType::SetDiscard) : return self().deserialize_SetDiscard(); + case (ASR::stmtType::ListInsert) : return self().deserialize_ListInsert(); + case (ASR::stmtType::ListRemove) : return self().deserialize_ListRemove(); + case (ASR::stmtType::ListClear) : return self().deserialize_ListClear(); + case (ASR::stmtType::DictInsert) : return self().deserialize_DictInsert(); + case (ASR::stmtType::DictClear) : return self().deserialize_DictClear(); + case (ASR::stmtType::SetClear) : return self().deserialize_SetClear(); + case (ASR::stmtType::Expr) : return self().deserialize_Expr(); + default : throw LCompilersException("Unknown type in deserialize_stmt()"); + } + throw LCompilersException("Switch statement above was not exhaustive."); + } + asr_t* deserialize_IfExp() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_test; + m_test = ASR::down_cast(self().deserialize_expr()); + ASR::expr_t *m_body; + m_body = ASR::down_cast(self().deserialize_expr()); + ASR::expr_t *m_orelse; + m_orelse = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_IfExp_t(al, loc, m_test, m_body, m_orelse, m_type, m_value); + } + asr_t* deserialize_ComplexConstructor() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_re; + m_re = ASR::down_cast(self().deserialize_expr()); + ASR::expr_t *m_im; + m_im = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_ComplexConstructor_t(al, loc, m_re, m_im, m_type, m_value); + } + asr_t* deserialize_NamedExpr() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_target; + m_target = ASR::down_cast(self().deserialize_expr()); + ASR::expr_t *m_value; + m_value = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + return ASR::make_NamedExpr_t(al, loc, m_target, m_value, m_type); + } + asr_t* deserialize_FunctionCall() { + size_t n_args; // Sequence + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::symbol_t *m_name; + m_name = self().read_symbol(); + ASR::symbol_t *m_original_name; + if (self().read_bool()) { + m_original_name = self().read_symbol(); + } else { + m_original_name = nullptr; + } + n_args = self().read_int64(); + Vec v_args; + v_args.reserve(al, n_args); + for (size_t i=0; i(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + ASR::expr_t *m_dt; + if (self().read_bool()) { + m_dt = ASR::down_cast(self().deserialize_expr()); + } else { + m_dt = nullptr; + } + return ASR::make_FunctionCall_t(al, loc, m_name, m_original_name, v_args.p, v_args.n, m_type, m_value, m_dt); + } + asr_t* deserialize_IntrinsicElementalFunction() { + size_t n_args; // Sequence + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + int64_t m_intrinsic_id = self().read_int64(); + n_args = self().read_int64(); + Vec v_args; + v_args.reserve(al, n_args); + for (size_t i=0; i(self().deserialize_expr())); + } + int64_t m_overload_id = self().read_int64(); + ASR::ttype_t *m_type; + if (self().read_bool()) { + m_type = ASR::down_cast(self().deserialize_ttype()); + } else { + m_type = nullptr; + } + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_IntrinsicElementalFunction_t(al, loc, m_intrinsic_id, v_args.p, v_args.n, m_overload_id, m_type, m_value); + } + asr_t* deserialize_IntrinsicArrayFunction() { + size_t n_args; // Sequence + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + int64_t m_arr_intrinsic_id = self().read_int64(); + n_args = self().read_int64(); + Vec v_args; + v_args.reserve(al, n_args); + for (size_t i=0; i(self().deserialize_expr())); + } + int64_t m_overload_id = self().read_int64(); + ASR::ttype_t *m_type; + if (self().read_bool()) { + m_type = ASR::down_cast(self().deserialize_ttype()); + } else { + m_type = nullptr; + } + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_IntrinsicArrayFunction_t(al, loc, m_arr_intrinsic_id, v_args.p, v_args.n, m_overload_id, m_type, m_value); + } + asr_t* deserialize_IntrinsicImpureFunction() { + size_t n_args; // Sequence + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + int64_t m_impure_intrinsic_id = self().read_int64(); + n_args = self().read_int64(); + Vec v_args; + v_args.reserve(al, n_args); + for (size_t i=0; i(self().deserialize_expr())); + } + int64_t m_overload_id = self().read_int64(); + ASR::ttype_t *m_type; + if (self().read_bool()) { + m_type = ASR::down_cast(self().deserialize_ttype()); + } else { + m_type = nullptr; + } + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_IntrinsicImpureFunction_t(al, loc, m_impure_intrinsic_id, v_args.p, v_args.n, m_overload_id, m_type, m_value); + } + asr_t* deserialize_TypeInquiry() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + int64_t m_inquiry_id = self().read_int64(); + ASR::ttype_t *m_arg_type; + m_arg_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_arg; + if (self().read_bool()) { + m_arg = ASR::down_cast(self().deserialize_expr()); + } else { + m_arg = nullptr; + } + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + m_value = ASR::down_cast(self().deserialize_expr()); + return ASR::make_TypeInquiry_t(al, loc, m_inquiry_id, m_arg_type, m_arg, m_type, m_value); + } + asr_t* deserialize_StructConstructor() { + size_t n_args; // Sequence + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::symbol_t *m_dt_sym; + m_dt_sym = self().read_symbol(); + n_args = self().read_int64(); + Vec v_args; + v_args.reserve(al, n_args); + for (size_t i=0; i(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_StructConstructor_t(al, loc, m_dt_sym, v_args.p, v_args.n, m_type, m_value); + } + asr_t* deserialize_StructConstant() { + size_t n_args; // Sequence + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::symbol_t *m_dt_sym; + m_dt_sym = self().read_symbol(); + n_args = self().read_int64(); + Vec v_args; + v_args.reserve(al, n_args); + for (size_t i=0; i(self().deserialize_ttype()); + return ASR::make_StructConstant_t(al, loc, m_dt_sym, v_args.p, v_args.n, m_type); + } + asr_t* deserialize_EnumConstructor() { + size_t n_args; // Sequence + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::symbol_t *m_dt_sym; + m_dt_sym = self().read_symbol(); + n_args = self().read_int64(); + Vec v_args; + v_args.reserve(al, n_args); + for (size_t i=0; i(self().deserialize_expr())); + } + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_EnumConstructor_t(al, loc, m_dt_sym, v_args.p, v_args.n, m_type, m_value); + } + asr_t* deserialize_UnionConstructor() { + size_t n_args; // Sequence + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::symbol_t *m_dt_sym; + m_dt_sym = self().read_symbol(); + n_args = self().read_int64(); + Vec v_args; + v_args.reserve(al, n_args); + for (size_t i=0; i(self().deserialize_expr())); + } + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_UnionConstructor_t(al, loc, m_dt_sym, v_args.p, v_args.n, m_type, m_value); + } + asr_t* deserialize_ImpliedDoLoop() { + size_t n_values; // Sequence + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + n_values = self().read_int64(); + Vec v_values; + v_values.reserve(al, n_values); + for (size_t i=0; i(self().deserialize_expr())); + } + ASR::expr_t *m_var; + m_var = ASR::down_cast(self().deserialize_expr()); + ASR::expr_t *m_start; + m_start = ASR::down_cast(self().deserialize_expr()); + ASR::expr_t *m_end; + m_end = ASR::down_cast(self().deserialize_expr()); + ASR::expr_t *m_increment; + if (self().read_bool()) { + m_increment = ASR::down_cast(self().deserialize_expr()); + } else { + m_increment = nullptr; + } + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_ImpliedDoLoop_t(al, loc, v_values.p, v_values.n, m_var, m_start, m_end, m_increment, m_type, m_value); + } + asr_t* deserialize_IntegerConstant() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + int64_t m_n = self().read_int64(); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::integerbozType m_intboz_type = self().deserialize_integerboz(); + return ASR::make_IntegerConstant_t(al, loc, m_n, m_type, m_intboz_type); + } + asr_t* deserialize_IntegerBitNot() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_arg; + m_arg = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_IntegerBitNot_t(al, loc, m_arg, m_type, m_value); + } + asr_t* deserialize_IntegerUnaryMinus() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_arg; + m_arg = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_IntegerUnaryMinus_t(al, loc, m_arg, m_type, m_value); + } + asr_t* deserialize_IntegerCompare() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_left; + m_left = ASR::down_cast(self().deserialize_expr()); + ASR::cmpopType m_op = self().deserialize_cmpop(); + ASR::expr_t *m_right; + m_right = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_IntegerCompare_t(al, loc, m_left, m_op, m_right, m_type, m_value); + } + asr_t* deserialize_IntegerBinOp() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_left; + m_left = ASR::down_cast(self().deserialize_expr()); + ASR::binopType m_op = self().deserialize_binop(); + ASR::expr_t *m_right; + m_right = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_IntegerBinOp_t(al, loc, m_left, m_op, m_right, m_type, m_value); + } + asr_t* deserialize_UnsignedIntegerConstant() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + int64_t m_n = self().read_int64(); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + return ASR::make_UnsignedIntegerConstant_t(al, loc, m_n, m_type); + } + asr_t* deserialize_UnsignedIntegerUnaryMinus() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_arg; + m_arg = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_UnsignedIntegerUnaryMinus_t(al, loc, m_arg, m_type, m_value); + } + asr_t* deserialize_UnsignedIntegerBitNot() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_arg; + m_arg = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_UnsignedIntegerBitNot_t(al, loc, m_arg, m_type, m_value); + } + asr_t* deserialize_UnsignedIntegerCompare() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_left; + m_left = ASR::down_cast(self().deserialize_expr()); + ASR::cmpopType m_op = self().deserialize_cmpop(); + ASR::expr_t *m_right; + m_right = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_UnsignedIntegerCompare_t(al, loc, m_left, m_op, m_right, m_type, m_value); + } + asr_t* deserialize_UnsignedIntegerBinOp() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_left; + m_left = ASR::down_cast(self().deserialize_expr()); + ASR::binopType m_op = self().deserialize_binop(); + ASR::expr_t *m_right; + m_right = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_UnsignedIntegerBinOp_t(al, loc, m_left, m_op, m_right, m_type, m_value); + } + asr_t* deserialize_RealConstant() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + double m_r = self().read_float64(); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + return ASR::make_RealConstant_t(al, loc, m_r, m_type); + } + asr_t* deserialize_RealUnaryMinus() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_arg; + m_arg = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_RealUnaryMinus_t(al, loc, m_arg, m_type, m_value); + } + asr_t* deserialize_RealCompare() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_left; + m_left = ASR::down_cast(self().deserialize_expr()); + ASR::cmpopType m_op = self().deserialize_cmpop(); + ASR::expr_t *m_right; + m_right = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_RealCompare_t(al, loc, m_left, m_op, m_right, m_type, m_value); + } + asr_t* deserialize_RealBinOp() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_left; + m_left = ASR::down_cast(self().deserialize_expr()); + ASR::binopType m_op = self().deserialize_binop(); + ASR::expr_t *m_right; + m_right = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_RealBinOp_t(al, loc, m_left, m_op, m_right, m_type, m_value); + } + asr_t* deserialize_RealCopySign() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_target; + m_target = ASR::down_cast(self().deserialize_expr()); + ASR::expr_t *m_source; + m_source = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_RealCopySign_t(al, loc, m_target, m_source, m_type, m_value); + } + asr_t* deserialize_ComplexConstant() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + double m_re = self().read_float64(); + double m_im = self().read_float64(); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + return ASR::make_ComplexConstant_t(al, loc, m_re, m_im, m_type); + } + asr_t* deserialize_ComplexUnaryMinus() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_arg; + m_arg = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_ComplexUnaryMinus_t(al, loc, m_arg, m_type, m_value); + } + asr_t* deserialize_ComplexCompare() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_left; + m_left = ASR::down_cast(self().deserialize_expr()); + ASR::cmpopType m_op = self().deserialize_cmpop(); + ASR::expr_t *m_right; + m_right = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_ComplexCompare_t(al, loc, m_left, m_op, m_right, m_type, m_value); + } + asr_t* deserialize_ComplexBinOp() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_left; + m_left = ASR::down_cast(self().deserialize_expr()); + ASR::binopType m_op = self().deserialize_binop(); + ASR::expr_t *m_right; + m_right = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_ComplexBinOp_t(al, loc, m_left, m_op, m_right, m_type, m_value); + } + asr_t* deserialize_LogicalConstant() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + bool m_value = self().read_bool(); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + return ASR::make_LogicalConstant_t(al, loc, m_value, m_type); + } + asr_t* deserialize_LogicalNot() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_arg; + m_arg = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_LogicalNot_t(al, loc, m_arg, m_type, m_value); + } + asr_t* deserialize_LogicalCompare() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_left; + m_left = ASR::down_cast(self().deserialize_expr()); + ASR::cmpopType m_op = self().deserialize_cmpop(); + ASR::expr_t *m_right; + m_right = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_LogicalCompare_t(al, loc, m_left, m_op, m_right, m_type, m_value); + } + asr_t* deserialize_LogicalBinOp() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_left; + m_left = ASR::down_cast(self().deserialize_expr()); + ASR::logicalbinopType m_op = self().deserialize_logicalbinop(); + ASR::expr_t *m_right; + m_right = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_LogicalBinOp_t(al, loc, m_left, m_op, m_right, m_type, m_value); + } + asr_t* deserialize_ListConstant() { + size_t n_args; // Sequence + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + n_args = self().read_int64(); + Vec v_args; + v_args.reserve(al, n_args); + for (size_t i=0; i(self().deserialize_expr())); + } + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + return ASR::make_ListConstant_t(al, loc, v_args.p, v_args.n, m_type); + } + asr_t* deserialize_ListLen() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_arg; + m_arg = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_ListLen_t(al, loc, m_arg, m_type, m_value); + } + asr_t* deserialize_ListConcat() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_left; + m_left = ASR::down_cast(self().deserialize_expr()); + ASR::expr_t *m_right; + m_right = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_ListConcat_t(al, loc, m_left, m_right, m_type, m_value); + } + asr_t* deserialize_ListCompare() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_left; + m_left = ASR::down_cast(self().deserialize_expr()); + ASR::cmpopType m_op = self().deserialize_cmpop(); + ASR::expr_t *m_right; + m_right = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_ListCompare_t(al, loc, m_left, m_op, m_right, m_type, m_value); + } + asr_t* deserialize_ListCount() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_arg; + m_arg = ASR::down_cast(self().deserialize_expr()); + ASR::expr_t *m_ele; + m_ele = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_ListCount_t(al, loc, m_arg, m_ele, m_type, m_value); + } + asr_t* deserialize_ListContains() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_left; + m_left = ASR::down_cast(self().deserialize_expr()); + ASR::expr_t *m_right; + m_right = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_ListContains_t(al, loc, m_left, m_right, m_type, m_value); + } + asr_t* deserialize_SetConstant() { + size_t n_elements; // Sequence + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + n_elements = self().read_int64(); + Vec v_elements; + v_elements.reserve(al, n_elements); + for (size_t i=0; i(self().deserialize_expr())); + } + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + return ASR::make_SetConstant_t(al, loc, v_elements.p, v_elements.n, m_type); + } + asr_t* deserialize_SetLen() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_arg; + m_arg = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_SetLen_t(al, loc, m_arg, m_type, m_value); + } + asr_t* deserialize_TupleConstant() { + size_t n_elements; // Sequence + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + n_elements = self().read_int64(); + Vec v_elements; + v_elements.reserve(al, n_elements); + for (size_t i=0; i(self().deserialize_expr())); + } + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + return ASR::make_TupleConstant_t(al, loc, v_elements.p, v_elements.n, m_type); + } + asr_t* deserialize_TupleLen() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_arg; + m_arg = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + m_value = ASR::down_cast(self().deserialize_expr()); + return ASR::make_TupleLen_t(al, loc, m_arg, m_type, m_value); + } + asr_t* deserialize_TupleCompare() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_left; + m_left = ASR::down_cast(self().deserialize_expr()); + ASR::cmpopType m_op = self().deserialize_cmpop(); + ASR::expr_t *m_right; + m_right = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_TupleCompare_t(al, loc, m_left, m_op, m_right, m_type, m_value); + } + asr_t* deserialize_TupleConcat() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_left; + m_left = ASR::down_cast(self().deserialize_expr()); + ASR::expr_t *m_right; + m_right = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_TupleConcat_t(al, loc, m_left, m_right, m_type, m_value); + } + asr_t* deserialize_TupleContains() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_left; + m_left = ASR::down_cast(self().deserialize_expr()); + ASR::expr_t *m_right; + m_right = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_TupleContains_t(al, loc, m_left, m_right, m_type, m_value); + } + asr_t* deserialize_StringConstant() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + char *m_s; + m_s = self().read_cstring(); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + return ASR::make_StringConstant_t(al, loc, m_s, m_type); + } + asr_t* deserialize_StringConcat() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_left; + m_left = ASR::down_cast(self().deserialize_expr()); + ASR::expr_t *m_right; + m_right = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_StringConcat_t(al, loc, m_left, m_right, m_type, m_value); + } + asr_t* deserialize_StringRepeat() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_left; + m_left = ASR::down_cast(self().deserialize_expr()); + ASR::expr_t *m_right; + m_right = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_StringRepeat_t(al, loc, m_left, m_right, m_type, m_value); + } + asr_t* deserialize_StringLen() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_arg; + m_arg = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_StringLen_t(al, loc, m_arg, m_type, m_value); + } + asr_t* deserialize_StringItem() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_arg; + m_arg = ASR::down_cast(self().deserialize_expr()); + ASR::expr_t *m_idx; + m_idx = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_StringItem_t(al, loc, m_arg, m_idx, m_type, m_value); + } + asr_t* deserialize_StringSection() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_arg; + m_arg = ASR::down_cast(self().deserialize_expr()); + ASR::expr_t *m_start; + if (self().read_bool()) { + m_start = ASR::down_cast(self().deserialize_expr()); + } else { + m_start = nullptr; + } + ASR::expr_t *m_end; + if (self().read_bool()) { + m_end = ASR::down_cast(self().deserialize_expr()); + } else { + m_end = nullptr; + } + ASR::expr_t *m_step; + if (self().read_bool()) { + m_step = ASR::down_cast(self().deserialize_expr()); + } else { + m_step = nullptr; + } + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_StringSection_t(al, loc, m_arg, m_start, m_end, m_step, m_type, m_value); + } + asr_t* deserialize_StringCompare() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_left; + m_left = ASR::down_cast(self().deserialize_expr()); + ASR::cmpopType m_op = self().deserialize_cmpop(); + ASR::expr_t *m_right; + m_right = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_StringCompare_t(al, loc, m_left, m_op, m_right, m_type, m_value); + } + asr_t* deserialize_StringContains() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_substr; + m_substr = ASR::down_cast(self().deserialize_expr()); + ASR::expr_t *m_str; + m_str = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_StringContains_t(al, loc, m_substr, m_str, m_type, m_value); + } + asr_t* deserialize_StringOrd() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_arg; + m_arg = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_StringOrd_t(al, loc, m_arg, m_type, m_value); + } + asr_t* deserialize_StringChr() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_arg; + m_arg = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_StringChr_t(al, loc, m_arg, m_type, m_value); + } + asr_t* deserialize_StringFormat() { + size_t n_args; // Sequence + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_fmt; + if (self().read_bool()) { + m_fmt = ASR::down_cast(self().deserialize_expr()); + } else { + m_fmt = nullptr; + } + n_args = self().read_int64(); + Vec v_args; + v_args.reserve(al, n_args); + for (size_t i=0; i(self().deserialize_expr())); + } + ASR::string_format_kindType m_kind = self().deserialize_string_format_kind(); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_StringFormat_t(al, loc, m_fmt, v_args.p, v_args.n, m_kind, m_type, m_value); + } + asr_t* deserialize_StringPhysicalCast() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_arg; + m_arg = ASR::down_cast(self().deserialize_expr()); + ASR::string_physical_typeType m_old = self().deserialize_string_physical_type(); + ASR::string_physical_typeType m_new = self().deserialize_string_physical_type(); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_StringPhysicalCast_t(al, loc, m_arg, m_old, m_new, m_type, m_value); + } + asr_t* deserialize_CPtrCompare() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_left; + m_left = ASR::down_cast(self().deserialize_expr()); + ASR::cmpopType m_op = self().deserialize_cmpop(); + ASR::expr_t *m_right; + m_right = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_CPtrCompare_t(al, loc, m_left, m_op, m_right, m_type, m_value); + } + asr_t* deserialize_SymbolicCompare() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_left; + m_left = ASR::down_cast(self().deserialize_expr()); + ASR::cmpopType m_op = self().deserialize_cmpop(); + ASR::expr_t *m_right; + m_right = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_SymbolicCompare_t(al, loc, m_left, m_op, m_right, m_type, m_value); + } + asr_t* deserialize_DictConstant() { + size_t n_keys; // Sequence + size_t n_values; // Sequence + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + n_keys = self().read_int64(); + Vec v_keys; + v_keys.reserve(al, n_keys); + for (size_t i=0; i(self().deserialize_expr())); + } + n_values = self().read_int64(); + Vec v_values; + v_values.reserve(al, n_values); + for (size_t i=0; i(self().deserialize_expr())); + } + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + return ASR::make_DictConstant_t(al, loc, v_keys.p, v_keys.n, v_values.p, v_values.n, m_type); + } + asr_t* deserialize_DictLen() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_arg; + m_arg = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_DictLen_t(al, loc, m_arg, m_type, m_value); + } + asr_t* deserialize_Var() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::symbol_t *m_v; + m_v = self().read_symbol(); + return ASR::make_Var_t(al, loc, m_v); + } + asr_t* deserialize_FunctionParam() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + int64_t m_param_number = self().read_int64(); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_FunctionParam_t(al, loc, m_param_number, m_type, m_value); + } + asr_t* deserialize_ArrayConstructor() { + size_t n_args; // Sequence + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + n_args = self().read_int64(); + Vec v_args; + v_args.reserve(al, n_args); + for (size_t i=0; i(self().deserialize_expr())); + } + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + ASR::arraystorageType m_storage_format = self().deserialize_arraystorage(); + return ASR::make_ArrayConstructor_t(al, loc, v_args.p, v_args.n, m_type, m_value, m_storage_format); + } + asr_t* deserialize_ArrayConstant() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + int64_t m_n_data = self().read_int64(); + void *m_data = self().read_void(m_n_data); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::arraystorageType m_storage_format = self().deserialize_arraystorage(); + return ASR::make_ArrayConstant_t(al, loc, m_n_data, m_data, m_type, m_storage_format); + } + asr_t* deserialize_ArrayItem() { + size_t n_args; // Sequence + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_v; + m_v = ASR::down_cast(self().deserialize_expr()); + n_args = self().read_int64(); + Vec v_args; + v_args.reserve(al, n_args); + for (size_t i=0; i(self().deserialize_ttype()); + ASR::arraystorageType m_storage_format = self().deserialize_arraystorage(); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_ArrayItem_t(al, loc, m_v, v_args.p, v_args.n, m_type, m_storage_format, m_value); + } + asr_t* deserialize_ArraySection() { + size_t n_args; // Sequence + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_v; + m_v = ASR::down_cast(self().deserialize_expr()); + n_args = self().read_int64(); + Vec v_args; + v_args.reserve(al, n_args); + for (size_t i=0; i(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_ArraySection_t(al, loc, m_v, v_args.p, v_args.n, m_type, m_value); + } + asr_t* deserialize_ArraySize() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_v; + m_v = ASR::down_cast(self().deserialize_expr()); + ASR::expr_t *m_dim; + if (self().read_bool()) { + m_dim = ASR::down_cast(self().deserialize_expr()); + } else { + m_dim = nullptr; + } + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_ArraySize_t(al, loc, m_v, m_dim, m_type, m_value); + } + asr_t* deserialize_ArrayBound() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_v; + m_v = ASR::down_cast(self().deserialize_expr()); + ASR::expr_t *m_dim; + if (self().read_bool()) { + m_dim = ASR::down_cast(self().deserialize_expr()); + } else { + m_dim = nullptr; + } + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::arrayboundType m_bound = self().deserialize_arraybound(); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_ArrayBound_t(al, loc, m_v, m_dim, m_type, m_bound, m_value); + } + asr_t* deserialize_ArrayTranspose() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_matrix; + m_matrix = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_ArrayTranspose_t(al, loc, m_matrix, m_type, m_value); + } + asr_t* deserialize_ArrayPack() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_array; + m_array = ASR::down_cast(self().deserialize_expr()); + ASR::expr_t *m_mask; + m_mask = ASR::down_cast(self().deserialize_expr()); + ASR::expr_t *m_vector; + if (self().read_bool()) { + m_vector = ASR::down_cast(self().deserialize_expr()); + } else { + m_vector = nullptr; + } + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_ArrayPack_t(al, loc, m_array, m_mask, m_vector, m_type, m_value); + } + asr_t* deserialize_ArrayReshape() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_array; + m_array = ASR::down_cast(self().deserialize_expr()); + ASR::expr_t *m_shape; + m_shape = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_ArrayReshape_t(al, loc, m_array, m_shape, m_type, m_value); + } + asr_t* deserialize_ArrayAll() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_mask; + m_mask = ASR::down_cast(self().deserialize_expr()); + ASR::expr_t *m_dim; + if (self().read_bool()) { + m_dim = ASR::down_cast(self().deserialize_expr()); + } else { + m_dim = nullptr; + } + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_ArrayAll_t(al, loc, m_mask, m_dim, m_type, m_value); + } + asr_t* deserialize_ArrayBroadcast() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_array; + m_array = ASR::down_cast(self().deserialize_expr()); + ASR::expr_t *m_shape; + m_shape = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_ArrayBroadcast_t(al, loc, m_array, m_shape, m_type, m_value); + } + asr_t* deserialize_BitCast() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_source; + m_source = ASR::down_cast(self().deserialize_expr()); + ASR::expr_t *m_mold; + m_mold = ASR::down_cast(self().deserialize_expr()); + ASR::expr_t *m_size; + if (self().read_bool()) { + m_size = ASR::down_cast(self().deserialize_expr()); + } else { + m_size = nullptr; + } + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_BitCast_t(al, loc, m_source, m_mold, m_size, m_type, m_value); + } + asr_t* deserialize_StructInstanceMember() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_v; + m_v = ASR::down_cast(self().deserialize_expr()); + ASR::symbol_t *m_m; + m_m = self().read_symbol(); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_StructInstanceMember_t(al, loc, m_v, m_m, m_type, m_value); + } + asr_t* deserialize_StructStaticMember() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_v; + m_v = ASR::down_cast(self().deserialize_expr()); + ASR::symbol_t *m_m; + m_m = self().read_symbol(); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_StructStaticMember_t(al, loc, m_v, m_m, m_type, m_value); + } + asr_t* deserialize_EnumStaticMember() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_v; + m_v = ASR::down_cast(self().deserialize_expr()); + ASR::symbol_t *m_m; + m_m = self().read_symbol(); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_EnumStaticMember_t(al, loc, m_v, m_m, m_type, m_value); + } + asr_t* deserialize_UnionInstanceMember() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_v; + m_v = ASR::down_cast(self().deserialize_expr()); + ASR::symbol_t *m_m; + m_m = self().read_symbol(); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_UnionInstanceMember_t(al, loc, m_v, m_m, m_type, m_value); + } + asr_t* deserialize_EnumName() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_v; + m_v = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_enum_type; + m_enum_type = ASR::down_cast(self().deserialize_ttype()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_EnumName_t(al, loc, m_v, m_enum_type, m_type, m_value); + } + asr_t* deserialize_EnumValue() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_v; + m_v = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_enum_type; + m_enum_type = ASR::down_cast(self().deserialize_ttype()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_EnumValue_t(al, loc, m_v, m_enum_type, m_type, m_value); + } + asr_t* deserialize_OverloadedCompare() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_left; + m_left = ASR::down_cast(self().deserialize_expr()); + ASR::cmpopType m_op = self().deserialize_cmpop(); + ASR::expr_t *m_right; + m_right = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + ASR::expr_t *m_overloaded; + m_overloaded = ASR::down_cast(self().deserialize_expr()); + return ASR::make_OverloadedCompare_t(al, loc, m_left, m_op, m_right, m_type, m_value, m_overloaded); + } + asr_t* deserialize_OverloadedBinOp() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_left; + m_left = ASR::down_cast(self().deserialize_expr()); + ASR::binopType m_op = self().deserialize_binop(); + ASR::expr_t *m_right; + m_right = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + ASR::expr_t *m_overloaded; + m_overloaded = ASR::down_cast(self().deserialize_expr()); + return ASR::make_OverloadedBinOp_t(al, loc, m_left, m_op, m_right, m_type, m_value, m_overloaded); + } + asr_t* deserialize_OverloadedUnaryMinus() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_arg; + m_arg = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + ASR::expr_t *m_overloaded; + m_overloaded = ASR::down_cast(self().deserialize_expr()); + return ASR::make_OverloadedUnaryMinus_t(al, loc, m_arg, m_type, m_value, m_overloaded); + } + asr_t* deserialize_OverloadedStringConcat() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_left; + m_left = ASR::down_cast(self().deserialize_expr()); + ASR::expr_t *m_right; + m_right = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + ASR::expr_t *m_overloaded; + m_overloaded = ASR::down_cast(self().deserialize_expr()); + return ASR::make_OverloadedStringConcat_t(al, loc, m_left, m_right, m_type, m_value, m_overloaded); + } + asr_t* deserialize_Cast() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_arg; + m_arg = ASR::down_cast(self().deserialize_expr()); + ASR::cast_kindType m_kind = self().deserialize_cast_kind(); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_Cast_t(al, loc, m_arg, m_kind, m_type, m_value); + } + asr_t* deserialize_ArrayPhysicalCast() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_arg; + m_arg = ASR::down_cast(self().deserialize_expr()); + ASR::array_physical_typeType m_old = self().deserialize_array_physical_type(); + ASR::array_physical_typeType m_new = self().deserialize_array_physical_type(); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_ArrayPhysicalCast_t(al, loc, m_arg, m_old, m_new, m_type, m_value); + } + asr_t* deserialize_ComplexRe() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_arg; + m_arg = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_ComplexRe_t(al, loc, m_arg, m_type, m_value); + } + asr_t* deserialize_ComplexIm() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_arg; + m_arg = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_ComplexIm_t(al, loc, m_arg, m_type, m_value); + } + asr_t* deserialize_DictItem() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_a; + m_a = ASR::down_cast(self().deserialize_expr()); + ASR::expr_t *m_key; + m_key = ASR::down_cast(self().deserialize_expr()); + ASR::expr_t *m_default; + if (self().read_bool()) { + m_default = ASR::down_cast(self().deserialize_expr()); + } else { + m_default = nullptr; + } + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_DictItem_t(al, loc, m_a, m_key, m_default, m_type, m_value); + } + asr_t* deserialize_CLoc() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_arg; + m_arg = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_CLoc_t(al, loc, m_arg, m_type, m_value); + } + asr_t* deserialize_PointerToCPtr() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_arg; + m_arg = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_PointerToCPtr_t(al, loc, m_arg, m_type, m_value); + } + asr_t* deserialize_GetPointer() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_arg; + m_arg = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_GetPointer_t(al, loc, m_arg, m_type, m_value); + } + asr_t* deserialize_ListItem() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_a; + m_a = ASR::down_cast(self().deserialize_expr()); + ASR::expr_t *m_pos; + m_pos = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_ListItem_t(al, loc, m_a, m_pos, m_type, m_value); + } + asr_t* deserialize_TupleItem() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_a; + m_a = ASR::down_cast(self().deserialize_expr()); + ASR::expr_t *m_pos; + m_pos = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_TupleItem_t(al, loc, m_a, m_pos, m_type, m_value); + } + asr_t* deserialize_ListSection() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_a; + m_a = ASR::down_cast(self().deserialize_expr()); + ASR::array_index_t m_section = self().deserialize_array_index(); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_ListSection_t(al, loc, m_a, m_section, m_type, m_value); + } + asr_t* deserialize_ListRepeat() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_left; + m_left = ASR::down_cast(self().deserialize_expr()); + ASR::expr_t *m_right; + m_right = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_ListRepeat_t(al, loc, m_left, m_right, m_type, m_value); + } + asr_t* deserialize_DictPop() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_a; + m_a = ASR::down_cast(self().deserialize_expr()); + ASR::expr_t *m_key; + m_key = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_DictPop_t(al, loc, m_a, m_key, m_type, m_value); + } + asr_t* deserialize_SetPop() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_a; + m_a = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_SetPop_t(al, loc, m_a, m_type, m_value); + } + asr_t* deserialize_SetContains() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_left; + m_left = ASR::down_cast(self().deserialize_expr()); + ASR::expr_t *m_right; + m_right = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_SetContains_t(al, loc, m_left, m_right, m_type, m_value); + } + asr_t* deserialize_DictContains() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_left; + m_left = ASR::down_cast(self().deserialize_expr()); + ASR::expr_t *m_right; + m_right = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_DictContains_t(al, loc, m_left, m_right, m_type, m_value); + } + asr_t* deserialize_IntegerBitLen() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_a; + m_a = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_IntegerBitLen_t(al, loc, m_a, m_type, m_value); + } + asr_t* deserialize_Ichar() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_arg; + m_arg = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_Ichar_t(al, loc, m_arg, m_type, m_value); + } + asr_t* deserialize_Iachar() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_arg; + m_arg = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_Iachar_t(al, loc, m_arg, m_type, m_value); + } + asr_t* deserialize_SizeOfType() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::ttype_t *m_arg; + m_arg = ASR::down_cast(self().deserialize_ttype()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_SizeOfType_t(al, loc, m_arg, m_type, m_value); + } + asr_t* deserialize_PointerNullConstant() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + return ASR::make_PointerNullConstant_t(al, loc, m_type); + } + asr_t* deserialize_PointerAssociated() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_ptr; + m_ptr = ASR::down_cast(self().deserialize_expr()); + ASR::expr_t *m_tgt; + if (self().read_bool()) { + m_tgt = ASR::down_cast(self().deserialize_expr()); + } else { + m_tgt = nullptr; + } + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_PointerAssociated_t(al, loc, m_ptr, m_tgt, m_type, m_value); + } + asr_t* deserialize_RealSqrt() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_arg; + m_arg = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_RealSqrt_t(al, loc, m_arg, m_type, m_value); + } + asr_t* deserialize_ArrayIsContiguous() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_array; + m_array = ASR::down_cast(self().deserialize_expr()); + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + ASR::expr_t *m_value; + if (self().read_bool()) { + m_value = ASR::down_cast(self().deserialize_expr()); + } else { + m_value = nullptr; + } + return ASR::make_ArrayIsContiguous_t(al, loc, m_array, m_type, m_value); + } + asr_t* deserialize_expr() { + uint8_t t = self().read_int8(); + ASR::exprType ty = static_cast(t); + switch (ty) { + case (ASR::exprType::IfExp) : return self().deserialize_IfExp(); + case (ASR::exprType::ComplexConstructor) : return self().deserialize_ComplexConstructor(); + case (ASR::exprType::NamedExpr) : return self().deserialize_NamedExpr(); + case (ASR::exprType::FunctionCall) : return self().deserialize_FunctionCall(); + case (ASR::exprType::IntrinsicElementalFunction) : return self().deserialize_IntrinsicElementalFunction(); + case (ASR::exprType::IntrinsicArrayFunction) : return self().deserialize_IntrinsicArrayFunction(); + case (ASR::exprType::IntrinsicImpureFunction) : return self().deserialize_IntrinsicImpureFunction(); + case (ASR::exprType::TypeInquiry) : return self().deserialize_TypeInquiry(); + case (ASR::exprType::StructConstructor) : return self().deserialize_StructConstructor(); + case (ASR::exprType::StructConstant) : return self().deserialize_StructConstant(); + case (ASR::exprType::EnumConstructor) : return self().deserialize_EnumConstructor(); + case (ASR::exprType::UnionConstructor) : return self().deserialize_UnionConstructor(); + case (ASR::exprType::ImpliedDoLoop) : return self().deserialize_ImpliedDoLoop(); + case (ASR::exprType::IntegerConstant) : return self().deserialize_IntegerConstant(); + case (ASR::exprType::IntegerBitNot) : return self().deserialize_IntegerBitNot(); + case (ASR::exprType::IntegerUnaryMinus) : return self().deserialize_IntegerUnaryMinus(); + case (ASR::exprType::IntegerCompare) : return self().deserialize_IntegerCompare(); + case (ASR::exprType::IntegerBinOp) : return self().deserialize_IntegerBinOp(); + case (ASR::exprType::UnsignedIntegerConstant) : return self().deserialize_UnsignedIntegerConstant(); + case (ASR::exprType::UnsignedIntegerUnaryMinus) : return self().deserialize_UnsignedIntegerUnaryMinus(); + case (ASR::exprType::UnsignedIntegerBitNot) : return self().deserialize_UnsignedIntegerBitNot(); + case (ASR::exprType::UnsignedIntegerCompare) : return self().deserialize_UnsignedIntegerCompare(); + case (ASR::exprType::UnsignedIntegerBinOp) : return self().deserialize_UnsignedIntegerBinOp(); + case (ASR::exprType::RealConstant) : return self().deserialize_RealConstant(); + case (ASR::exprType::RealUnaryMinus) : return self().deserialize_RealUnaryMinus(); + case (ASR::exprType::RealCompare) : return self().deserialize_RealCompare(); + case (ASR::exprType::RealBinOp) : return self().deserialize_RealBinOp(); + case (ASR::exprType::RealCopySign) : return self().deserialize_RealCopySign(); + case (ASR::exprType::ComplexConstant) : return self().deserialize_ComplexConstant(); + case (ASR::exprType::ComplexUnaryMinus) : return self().deserialize_ComplexUnaryMinus(); + case (ASR::exprType::ComplexCompare) : return self().deserialize_ComplexCompare(); + case (ASR::exprType::ComplexBinOp) : return self().deserialize_ComplexBinOp(); + case (ASR::exprType::LogicalConstant) : return self().deserialize_LogicalConstant(); + case (ASR::exprType::LogicalNot) : return self().deserialize_LogicalNot(); + case (ASR::exprType::LogicalCompare) : return self().deserialize_LogicalCompare(); + case (ASR::exprType::LogicalBinOp) : return self().deserialize_LogicalBinOp(); + case (ASR::exprType::ListConstant) : return self().deserialize_ListConstant(); + case (ASR::exprType::ListLen) : return self().deserialize_ListLen(); + case (ASR::exprType::ListConcat) : return self().deserialize_ListConcat(); + case (ASR::exprType::ListCompare) : return self().deserialize_ListCompare(); + case (ASR::exprType::ListCount) : return self().deserialize_ListCount(); + case (ASR::exprType::ListContains) : return self().deserialize_ListContains(); + case (ASR::exprType::SetConstant) : return self().deserialize_SetConstant(); + case (ASR::exprType::SetLen) : return self().deserialize_SetLen(); + case (ASR::exprType::TupleConstant) : return self().deserialize_TupleConstant(); + case (ASR::exprType::TupleLen) : return self().deserialize_TupleLen(); + case (ASR::exprType::TupleCompare) : return self().deserialize_TupleCompare(); + case (ASR::exprType::TupleConcat) : return self().deserialize_TupleConcat(); + case (ASR::exprType::TupleContains) : return self().deserialize_TupleContains(); + case (ASR::exprType::StringConstant) : return self().deserialize_StringConstant(); + case (ASR::exprType::StringConcat) : return self().deserialize_StringConcat(); + case (ASR::exprType::StringRepeat) : return self().deserialize_StringRepeat(); + case (ASR::exprType::StringLen) : return self().deserialize_StringLen(); + case (ASR::exprType::StringItem) : return self().deserialize_StringItem(); + case (ASR::exprType::StringSection) : return self().deserialize_StringSection(); + case (ASR::exprType::StringCompare) : return self().deserialize_StringCompare(); + case (ASR::exprType::StringContains) : return self().deserialize_StringContains(); + case (ASR::exprType::StringOrd) : return self().deserialize_StringOrd(); + case (ASR::exprType::StringChr) : return self().deserialize_StringChr(); + case (ASR::exprType::StringFormat) : return self().deserialize_StringFormat(); + case (ASR::exprType::StringPhysicalCast) : return self().deserialize_StringPhysicalCast(); + case (ASR::exprType::CPtrCompare) : return self().deserialize_CPtrCompare(); + case (ASR::exprType::SymbolicCompare) : return self().deserialize_SymbolicCompare(); + case (ASR::exprType::DictConstant) : return self().deserialize_DictConstant(); + case (ASR::exprType::DictLen) : return self().deserialize_DictLen(); + case (ASR::exprType::Var) : return self().deserialize_Var(); + case (ASR::exprType::FunctionParam) : return self().deserialize_FunctionParam(); + case (ASR::exprType::ArrayConstructor) : return self().deserialize_ArrayConstructor(); + case (ASR::exprType::ArrayConstant) : return self().deserialize_ArrayConstant(); + case (ASR::exprType::ArrayItem) : return self().deserialize_ArrayItem(); + case (ASR::exprType::ArraySection) : return self().deserialize_ArraySection(); + case (ASR::exprType::ArraySize) : return self().deserialize_ArraySize(); + case (ASR::exprType::ArrayBound) : return self().deserialize_ArrayBound(); + case (ASR::exprType::ArrayTranspose) : return self().deserialize_ArrayTranspose(); + case (ASR::exprType::ArrayPack) : return self().deserialize_ArrayPack(); + case (ASR::exprType::ArrayReshape) : return self().deserialize_ArrayReshape(); + case (ASR::exprType::ArrayAll) : return self().deserialize_ArrayAll(); + case (ASR::exprType::ArrayBroadcast) : return self().deserialize_ArrayBroadcast(); + case (ASR::exprType::BitCast) : return self().deserialize_BitCast(); + case (ASR::exprType::StructInstanceMember) : return self().deserialize_StructInstanceMember(); + case (ASR::exprType::StructStaticMember) : return self().deserialize_StructStaticMember(); + case (ASR::exprType::EnumStaticMember) : return self().deserialize_EnumStaticMember(); + case (ASR::exprType::UnionInstanceMember) : return self().deserialize_UnionInstanceMember(); + case (ASR::exprType::EnumName) : return self().deserialize_EnumName(); + case (ASR::exprType::EnumValue) : return self().deserialize_EnumValue(); + case (ASR::exprType::OverloadedCompare) : return self().deserialize_OverloadedCompare(); + case (ASR::exprType::OverloadedBinOp) : return self().deserialize_OverloadedBinOp(); + case (ASR::exprType::OverloadedUnaryMinus) : return self().deserialize_OverloadedUnaryMinus(); + case (ASR::exprType::OverloadedStringConcat) : return self().deserialize_OverloadedStringConcat(); + case (ASR::exprType::Cast) : return self().deserialize_Cast(); + case (ASR::exprType::ArrayPhysicalCast) : return self().deserialize_ArrayPhysicalCast(); + case (ASR::exprType::ComplexRe) : return self().deserialize_ComplexRe(); + case (ASR::exprType::ComplexIm) : return self().deserialize_ComplexIm(); + case (ASR::exprType::DictItem) : return self().deserialize_DictItem(); + case (ASR::exprType::CLoc) : return self().deserialize_CLoc(); + case (ASR::exprType::PointerToCPtr) : return self().deserialize_PointerToCPtr(); + case (ASR::exprType::GetPointer) : return self().deserialize_GetPointer(); + case (ASR::exprType::ListItem) : return self().deserialize_ListItem(); + case (ASR::exprType::TupleItem) : return self().deserialize_TupleItem(); + case (ASR::exprType::ListSection) : return self().deserialize_ListSection(); + case (ASR::exprType::ListRepeat) : return self().deserialize_ListRepeat(); + case (ASR::exprType::DictPop) : return self().deserialize_DictPop(); + case (ASR::exprType::SetPop) : return self().deserialize_SetPop(); + case (ASR::exprType::SetContains) : return self().deserialize_SetContains(); + case (ASR::exprType::DictContains) : return self().deserialize_DictContains(); + case (ASR::exprType::IntegerBitLen) : return self().deserialize_IntegerBitLen(); + case (ASR::exprType::Ichar) : return self().deserialize_Ichar(); + case (ASR::exprType::Iachar) : return self().deserialize_Iachar(); + case (ASR::exprType::SizeOfType) : return self().deserialize_SizeOfType(); + case (ASR::exprType::PointerNullConstant) : return self().deserialize_PointerNullConstant(); + case (ASR::exprType::PointerAssociated) : return self().deserialize_PointerAssociated(); + case (ASR::exprType::RealSqrt) : return self().deserialize_RealSqrt(); + case (ASR::exprType::ArrayIsContiguous) : return self().deserialize_ArrayIsContiguous(); + default : throw LCompilersException("Unknown type in deserialize_expr()"); + } + throw LCompilersException("Switch statement above was not exhaustive."); + } + asr_t* deserialize_Integer() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + int64_t m_kind = self().read_int64(); + return ASR::make_Integer_t(al, loc, m_kind); + } + asr_t* deserialize_UnsignedInteger() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + int64_t m_kind = self().read_int64(); + return ASR::make_UnsignedInteger_t(al, loc, m_kind); + } + asr_t* deserialize_Real() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + int64_t m_kind = self().read_int64(); + return ASR::make_Real_t(al, loc, m_kind); + } + asr_t* deserialize_Complex() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + int64_t m_kind = self().read_int64(); + return ASR::make_Complex_t(al, loc, m_kind); + } + asr_t* deserialize_String() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + int64_t m_kind = self().read_int64(); + int64_t m_len = self().read_int64(); + ASR::expr_t *m_len_expr; + if (self().read_bool()) { + m_len_expr = ASR::down_cast(self().deserialize_expr()); + } else { + m_len_expr = nullptr; + } + ASR::string_physical_typeType m_physical_type = self().deserialize_string_physical_type(); + return ASR::make_String_t(al, loc, m_kind, m_len, m_len_expr, m_physical_type); + } + asr_t* deserialize_Logical() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + int64_t m_kind = self().read_int64(); + return ASR::make_Logical_t(al, loc, m_kind); + } + asr_t* deserialize_Set() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + return ASR::make_Set_t(al, loc, m_type); + } + asr_t* deserialize_List() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + return ASR::make_List_t(al, loc, m_type); + } + asr_t* deserialize_Tuple() { + size_t n_type; // Sequence + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + n_type = self().read_int64(); + Vec v_type; + v_type.reserve(al, n_type); + for (size_t i=0; i(self().deserialize_ttype())); + } + return ASR::make_Tuple_t(al, loc, v_type.p, v_type.n); + } + asr_t* deserialize_StructType() { + size_t n_data_member_types; // Sequence + size_t n_member_function_types; // Sequence + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + n_data_member_types = self().read_int64(); + Vec v_data_member_types; + v_data_member_types.reserve(al, n_data_member_types); + for (size_t i=0; i(self().deserialize_ttype())); + } + n_member_function_types = self().read_int64(); + Vec v_member_function_types; + v_member_function_types.reserve(al, n_member_function_types); + for (size_t i=0; i(self().deserialize_ttype())); + } + bool m_is_cstruct = self().read_bool(); + ASR::symbol_t *m_derived_type; + m_derived_type = self().read_symbol(); + return ASR::make_StructType_t(al, loc, v_data_member_types.p, v_data_member_types.n, v_member_function_types.p, v_member_function_types.n, m_is_cstruct, m_derived_type); + } + asr_t* deserialize_EnumType() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::symbol_t *m_enum_type; + m_enum_type = self().read_symbol(); + return ASR::make_EnumType_t(al, loc, m_enum_type); + } + asr_t* deserialize_UnionType() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::symbol_t *m_union_type; + m_union_type = self().read_symbol(); + return ASR::make_UnionType_t(al, loc, m_union_type); + } + asr_t* deserialize_ClassType() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::symbol_t *m_class_type; + m_class_type = self().read_symbol(); + return ASR::make_ClassType_t(al, loc, m_class_type); + } + asr_t* deserialize_Dict() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::ttype_t *m_key_type; + m_key_type = ASR::down_cast(self().deserialize_ttype()); + ASR::ttype_t *m_value_type; + m_value_type = ASR::down_cast(self().deserialize_ttype()); + return ASR::make_Dict_t(al, loc, m_key_type, m_value_type); + } + asr_t* deserialize_Pointer() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + return ASR::make_Pointer_t(al, loc, m_type); + } + asr_t* deserialize_Allocatable() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + return ASR::make_Allocatable_t(al, loc, m_type); + } + asr_t* deserialize_CPtr() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + return ASR::make_CPtr_t(al, loc); + } + asr_t* deserialize_SymbolicExpression() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + return ASR::make_SymbolicExpression_t(al, loc); + } + asr_t* deserialize_TypeParameter() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + char *m_param; + m_param = self().read_cstring(); + return ASR::make_TypeParameter_t(al, loc, m_param); + } + asr_t* deserialize_Array() { + size_t n_dims; // Sequence + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + n_dims = self().read_int64(); + Vec v_dims; + v_dims.reserve(al, n_dims); + for (size_t i=0; i v_arg_types; + v_arg_types.reserve(al, n_arg_types); + for (size_t i=0; i(self().deserialize_ttype())); + } + ASR::ttype_t *m_return_var_type; + if (self().read_bool()) { + m_return_var_type = ASR::down_cast(self().deserialize_ttype()); + } else { + m_return_var_type = nullptr; + } + ASR::abiType m_abi = self().deserialize_abi(); + ASR::deftypeType m_deftype = self().deserialize_deftype(); + char *m_bindc_name; + bool m_bindc_name_present = self().read_bool(); + if (m_bindc_name_present) { + m_bindc_name = self().read_cstring(); + } else { + m_bindc_name = nullptr; + } + bool m_elemental = self().read_bool(); + bool m_pure = self().read_bool(); + bool m_module = self().read_bool(); + bool m_inline = self().read_bool(); + bool m_static = self().read_bool(); + n_restrictions = self().read_int64(); + Vec v_restrictions; + v_restrictions.reserve(al, n_restrictions); + for (size_t i=0; i(t); + switch (ty) { + case (ASR::ttypeType::Integer) : return self().deserialize_Integer(); + case (ASR::ttypeType::UnsignedInteger) : return self().deserialize_UnsignedInteger(); + case (ASR::ttypeType::Real) : return self().deserialize_Real(); + case (ASR::ttypeType::Complex) : return self().deserialize_Complex(); + case (ASR::ttypeType::String) : return self().deserialize_String(); + case (ASR::ttypeType::Logical) : return self().deserialize_Logical(); + case (ASR::ttypeType::Set) : return self().deserialize_Set(); + case (ASR::ttypeType::List) : return self().deserialize_List(); + case (ASR::ttypeType::Tuple) : return self().deserialize_Tuple(); + case (ASR::ttypeType::StructType) : return self().deserialize_StructType(); + case (ASR::ttypeType::EnumType) : return self().deserialize_EnumType(); + case (ASR::ttypeType::UnionType) : return self().deserialize_UnionType(); + case (ASR::ttypeType::ClassType) : return self().deserialize_ClassType(); + case (ASR::ttypeType::Dict) : return self().deserialize_Dict(); + case (ASR::ttypeType::Pointer) : return self().deserialize_Pointer(); + case (ASR::ttypeType::Allocatable) : return self().deserialize_Allocatable(); + case (ASR::ttypeType::CPtr) : return self().deserialize_CPtr(); + case (ASR::ttypeType::SymbolicExpression) : return self().deserialize_SymbolicExpression(); + case (ASR::ttypeType::TypeParameter) : return self().deserialize_TypeParameter(); + case (ASR::ttypeType::Array) : return self().deserialize_Array(); + case (ASR::ttypeType::FunctionType) : return self().deserialize_FunctionType(); + default : throw LCompilersException("Unknown type in deserialize_ttype()"); + } + throw LCompilersException("Switch statement above was not exhaustive."); + } + cast_kindType deserialize_cast_kind() { + uint8_t t = self().read_int8(); + cast_kindType ty = static_cast(t); + return ty; + } + storage_typeType deserialize_storage_type() { + uint8_t t = self().read_int8(); + storage_typeType ty = static_cast(t); + return ty; + } + accessType deserialize_access() { + uint8_t t = self().read_int8(); + accessType ty = static_cast(t); + return ty; + } + intentType deserialize_intent() { + uint8_t t = self().read_int8(); + intentType ty = static_cast(t); + return ty; + } + deftypeType deserialize_deftype() { + uint8_t t = self().read_int8(); + deftypeType ty = static_cast(t); + return ty; + } + presenceType deserialize_presence() { + uint8_t t = self().read_int8(); + presenceType ty = static_cast(t); + return ty; + } + abiType deserialize_abi() { + uint8_t t = self().read_int8(); + abiType ty = static_cast(t); + return ty; + } + dimension_t deserialize_dimension() { + dimension_t x; + { + bool present=self().read_bool(); + if (present) { + x.m_start = down_cast(deserialize_expr()); + } else { + x.m_start = nullptr; + } + } + { + bool present=self().read_bool(); + if (present) { + x.m_length = down_cast(deserialize_expr()); + } else { + x.m_length = nullptr; + } + } + return x; + } + alloc_arg_t deserialize_alloc_arg() { + alloc_arg_t x; + { + x.m_a = down_cast(deserialize_expr()); + } + { + uint64_t n = self().read_int64(); + Vec v; + v.reserve(al, n); + for (uint64_t i=0; i(deserialize_expr()); + } else { + x.m_len_expr = nullptr; + } + } + { + bool present=self().read_bool(); + if (present) { + x.m_type = down_cast(deserialize_ttype()); + } else { + x.m_type = nullptr; + } + } + return x; + } + asr_t* deserialize_Attribute() { + size_t n_args; // Sequence + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + char *m_name; + m_name = self().read_cstring(); + n_args = self().read_int64(); + Vec v_args; + v_args.reserve(al, n_args); + for (size_t i=0; i(t); + switch (ty) { + case (ASR::attributeType::Attribute) : return self().deserialize_Attribute(); + default : throw LCompilersException("Unknown type in deserialize_attribute()"); + } + throw LCompilersException("Switch statement above was not exhaustive."); + } + attribute_arg_t deserialize_attribute_arg() { + attribute_arg_t x; + { + x.m_arg = self().read_cstring(); + } + return x; + } + call_arg_t deserialize_call_arg() { + call_arg_t x; + { + bool present=self().read_bool(); + if (present) { + x.m_value = down_cast(deserialize_expr()); + } else { + x.m_value = nullptr; + } + } + return x; + } + reduction_expr_t deserialize_reduction_expr() { + reduction_expr_t x; + { + x.m_op = deserialize_reduction_op(); + } + { + x.m_arg = down_cast(deserialize_expr()); + } + return x; + } + asr_t* deserialize_Bind() { + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + char *m_lang; + m_lang = self().read_cstring(); + char *m_name; + m_name = self().read_cstring(); + return ASR::make_Bind_t(al, loc, m_lang, m_name); + } + asr_t* deserialize_tbind() { + uint8_t t = self().read_int8(); + ASR::tbindType ty = static_cast(t); + switch (ty) { + case (ASR::tbindType::Bind) : return self().deserialize_Bind(); + default : throw LCompilersException("Unknown type in deserialize_tbind()"); + } + throw LCompilersException("Switch statement above was not exhaustive."); + } + array_index_t deserialize_array_index() { + array_index_t x; + { + bool present=self().read_bool(); + if (present) { + x.m_left = down_cast(deserialize_expr()); + } else { + x.m_left = nullptr; + } + } + { + bool present=self().read_bool(); + if (present) { + x.m_right = down_cast(deserialize_expr()); + } else { + x.m_right = nullptr; + } + } + { + bool present=self().read_bool(); + if (present) { + x.m_step = down_cast(deserialize_expr()); + } else { + x.m_step = nullptr; + } + } + return x; + } + do_loop_head_t deserialize_do_loop_head() { + do_loop_head_t x; + { + bool present=self().read_bool(); + if (present) { + x.m_v = down_cast(deserialize_expr()); + } else { + x.m_v = nullptr; + } + } + { + bool present=self().read_bool(); + if (present) { + x.m_start = down_cast(deserialize_expr()); + } else { + x.m_start = nullptr; + } + } + { + bool present=self().read_bool(); + if (present) { + x.m_end = down_cast(deserialize_expr()); + } else { + x.m_end = nullptr; + } + } + { + bool present=self().read_bool(); + if (present) { + x.m_increment = down_cast(deserialize_expr()); + } else { + x.m_increment = nullptr; + } + } + return x; + } + asr_t* deserialize_CaseStmt() { + size_t n_test; // Sequence + size_t n_body; // Sequence + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + n_test = self().read_int64(); + Vec v_test; + v_test.reserve(al, n_test); + for (size_t i=0; i(self().deserialize_expr())); + } + n_body = self().read_int64(); + Vec v_body; + v_body.reserve(al, n_body); + for (size_t i=0; i(self().deserialize_stmt())); + } + bool m_fall_through = self().read_bool(); + return ASR::make_CaseStmt_t(al, loc, v_test.p, v_test.n, v_body.p, v_body.n, m_fall_through); + } + asr_t* deserialize_CaseStmt_Range() { + size_t n_body; // Sequence + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::expr_t *m_start; + if (self().read_bool()) { + m_start = ASR::down_cast(self().deserialize_expr()); + } else { + m_start = nullptr; + } + ASR::expr_t *m_end; + if (self().read_bool()) { + m_end = ASR::down_cast(self().deserialize_expr()); + } else { + m_end = nullptr; + } + n_body = self().read_int64(); + Vec v_body; + v_body.reserve(al, n_body); + for (size_t i=0; i(self().deserialize_stmt())); + } + return ASR::make_CaseStmt_Range_t(al, loc, m_start, m_end, v_body.p, v_body.n); + } + asr_t* deserialize_case_stmt() { + uint8_t t = self().read_int8(); + ASR::case_stmtType ty = static_cast(t); + switch (ty) { + case (ASR::case_stmtType::CaseStmt) : return self().deserialize_CaseStmt(); + case (ASR::case_stmtType::CaseStmt_Range) : return self().deserialize_CaseStmt_Range(); + default : throw LCompilersException("Unknown type in deserialize_case_stmt()"); + } + throw LCompilersException("Switch statement above was not exhaustive."); + } + asr_t* deserialize_TypeStmtName() { + size_t n_body; // Sequence + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::symbol_t *m_sym; + m_sym = self().read_symbol(); + n_body = self().read_int64(); + Vec v_body; + v_body.reserve(al, n_body); + for (size_t i=0; i(self().deserialize_stmt())); + } + return ASR::make_TypeStmtName_t(al, loc, m_sym, v_body.p, v_body.n); + } + asr_t* deserialize_ClassStmt() { + size_t n_body; // Sequence + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::symbol_t *m_sym; + m_sym = self().read_symbol(); + n_body = self().read_int64(); + Vec v_body; + v_body.reserve(al, n_body); + for (size_t i=0; i(self().deserialize_stmt())); + } + return ASR::make_ClassStmt_t(al, loc, m_sym, v_body.p, v_body.n); + } + asr_t* deserialize_TypeStmtType() { + size_t n_body; // Sequence + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + ASR::ttype_t *m_type; + m_type = ASR::down_cast(self().deserialize_ttype()); + n_body = self().read_int64(); + Vec v_body; + v_body.reserve(al, n_body); + for (size_t i=0; i(self().deserialize_stmt())); + } + return ASR::make_TypeStmtType_t(al, loc, m_type, v_body.p, v_body.n); + } + asr_t* deserialize_type_stmt() { + uint8_t t = self().read_int8(); + ASR::type_stmtType ty = static_cast(t); + switch (ty) { + case (ASR::type_stmtType::TypeStmtName) : return self().deserialize_TypeStmtName(); + case (ASR::type_stmtType::ClassStmt) : return self().deserialize_ClassStmt(); + case (ASR::type_stmtType::TypeStmtType) : return self().deserialize_TypeStmtType(); + default : throw LCompilersException("Unknown type in deserialize_type_stmt()"); + } + throw LCompilersException("Switch statement above was not exhaustive."); + } + enumtypeType deserialize_enumtype() { + uint8_t t = self().read_int8(); + enumtypeType ty = static_cast(t); + return ty; + } + asr_t* deserialize_Require() { + size_t n_args; // Sequence + Location loc; + loc.first = self().read_int64() + offset; + loc.last = self().read_int64() + offset; + char *m_name; + m_name = self().read_cstring(); + n_args = self().read_int64(); + Vec v_args; + v_args.reserve(al, n_args); + for (size_t i=0; i(t); + switch (ty) { + case (ASR::require_instantiationType::Require) : return self().deserialize_Require(); + default : throw LCompilersException("Unknown type in deserialize_require_instantiation()"); + } + throw LCompilersException("Switch statement above was not exhaustive."); + } + array_physical_typeType deserialize_array_physical_type() { + uint8_t t = self().read_int8(); + array_physical_typeType ty = static_cast(t); + return ty; + } + string_physical_typeType deserialize_string_physical_type() { + uint8_t t = self().read_int8(); + string_physical_typeType ty = static_cast(t); + return ty; + } + binopType deserialize_binop() { + uint8_t t = self().read_int8(); + binopType ty = static_cast(t); + return ty; + } + reduction_opType deserialize_reduction_op() { + uint8_t t = self().read_int8(); + reduction_opType ty = static_cast(t); + return ty; + } + logicalbinopType deserialize_logicalbinop() { + uint8_t t = self().read_int8(); + logicalbinopType ty = static_cast(t); + return ty; + } + cmpopType deserialize_cmpop() { + uint8_t t = self().read_int8(); + cmpopType ty = static_cast(t); + return ty; + } + integerbozType deserialize_integerboz() { + uint8_t t = self().read_int8(); + integerbozType ty = static_cast(t); + return ty; + } + arrayboundType deserialize_arraybound() { + uint8_t t = self().read_int8(); + arrayboundType ty = static_cast(t); + return ty; + } + arraystorageType deserialize_arraystorage() { + uint8_t t = self().read_int8(); + arraystorageType ty = static_cast(t); + return ty; + } + string_format_kindType deserialize_string_format_kind() { + uint8_t t = self().read_int8(); + string_format_kindType ty = static_cast(t); + return ty; + } +}; + + +} diff --git a/src/libasr/asr_expr_base_replacer_visitor.h b/src/libasr/asr_expr_base_replacer_visitor.h new file mode 100644 index 0000000000..5ca9963952 --- /dev/null +++ b/src/libasr/asr_expr_base_replacer_visitor.h @@ -0,0 +1,2643 @@ +#pragma once + +// Generated by grammar/asdl_cpp.py + +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace LCompilers::ASR { +/******************************************************************************/ +// Expression Replacer Base class + +template +class BaseExprReplacer { +public: + bool call_replacer_on_value=true; + StructType& self() { return static_cast(*this); } + + ASR::expr_t** current_expr; + + BaseExprReplacer() : current_expr(nullptr) {} + + + void replace_IfExp(IfExp_t* x) { + ASR::expr_t** current_expr_copy_0 = current_expr; + current_expr = &(x->m_test); + self().replace_expr(x->m_test); + current_expr = current_expr_copy_0; + ASR::expr_t** current_expr_copy_1 = current_expr; + current_expr = &(x->m_body); + self().replace_expr(x->m_body); + current_expr = current_expr_copy_1; + ASR::expr_t** current_expr_copy_2 = current_expr; + current_expr = &(x->m_orelse); + self().replace_expr(x->m_orelse); + current_expr = current_expr_copy_2; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_3 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_3; + } + } + + + void replace_ComplexConstructor(ComplexConstructor_t* x) { + ASR::expr_t** current_expr_copy_4 = current_expr; + current_expr = &(x->m_re); + self().replace_expr(x->m_re); + current_expr = current_expr_copy_4; + ASR::expr_t** current_expr_copy_5 = current_expr; + current_expr = &(x->m_im); + self().replace_expr(x->m_im); + current_expr = current_expr_copy_5; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_6 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_6; + } + } + + + void replace_NamedExpr(NamedExpr_t* x) { + ASR::expr_t** current_expr_copy_7 = current_expr; + current_expr = &(x->m_target); + self().replace_expr(x->m_target); + current_expr = current_expr_copy_7; + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_8 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_8; + } + self().replace_ttype(x->m_type); + } + + + void replace_FunctionCall(FunctionCall_t* x) { + for (size_t i = 0; i < x->n_args; i++) { + if (x->m_args[i].m_value != nullptr) { + ASR::expr_t** current_expr_copy_9 = current_expr; + current_expr = &(x->m_args[i].m_value); + self().replace_expr(x->m_args[i].m_value); + current_expr = current_expr_copy_9; + } + } + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_10 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_10; + } + ASR::expr_t** current_expr_copy_11 = current_expr; + current_expr = &(x->m_dt); + self().replace_expr(x->m_dt); + current_expr = current_expr_copy_11; + } + + + void replace_IntrinsicElementalFunction(IntrinsicElementalFunction_t* x) { + for (size_t i = 0; i < x->n_args; i++) { + ASR::expr_t** current_expr_copy_12 = current_expr; + current_expr = &(x->m_args[i]); + self().replace_expr(x->m_args[i]); + current_expr = current_expr_copy_12; + } + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_13 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_13; + } + } + + + void replace_IntrinsicArrayFunction(IntrinsicArrayFunction_t* x) { + for (size_t i = 0; i < x->n_args; i++) { + ASR::expr_t** current_expr_copy_14 = current_expr; + current_expr = &(x->m_args[i]); + self().replace_expr(x->m_args[i]); + current_expr = current_expr_copy_14; + } + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_15 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_15; + } + } + + + void replace_IntrinsicImpureFunction(IntrinsicImpureFunction_t* x) { + for (size_t i = 0; i < x->n_args; i++) { + ASR::expr_t** current_expr_copy_16 = current_expr; + current_expr = &(x->m_args[i]); + self().replace_expr(x->m_args[i]); + current_expr = current_expr_copy_16; + } + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_17 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_17; + } + } + + + void replace_TypeInquiry(TypeInquiry_t* x) { + self().replace_ttype(x->m_arg_type); + ASR::expr_t** current_expr_copy_18 = current_expr; + current_expr = &(x->m_arg); + self().replace_expr(x->m_arg); + current_expr = current_expr_copy_18; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_19 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_19; + } + } + + + void replace_StructConstructor(StructConstructor_t* x) { + for (size_t i = 0; i < x->n_args; i++) { + if (x->m_args[i].m_value != nullptr) { + ASR::expr_t** current_expr_copy_20 = current_expr; + current_expr = &(x->m_args[i].m_value); + self().replace_expr(x->m_args[i].m_value); + current_expr = current_expr_copy_20; + } + } + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_21 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_21; + } + } + + + void replace_StructConstant(StructConstant_t* x) { + for (size_t i = 0; i < x->n_args; i++) { + if (x->m_args[i].m_value != nullptr) { + ASR::expr_t** current_expr_copy_22 = current_expr; + current_expr = &(x->m_args[i].m_value); + self().replace_expr(x->m_args[i].m_value); + current_expr = current_expr_copy_22; + } + } + self().replace_ttype(x->m_type); + } + + + void replace_EnumConstructor(EnumConstructor_t* x) { + for (size_t i = 0; i < x->n_args; i++) { + ASR::expr_t** current_expr_copy_23 = current_expr; + current_expr = &(x->m_args[i]); + self().replace_expr(x->m_args[i]); + current_expr = current_expr_copy_23; + } + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_24 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_24; + } + } + + + void replace_UnionConstructor(UnionConstructor_t* x) { + for (size_t i = 0; i < x->n_args; i++) { + ASR::expr_t** current_expr_copy_25 = current_expr; + current_expr = &(x->m_args[i]); + self().replace_expr(x->m_args[i]); + current_expr = current_expr_copy_25; + } + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_26 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_26; + } + } + + + void replace_ImpliedDoLoop(ImpliedDoLoop_t* x) { + for (size_t i = 0; i < x->n_values; i++) { + ASR::expr_t** current_expr_copy_27 = current_expr; + current_expr = &(x->m_values[i]); + self().replace_expr(x->m_values[i]); + current_expr = current_expr_copy_27; + } + ASR::expr_t** current_expr_copy_28 = current_expr; + current_expr = &(x->m_var); + self().replace_expr(x->m_var); + current_expr = current_expr_copy_28; + ASR::expr_t** current_expr_copy_29 = current_expr; + current_expr = &(x->m_start); + self().replace_expr(x->m_start); + current_expr = current_expr_copy_29; + ASR::expr_t** current_expr_copy_30 = current_expr; + current_expr = &(x->m_end); + self().replace_expr(x->m_end); + current_expr = current_expr_copy_30; + ASR::expr_t** current_expr_copy_31 = current_expr; + current_expr = &(x->m_increment); + self().replace_expr(x->m_increment); + current_expr = current_expr_copy_31; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_32 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_32; + } + } + + + void replace_IntegerConstant(IntegerConstant_t* x) { + self().replace_ttype(x->m_type); + } + + + void replace_IntegerBitNot(IntegerBitNot_t* x) { + ASR::expr_t** current_expr_copy_33 = current_expr; + current_expr = &(x->m_arg); + self().replace_expr(x->m_arg); + current_expr = current_expr_copy_33; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_34 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_34; + } + } + + + void replace_IntegerUnaryMinus(IntegerUnaryMinus_t* x) { + ASR::expr_t** current_expr_copy_35 = current_expr; + current_expr = &(x->m_arg); + self().replace_expr(x->m_arg); + current_expr = current_expr_copy_35; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_36 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_36; + } + } + + + void replace_IntegerCompare(IntegerCompare_t* x) { + ASR::expr_t** current_expr_copy_37 = current_expr; + current_expr = &(x->m_left); + self().replace_expr(x->m_left); + current_expr = current_expr_copy_37; + ASR::expr_t** current_expr_copy_38 = current_expr; + current_expr = &(x->m_right); + self().replace_expr(x->m_right); + current_expr = current_expr_copy_38; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_39 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_39; + } + } + + + void replace_IntegerBinOp(IntegerBinOp_t* x) { + ASR::expr_t** current_expr_copy_40 = current_expr; + current_expr = &(x->m_left); + self().replace_expr(x->m_left); + current_expr = current_expr_copy_40; + ASR::expr_t** current_expr_copy_41 = current_expr; + current_expr = &(x->m_right); + self().replace_expr(x->m_right); + current_expr = current_expr_copy_41; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_42 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_42; + } + } + + + void replace_UnsignedIntegerConstant(UnsignedIntegerConstant_t* x) { + self().replace_ttype(x->m_type); + } + + + void replace_UnsignedIntegerUnaryMinus(UnsignedIntegerUnaryMinus_t* x) { + ASR::expr_t** current_expr_copy_43 = current_expr; + current_expr = &(x->m_arg); + self().replace_expr(x->m_arg); + current_expr = current_expr_copy_43; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_44 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_44; + } + } + + + void replace_UnsignedIntegerBitNot(UnsignedIntegerBitNot_t* x) { + ASR::expr_t** current_expr_copy_45 = current_expr; + current_expr = &(x->m_arg); + self().replace_expr(x->m_arg); + current_expr = current_expr_copy_45; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_46 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_46; + } + } + + + void replace_UnsignedIntegerCompare(UnsignedIntegerCompare_t* x) { + ASR::expr_t** current_expr_copy_47 = current_expr; + current_expr = &(x->m_left); + self().replace_expr(x->m_left); + current_expr = current_expr_copy_47; + ASR::expr_t** current_expr_copy_48 = current_expr; + current_expr = &(x->m_right); + self().replace_expr(x->m_right); + current_expr = current_expr_copy_48; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_49 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_49; + } + } + + + void replace_UnsignedIntegerBinOp(UnsignedIntegerBinOp_t* x) { + ASR::expr_t** current_expr_copy_50 = current_expr; + current_expr = &(x->m_left); + self().replace_expr(x->m_left); + current_expr = current_expr_copy_50; + ASR::expr_t** current_expr_copy_51 = current_expr; + current_expr = &(x->m_right); + self().replace_expr(x->m_right); + current_expr = current_expr_copy_51; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_52 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_52; + } + } + + + void replace_RealConstant(RealConstant_t* x) { + self().replace_ttype(x->m_type); + } + + + void replace_RealUnaryMinus(RealUnaryMinus_t* x) { + ASR::expr_t** current_expr_copy_53 = current_expr; + current_expr = &(x->m_arg); + self().replace_expr(x->m_arg); + current_expr = current_expr_copy_53; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_54 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_54; + } + } + + + void replace_RealCompare(RealCompare_t* x) { + ASR::expr_t** current_expr_copy_55 = current_expr; + current_expr = &(x->m_left); + self().replace_expr(x->m_left); + current_expr = current_expr_copy_55; + ASR::expr_t** current_expr_copy_56 = current_expr; + current_expr = &(x->m_right); + self().replace_expr(x->m_right); + current_expr = current_expr_copy_56; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_57 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_57; + } + } + + + void replace_RealBinOp(RealBinOp_t* x) { + ASR::expr_t** current_expr_copy_58 = current_expr; + current_expr = &(x->m_left); + self().replace_expr(x->m_left); + current_expr = current_expr_copy_58; + ASR::expr_t** current_expr_copy_59 = current_expr; + current_expr = &(x->m_right); + self().replace_expr(x->m_right); + current_expr = current_expr_copy_59; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_60 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_60; + } + } + + + void replace_RealCopySign(RealCopySign_t* x) { + ASR::expr_t** current_expr_copy_61 = current_expr; + current_expr = &(x->m_target); + self().replace_expr(x->m_target); + current_expr = current_expr_copy_61; + ASR::expr_t** current_expr_copy_62 = current_expr; + current_expr = &(x->m_source); + self().replace_expr(x->m_source); + current_expr = current_expr_copy_62; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_63 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_63; + } + } + + + void replace_ComplexConstant(ComplexConstant_t* x) { + self().replace_ttype(x->m_type); + } + + + void replace_ComplexUnaryMinus(ComplexUnaryMinus_t* x) { + ASR::expr_t** current_expr_copy_64 = current_expr; + current_expr = &(x->m_arg); + self().replace_expr(x->m_arg); + current_expr = current_expr_copy_64; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_65 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_65; + } + } + + + void replace_ComplexCompare(ComplexCompare_t* x) { + ASR::expr_t** current_expr_copy_66 = current_expr; + current_expr = &(x->m_left); + self().replace_expr(x->m_left); + current_expr = current_expr_copy_66; + ASR::expr_t** current_expr_copy_67 = current_expr; + current_expr = &(x->m_right); + self().replace_expr(x->m_right); + current_expr = current_expr_copy_67; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_68 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_68; + } + } + + + void replace_ComplexBinOp(ComplexBinOp_t* x) { + ASR::expr_t** current_expr_copy_69 = current_expr; + current_expr = &(x->m_left); + self().replace_expr(x->m_left); + current_expr = current_expr_copy_69; + ASR::expr_t** current_expr_copy_70 = current_expr; + current_expr = &(x->m_right); + self().replace_expr(x->m_right); + current_expr = current_expr_copy_70; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_71 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_71; + } + } + + + void replace_LogicalConstant(LogicalConstant_t* x) { + self().replace_ttype(x->m_type); + } + + + void replace_LogicalNot(LogicalNot_t* x) { + ASR::expr_t** current_expr_copy_72 = current_expr; + current_expr = &(x->m_arg); + self().replace_expr(x->m_arg); + current_expr = current_expr_copy_72; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_73 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_73; + } + } + + + void replace_LogicalCompare(LogicalCompare_t* x) { + ASR::expr_t** current_expr_copy_74 = current_expr; + current_expr = &(x->m_left); + self().replace_expr(x->m_left); + current_expr = current_expr_copy_74; + ASR::expr_t** current_expr_copy_75 = current_expr; + current_expr = &(x->m_right); + self().replace_expr(x->m_right); + current_expr = current_expr_copy_75; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_76 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_76; + } + } + + + void replace_LogicalBinOp(LogicalBinOp_t* x) { + ASR::expr_t** current_expr_copy_77 = current_expr; + current_expr = &(x->m_left); + self().replace_expr(x->m_left); + current_expr = current_expr_copy_77; + ASR::expr_t** current_expr_copy_78 = current_expr; + current_expr = &(x->m_right); + self().replace_expr(x->m_right); + current_expr = current_expr_copy_78; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_79 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_79; + } + } + + + void replace_ListConstant(ListConstant_t* x) { + for (size_t i = 0; i < x->n_args; i++) { + ASR::expr_t** current_expr_copy_80 = current_expr; + current_expr = &(x->m_args[i]); + self().replace_expr(x->m_args[i]); + current_expr = current_expr_copy_80; + } + self().replace_ttype(x->m_type); + } + + + void replace_ListLen(ListLen_t* x) { + ASR::expr_t** current_expr_copy_81 = current_expr; + current_expr = &(x->m_arg); + self().replace_expr(x->m_arg); + current_expr = current_expr_copy_81; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_82 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_82; + } + } + + + void replace_ListConcat(ListConcat_t* x) { + ASR::expr_t** current_expr_copy_83 = current_expr; + current_expr = &(x->m_left); + self().replace_expr(x->m_left); + current_expr = current_expr_copy_83; + ASR::expr_t** current_expr_copy_84 = current_expr; + current_expr = &(x->m_right); + self().replace_expr(x->m_right); + current_expr = current_expr_copy_84; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_85 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_85; + } + } + + + void replace_ListCompare(ListCompare_t* x) { + ASR::expr_t** current_expr_copy_86 = current_expr; + current_expr = &(x->m_left); + self().replace_expr(x->m_left); + current_expr = current_expr_copy_86; + ASR::expr_t** current_expr_copy_87 = current_expr; + current_expr = &(x->m_right); + self().replace_expr(x->m_right); + current_expr = current_expr_copy_87; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_88 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_88; + } + } + + + void replace_ListCount(ListCount_t* x) { + ASR::expr_t** current_expr_copy_89 = current_expr; + current_expr = &(x->m_arg); + self().replace_expr(x->m_arg); + current_expr = current_expr_copy_89; + ASR::expr_t** current_expr_copy_90 = current_expr; + current_expr = &(x->m_ele); + self().replace_expr(x->m_ele); + current_expr = current_expr_copy_90; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_91 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_91; + } + } + + + void replace_ListContains(ListContains_t* x) { + ASR::expr_t** current_expr_copy_92 = current_expr; + current_expr = &(x->m_left); + self().replace_expr(x->m_left); + current_expr = current_expr_copy_92; + ASR::expr_t** current_expr_copy_93 = current_expr; + current_expr = &(x->m_right); + self().replace_expr(x->m_right); + current_expr = current_expr_copy_93; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_94 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_94; + } + } + + + void replace_SetConstant(SetConstant_t* x) { + for (size_t i = 0; i < x->n_elements; i++) { + ASR::expr_t** current_expr_copy_95 = current_expr; + current_expr = &(x->m_elements[i]); + self().replace_expr(x->m_elements[i]); + current_expr = current_expr_copy_95; + } + self().replace_ttype(x->m_type); + } + + + void replace_SetLen(SetLen_t* x) { + ASR::expr_t** current_expr_copy_96 = current_expr; + current_expr = &(x->m_arg); + self().replace_expr(x->m_arg); + current_expr = current_expr_copy_96; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_97 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_97; + } + } + + + void replace_TupleConstant(TupleConstant_t* x) { + for (size_t i = 0; i < x->n_elements; i++) { + ASR::expr_t** current_expr_copy_98 = current_expr; + current_expr = &(x->m_elements[i]); + self().replace_expr(x->m_elements[i]); + current_expr = current_expr_copy_98; + } + self().replace_ttype(x->m_type); + } + + + void replace_TupleLen(TupleLen_t* x) { + ASR::expr_t** current_expr_copy_99 = current_expr; + current_expr = &(x->m_arg); + self().replace_expr(x->m_arg); + current_expr = current_expr_copy_99; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_100 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_100; + } + } + + + void replace_TupleCompare(TupleCompare_t* x) { + ASR::expr_t** current_expr_copy_101 = current_expr; + current_expr = &(x->m_left); + self().replace_expr(x->m_left); + current_expr = current_expr_copy_101; + ASR::expr_t** current_expr_copy_102 = current_expr; + current_expr = &(x->m_right); + self().replace_expr(x->m_right); + current_expr = current_expr_copy_102; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_103 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_103; + } + } + + + void replace_TupleConcat(TupleConcat_t* x) { + ASR::expr_t** current_expr_copy_104 = current_expr; + current_expr = &(x->m_left); + self().replace_expr(x->m_left); + current_expr = current_expr_copy_104; + ASR::expr_t** current_expr_copy_105 = current_expr; + current_expr = &(x->m_right); + self().replace_expr(x->m_right); + current_expr = current_expr_copy_105; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_106 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_106; + } + } + + + void replace_TupleContains(TupleContains_t* x) { + ASR::expr_t** current_expr_copy_107 = current_expr; + current_expr = &(x->m_left); + self().replace_expr(x->m_left); + current_expr = current_expr_copy_107; + ASR::expr_t** current_expr_copy_108 = current_expr; + current_expr = &(x->m_right); + self().replace_expr(x->m_right); + current_expr = current_expr_copy_108; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_109 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_109; + } + } + + + void replace_StringConstant(StringConstant_t* x) { + self().replace_ttype(x->m_type); + } + + + void replace_StringConcat(StringConcat_t* x) { + ASR::expr_t** current_expr_copy_110 = current_expr; + current_expr = &(x->m_left); + self().replace_expr(x->m_left); + current_expr = current_expr_copy_110; + ASR::expr_t** current_expr_copy_111 = current_expr; + current_expr = &(x->m_right); + self().replace_expr(x->m_right); + current_expr = current_expr_copy_111; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_112 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_112; + } + } + + + void replace_StringRepeat(StringRepeat_t* x) { + ASR::expr_t** current_expr_copy_113 = current_expr; + current_expr = &(x->m_left); + self().replace_expr(x->m_left); + current_expr = current_expr_copy_113; + ASR::expr_t** current_expr_copy_114 = current_expr; + current_expr = &(x->m_right); + self().replace_expr(x->m_right); + current_expr = current_expr_copy_114; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_115 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_115; + } + } + + + void replace_StringLen(StringLen_t* x) { + ASR::expr_t** current_expr_copy_116 = current_expr; + current_expr = &(x->m_arg); + self().replace_expr(x->m_arg); + current_expr = current_expr_copy_116; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_117 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_117; + } + } + + + void replace_StringItem(StringItem_t* x) { + ASR::expr_t** current_expr_copy_118 = current_expr; + current_expr = &(x->m_arg); + self().replace_expr(x->m_arg); + current_expr = current_expr_copy_118; + ASR::expr_t** current_expr_copy_119 = current_expr; + current_expr = &(x->m_idx); + self().replace_expr(x->m_idx); + current_expr = current_expr_copy_119; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_120 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_120; + } + } + + + void replace_StringSection(StringSection_t* x) { + ASR::expr_t** current_expr_copy_121 = current_expr; + current_expr = &(x->m_arg); + self().replace_expr(x->m_arg); + current_expr = current_expr_copy_121; + ASR::expr_t** current_expr_copy_122 = current_expr; + current_expr = &(x->m_start); + self().replace_expr(x->m_start); + current_expr = current_expr_copy_122; + ASR::expr_t** current_expr_copy_123 = current_expr; + current_expr = &(x->m_end); + self().replace_expr(x->m_end); + current_expr = current_expr_copy_123; + ASR::expr_t** current_expr_copy_124 = current_expr; + current_expr = &(x->m_step); + self().replace_expr(x->m_step); + current_expr = current_expr_copy_124; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_125 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_125; + } + } + + + void replace_StringCompare(StringCompare_t* x) { + ASR::expr_t** current_expr_copy_126 = current_expr; + current_expr = &(x->m_left); + self().replace_expr(x->m_left); + current_expr = current_expr_copy_126; + ASR::expr_t** current_expr_copy_127 = current_expr; + current_expr = &(x->m_right); + self().replace_expr(x->m_right); + current_expr = current_expr_copy_127; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_128 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_128; + } + } + + + void replace_StringContains(StringContains_t* x) { + ASR::expr_t** current_expr_copy_129 = current_expr; + current_expr = &(x->m_substr); + self().replace_expr(x->m_substr); + current_expr = current_expr_copy_129; + ASR::expr_t** current_expr_copy_130 = current_expr; + current_expr = &(x->m_str); + self().replace_expr(x->m_str); + current_expr = current_expr_copy_130; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_131 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_131; + } + } + + + void replace_StringOrd(StringOrd_t* x) { + ASR::expr_t** current_expr_copy_132 = current_expr; + current_expr = &(x->m_arg); + self().replace_expr(x->m_arg); + current_expr = current_expr_copy_132; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_133 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_133; + } + } + + + void replace_StringChr(StringChr_t* x) { + ASR::expr_t** current_expr_copy_134 = current_expr; + current_expr = &(x->m_arg); + self().replace_expr(x->m_arg); + current_expr = current_expr_copy_134; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_135 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_135; + } + } + + + void replace_StringFormat(StringFormat_t* x) { + ASR::expr_t** current_expr_copy_136 = current_expr; + current_expr = &(x->m_fmt); + self().replace_expr(x->m_fmt); + current_expr = current_expr_copy_136; + for (size_t i = 0; i < x->n_args; i++) { + ASR::expr_t** current_expr_copy_137 = current_expr; + current_expr = &(x->m_args[i]); + self().replace_expr(x->m_args[i]); + current_expr = current_expr_copy_137; + } + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_138 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_138; + } + } + + + void replace_StringPhysicalCast(StringPhysicalCast_t* x) { + ASR::expr_t** current_expr_copy_139 = current_expr; + current_expr = &(x->m_arg); + self().replace_expr(x->m_arg); + current_expr = current_expr_copy_139; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_140 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_140; + } + } + + + void replace_CPtrCompare(CPtrCompare_t* x) { + ASR::expr_t** current_expr_copy_141 = current_expr; + current_expr = &(x->m_left); + self().replace_expr(x->m_left); + current_expr = current_expr_copy_141; + ASR::expr_t** current_expr_copy_142 = current_expr; + current_expr = &(x->m_right); + self().replace_expr(x->m_right); + current_expr = current_expr_copy_142; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_143 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_143; + } + } + + + void replace_SymbolicCompare(SymbolicCompare_t* x) { + ASR::expr_t** current_expr_copy_144 = current_expr; + current_expr = &(x->m_left); + self().replace_expr(x->m_left); + current_expr = current_expr_copy_144; + ASR::expr_t** current_expr_copy_145 = current_expr; + current_expr = &(x->m_right); + self().replace_expr(x->m_right); + current_expr = current_expr_copy_145; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_146 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_146; + } + } + + + void replace_DictConstant(DictConstant_t* x) { + for (size_t i = 0; i < x->n_keys; i++) { + ASR::expr_t** current_expr_copy_147 = current_expr; + current_expr = &(x->m_keys[i]); + self().replace_expr(x->m_keys[i]); + current_expr = current_expr_copy_147; + } + for (size_t i = 0; i < x->n_values; i++) { + ASR::expr_t** current_expr_copy_148 = current_expr; + current_expr = &(x->m_values[i]); + self().replace_expr(x->m_values[i]); + current_expr = current_expr_copy_148; + } + self().replace_ttype(x->m_type); + } + + + void replace_DictLen(DictLen_t* x) { + ASR::expr_t** current_expr_copy_149 = current_expr; + current_expr = &(x->m_arg); + self().replace_expr(x->m_arg); + current_expr = current_expr_copy_149; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_150 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_150; + } + } + + + void replace_Var(Var_t* x) { + if (x) { } + } + + + void replace_FunctionParam(FunctionParam_t* x) { + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_151 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_151; + } + } + + + void replace_ArrayConstructor(ArrayConstructor_t* x) { + for (size_t i = 0; i < x->n_args; i++) { + ASR::expr_t** current_expr_copy_152 = current_expr; + current_expr = &(x->m_args[i]); + self().replace_expr(x->m_args[i]); + current_expr = current_expr_copy_152; + } + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_153 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_153; + } + } + + + void replace_ArrayConstant(ArrayConstant_t* x) { + self().replace_ttype(x->m_type); + } + + + void replace_ArrayItem(ArrayItem_t* x) { + ASR::expr_t** current_expr_copy_154 = current_expr; + current_expr = &(x->m_v); + self().replace_expr(x->m_v); + current_expr = current_expr_copy_154; + for (size_t i = 0; i < x->n_args; i++) { + if (x->m_args[i].m_left != nullptr) { + ASR::expr_t** current_expr_copy_155 = current_expr; + current_expr = &(x->m_args[i].m_left); + self().replace_expr(x->m_args[i].m_left); + current_expr = current_expr_copy_155; + } + if (x->m_args[i].m_right != nullptr) { + ASR::expr_t** current_expr_copy_156 = current_expr; + current_expr = &(x->m_args[i].m_right); + self().replace_expr(x->m_args[i].m_right); + current_expr = current_expr_copy_156; + } + if (x->m_args[i].m_step != nullptr) { + ASR::expr_t** current_expr_copy_157 = current_expr; + current_expr = &(x->m_args[i].m_step); + self().replace_expr(x->m_args[i].m_step); + current_expr = current_expr_copy_157; + } + } + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_158 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_158; + } + } + + + void replace_ArraySection(ArraySection_t* x) { + ASR::expr_t** current_expr_copy_159 = current_expr; + current_expr = &(x->m_v); + self().replace_expr(x->m_v); + current_expr = current_expr_copy_159; + for (size_t i = 0; i < x->n_args; i++) { + if (x->m_args[i].m_left != nullptr) { + ASR::expr_t** current_expr_copy_160 = current_expr; + current_expr = &(x->m_args[i].m_left); + self().replace_expr(x->m_args[i].m_left); + current_expr = current_expr_copy_160; + } + if (x->m_args[i].m_right != nullptr) { + ASR::expr_t** current_expr_copy_161 = current_expr; + current_expr = &(x->m_args[i].m_right); + self().replace_expr(x->m_args[i].m_right); + current_expr = current_expr_copy_161; + } + if (x->m_args[i].m_step != nullptr) { + ASR::expr_t** current_expr_copy_162 = current_expr; + current_expr = &(x->m_args[i].m_step); + self().replace_expr(x->m_args[i].m_step); + current_expr = current_expr_copy_162; + } + } + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_163 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_163; + } + } + + + void replace_ArraySize(ArraySize_t* x) { + ASR::expr_t** current_expr_copy_164 = current_expr; + current_expr = &(x->m_v); + self().replace_expr(x->m_v); + current_expr = current_expr_copy_164; + ASR::expr_t** current_expr_copy_165 = current_expr; + current_expr = &(x->m_dim); + self().replace_expr(x->m_dim); + current_expr = current_expr_copy_165; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_166 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_166; + } + } + + + void replace_ArrayBound(ArrayBound_t* x) { + ASR::expr_t** current_expr_copy_167 = current_expr; + current_expr = &(x->m_v); + self().replace_expr(x->m_v); + current_expr = current_expr_copy_167; + ASR::expr_t** current_expr_copy_168 = current_expr; + current_expr = &(x->m_dim); + self().replace_expr(x->m_dim); + current_expr = current_expr_copy_168; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_169 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_169; + } + } + + + void replace_ArrayTranspose(ArrayTranspose_t* x) { + ASR::expr_t** current_expr_copy_170 = current_expr; + current_expr = &(x->m_matrix); + self().replace_expr(x->m_matrix); + current_expr = current_expr_copy_170; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_171 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_171; + } + } + + + void replace_ArrayPack(ArrayPack_t* x) { + ASR::expr_t** current_expr_copy_172 = current_expr; + current_expr = &(x->m_array); + self().replace_expr(x->m_array); + current_expr = current_expr_copy_172; + ASR::expr_t** current_expr_copy_173 = current_expr; + current_expr = &(x->m_mask); + self().replace_expr(x->m_mask); + current_expr = current_expr_copy_173; + ASR::expr_t** current_expr_copy_174 = current_expr; + current_expr = &(x->m_vector); + self().replace_expr(x->m_vector); + current_expr = current_expr_copy_174; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_175 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_175; + } + } + + + void replace_ArrayReshape(ArrayReshape_t* x) { + ASR::expr_t** current_expr_copy_176 = current_expr; + current_expr = &(x->m_array); + self().replace_expr(x->m_array); + current_expr = current_expr_copy_176; + ASR::expr_t** current_expr_copy_177 = current_expr; + current_expr = &(x->m_shape); + self().replace_expr(x->m_shape); + current_expr = current_expr_copy_177; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_178 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_178; + } + } + + + void replace_ArrayAll(ArrayAll_t* x) { + ASR::expr_t** current_expr_copy_179 = current_expr; + current_expr = &(x->m_mask); + self().replace_expr(x->m_mask); + current_expr = current_expr_copy_179; + ASR::expr_t** current_expr_copy_180 = current_expr; + current_expr = &(x->m_dim); + self().replace_expr(x->m_dim); + current_expr = current_expr_copy_180; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_181 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_181; + } + } + + + void replace_ArrayBroadcast(ArrayBroadcast_t* x) { + ASR::expr_t** current_expr_copy_182 = current_expr; + current_expr = &(x->m_array); + self().replace_expr(x->m_array); + current_expr = current_expr_copy_182; + ASR::expr_t** current_expr_copy_183 = current_expr; + current_expr = &(x->m_shape); + self().replace_expr(x->m_shape); + current_expr = current_expr_copy_183; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_184 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_184; + } + } + + + void replace_BitCast(BitCast_t* x) { + ASR::expr_t** current_expr_copy_185 = current_expr; + current_expr = &(x->m_source); + self().replace_expr(x->m_source); + current_expr = current_expr_copy_185; + ASR::expr_t** current_expr_copy_186 = current_expr; + current_expr = &(x->m_mold); + self().replace_expr(x->m_mold); + current_expr = current_expr_copy_186; + ASR::expr_t** current_expr_copy_187 = current_expr; + current_expr = &(x->m_size); + self().replace_expr(x->m_size); + current_expr = current_expr_copy_187; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_188 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_188; + } + } + + + void replace_StructInstanceMember(StructInstanceMember_t* x) { + ASR::expr_t** current_expr_copy_189 = current_expr; + current_expr = &(x->m_v); + self().replace_expr(x->m_v); + current_expr = current_expr_copy_189; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_190 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_190; + } + } + + + void replace_StructStaticMember(StructStaticMember_t* x) { + ASR::expr_t** current_expr_copy_191 = current_expr; + current_expr = &(x->m_v); + self().replace_expr(x->m_v); + current_expr = current_expr_copy_191; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_192 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_192; + } + } + + + void replace_EnumStaticMember(EnumStaticMember_t* x) { + ASR::expr_t** current_expr_copy_193 = current_expr; + current_expr = &(x->m_v); + self().replace_expr(x->m_v); + current_expr = current_expr_copy_193; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_194 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_194; + } + } + + + void replace_UnionInstanceMember(UnionInstanceMember_t* x) { + ASR::expr_t** current_expr_copy_195 = current_expr; + current_expr = &(x->m_v); + self().replace_expr(x->m_v); + current_expr = current_expr_copy_195; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_196 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_196; + } + } + + + void replace_EnumName(EnumName_t* x) { + ASR::expr_t** current_expr_copy_197 = current_expr; + current_expr = &(x->m_v); + self().replace_expr(x->m_v); + current_expr = current_expr_copy_197; + self().replace_ttype(x->m_enum_type); + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_198 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_198; + } + } + + + void replace_EnumValue(EnumValue_t* x) { + ASR::expr_t** current_expr_copy_199 = current_expr; + current_expr = &(x->m_v); + self().replace_expr(x->m_v); + current_expr = current_expr_copy_199; + self().replace_ttype(x->m_enum_type); + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_200 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_200; + } + } + + + void replace_OverloadedCompare(OverloadedCompare_t* x) { + ASR::expr_t** current_expr_copy_201 = current_expr; + current_expr = &(x->m_left); + self().replace_expr(x->m_left); + current_expr = current_expr_copy_201; + ASR::expr_t** current_expr_copy_202 = current_expr; + current_expr = &(x->m_right); + self().replace_expr(x->m_right); + current_expr = current_expr_copy_202; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_203 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_203; + } + ASR::expr_t** current_expr_copy_204 = current_expr; + current_expr = &(x->m_overloaded); + self().replace_expr(x->m_overloaded); + current_expr = current_expr_copy_204; + } + + + void replace_OverloadedBinOp(OverloadedBinOp_t* x) { + ASR::expr_t** current_expr_copy_205 = current_expr; + current_expr = &(x->m_left); + self().replace_expr(x->m_left); + current_expr = current_expr_copy_205; + ASR::expr_t** current_expr_copy_206 = current_expr; + current_expr = &(x->m_right); + self().replace_expr(x->m_right); + current_expr = current_expr_copy_206; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_207 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_207; + } + ASR::expr_t** current_expr_copy_208 = current_expr; + current_expr = &(x->m_overloaded); + self().replace_expr(x->m_overloaded); + current_expr = current_expr_copy_208; + } + + + void replace_OverloadedUnaryMinus(OverloadedUnaryMinus_t* x) { + ASR::expr_t** current_expr_copy_209 = current_expr; + current_expr = &(x->m_arg); + self().replace_expr(x->m_arg); + current_expr = current_expr_copy_209; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_210 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_210; + } + ASR::expr_t** current_expr_copy_211 = current_expr; + current_expr = &(x->m_overloaded); + self().replace_expr(x->m_overloaded); + current_expr = current_expr_copy_211; + } + + + void replace_OverloadedStringConcat(OverloadedStringConcat_t* x) { + ASR::expr_t** current_expr_copy_212 = current_expr; + current_expr = &(x->m_left); + self().replace_expr(x->m_left); + current_expr = current_expr_copy_212; + ASR::expr_t** current_expr_copy_213 = current_expr; + current_expr = &(x->m_right); + self().replace_expr(x->m_right); + current_expr = current_expr_copy_213; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_214 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_214; + } + ASR::expr_t** current_expr_copy_215 = current_expr; + current_expr = &(x->m_overloaded); + self().replace_expr(x->m_overloaded); + current_expr = current_expr_copy_215; + } + + + void replace_Cast(Cast_t* x) { + ASR::expr_t** current_expr_copy_216 = current_expr; + current_expr = &(x->m_arg); + self().replace_expr(x->m_arg); + current_expr = current_expr_copy_216; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_217 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_217; + } + } + + + void replace_ArrayPhysicalCast(ArrayPhysicalCast_t* x) { + ASR::expr_t** current_expr_copy_218 = current_expr; + current_expr = &(x->m_arg); + self().replace_expr(x->m_arg); + current_expr = current_expr_copy_218; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_219 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_219; + } + } + + + void replace_ComplexRe(ComplexRe_t* x) { + ASR::expr_t** current_expr_copy_220 = current_expr; + current_expr = &(x->m_arg); + self().replace_expr(x->m_arg); + current_expr = current_expr_copy_220; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_221 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_221; + } + } + + + void replace_ComplexIm(ComplexIm_t* x) { + ASR::expr_t** current_expr_copy_222 = current_expr; + current_expr = &(x->m_arg); + self().replace_expr(x->m_arg); + current_expr = current_expr_copy_222; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_223 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_223; + } + } + + + void replace_DictItem(DictItem_t* x) { + ASR::expr_t** current_expr_copy_224 = current_expr; + current_expr = &(x->m_a); + self().replace_expr(x->m_a); + current_expr = current_expr_copy_224; + ASR::expr_t** current_expr_copy_225 = current_expr; + current_expr = &(x->m_key); + self().replace_expr(x->m_key); + current_expr = current_expr_copy_225; + ASR::expr_t** current_expr_copy_226 = current_expr; + current_expr = &(x->m_default); + self().replace_expr(x->m_default); + current_expr = current_expr_copy_226; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_227 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_227; + } + } + + + void replace_CLoc(CLoc_t* x) { + ASR::expr_t** current_expr_copy_228 = current_expr; + current_expr = &(x->m_arg); + self().replace_expr(x->m_arg); + current_expr = current_expr_copy_228; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_229 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_229; + } + } + + + void replace_PointerToCPtr(PointerToCPtr_t* x) { + ASR::expr_t** current_expr_copy_230 = current_expr; + current_expr = &(x->m_arg); + self().replace_expr(x->m_arg); + current_expr = current_expr_copy_230; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_231 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_231; + } + } + + + void replace_GetPointer(GetPointer_t* x) { + ASR::expr_t** current_expr_copy_232 = current_expr; + current_expr = &(x->m_arg); + self().replace_expr(x->m_arg); + current_expr = current_expr_copy_232; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_233 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_233; + } + } + + + void replace_ListItem(ListItem_t* x) { + ASR::expr_t** current_expr_copy_234 = current_expr; + current_expr = &(x->m_a); + self().replace_expr(x->m_a); + current_expr = current_expr_copy_234; + ASR::expr_t** current_expr_copy_235 = current_expr; + current_expr = &(x->m_pos); + self().replace_expr(x->m_pos); + current_expr = current_expr_copy_235; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_236 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_236; + } + } + + + void replace_TupleItem(TupleItem_t* x) { + ASR::expr_t** current_expr_copy_237 = current_expr; + current_expr = &(x->m_a); + self().replace_expr(x->m_a); + current_expr = current_expr_copy_237; + ASR::expr_t** current_expr_copy_238 = current_expr; + current_expr = &(x->m_pos); + self().replace_expr(x->m_pos); + current_expr = current_expr_copy_238; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_239 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_239; + } + } + + + void replace_ListSection(ListSection_t* x) { + ASR::expr_t** current_expr_copy_240 = current_expr; + current_expr = &(x->m_a); + self().replace_expr(x->m_a); + current_expr = current_expr_copy_240; + if (x->m_section.m_left != nullptr) { + ASR::expr_t** current_expr_copy_241 = current_expr; + current_expr = &(x->m_section.m_left); + self().replace_expr(x->m_section.m_left); + current_expr = current_expr_copy_241; + } + if (x->m_section.m_right != nullptr) { + ASR::expr_t** current_expr_copy_242 = current_expr; + current_expr = &(x->m_section.m_right); + self().replace_expr(x->m_section.m_right); + current_expr = current_expr_copy_242; + } + if (x->m_section.m_step != nullptr) { + ASR::expr_t** current_expr_copy_243 = current_expr; + current_expr = &(x->m_section.m_step); + self().replace_expr(x->m_section.m_step); + current_expr = current_expr_copy_243; + } + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_244 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_244; + } + } + + + void replace_ListRepeat(ListRepeat_t* x) { + ASR::expr_t** current_expr_copy_245 = current_expr; + current_expr = &(x->m_left); + self().replace_expr(x->m_left); + current_expr = current_expr_copy_245; + ASR::expr_t** current_expr_copy_246 = current_expr; + current_expr = &(x->m_right); + self().replace_expr(x->m_right); + current_expr = current_expr_copy_246; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_247 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_247; + } + } + + + void replace_DictPop(DictPop_t* x) { + ASR::expr_t** current_expr_copy_248 = current_expr; + current_expr = &(x->m_a); + self().replace_expr(x->m_a); + current_expr = current_expr_copy_248; + ASR::expr_t** current_expr_copy_249 = current_expr; + current_expr = &(x->m_key); + self().replace_expr(x->m_key); + current_expr = current_expr_copy_249; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_250 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_250; + } + } + + + void replace_SetPop(SetPop_t* x) { + ASR::expr_t** current_expr_copy_251 = current_expr; + current_expr = &(x->m_a); + self().replace_expr(x->m_a); + current_expr = current_expr_copy_251; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_252 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_252; + } + } + + + void replace_SetContains(SetContains_t* x) { + ASR::expr_t** current_expr_copy_253 = current_expr; + current_expr = &(x->m_left); + self().replace_expr(x->m_left); + current_expr = current_expr_copy_253; + ASR::expr_t** current_expr_copy_254 = current_expr; + current_expr = &(x->m_right); + self().replace_expr(x->m_right); + current_expr = current_expr_copy_254; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_255 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_255; + } + } + + + void replace_DictContains(DictContains_t* x) { + ASR::expr_t** current_expr_copy_256 = current_expr; + current_expr = &(x->m_left); + self().replace_expr(x->m_left); + current_expr = current_expr_copy_256; + ASR::expr_t** current_expr_copy_257 = current_expr; + current_expr = &(x->m_right); + self().replace_expr(x->m_right); + current_expr = current_expr_copy_257; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_258 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_258; + } + } + + + void replace_IntegerBitLen(IntegerBitLen_t* x) { + ASR::expr_t** current_expr_copy_259 = current_expr; + current_expr = &(x->m_a); + self().replace_expr(x->m_a); + current_expr = current_expr_copy_259; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_260 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_260; + } + } + + + void replace_Ichar(Ichar_t* x) { + ASR::expr_t** current_expr_copy_261 = current_expr; + current_expr = &(x->m_arg); + self().replace_expr(x->m_arg); + current_expr = current_expr_copy_261; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_262 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_262; + } + } + + + void replace_Iachar(Iachar_t* x) { + ASR::expr_t** current_expr_copy_263 = current_expr; + current_expr = &(x->m_arg); + self().replace_expr(x->m_arg); + current_expr = current_expr_copy_263; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_264 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_264; + } + } + + + void replace_SizeOfType(SizeOfType_t* x) { + self().replace_ttype(x->m_arg); + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_265 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_265; + } + } + + + void replace_PointerNullConstant(PointerNullConstant_t* x) { + self().replace_ttype(x->m_type); + } + + + void replace_PointerAssociated(PointerAssociated_t* x) { + ASR::expr_t** current_expr_copy_266 = current_expr; + current_expr = &(x->m_ptr); + self().replace_expr(x->m_ptr); + current_expr = current_expr_copy_266; + ASR::expr_t** current_expr_copy_267 = current_expr; + current_expr = &(x->m_tgt); + self().replace_expr(x->m_tgt); + current_expr = current_expr_copy_267; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_268 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_268; + } + } + + + void replace_RealSqrt(RealSqrt_t* x) { + ASR::expr_t** current_expr_copy_269 = current_expr; + current_expr = &(x->m_arg); + self().replace_expr(x->m_arg); + current_expr = current_expr_copy_269; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_270 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_270; + } + } + + + void replace_ArrayIsContiguous(ArrayIsContiguous_t* x) { + ASR::expr_t** current_expr_copy_271 = current_expr; + current_expr = &(x->m_array); + self().replace_expr(x->m_array); + current_expr = current_expr_copy_271; + self().replace_ttype(x->m_type); + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_272 = current_expr; + current_expr = &(x->m_value); + self().replace_expr(x->m_value); + current_expr = current_expr_copy_272; + } + } + + + void replace_Integer(Integer_t* x) { + if (x) { } + } + + + void replace_UnsignedInteger(UnsignedInteger_t* x) { + if (x) { } + } + + + void replace_Real(Real_t* x) { + if (x) { } + } + + + void replace_Complex(Complex_t* x) { + if (x) { } + } + + + void replace_String(String_t* x) { + ASR::expr_t** current_expr_copy_273 = current_expr; + current_expr = &(x->m_len_expr); + self().replace_expr(x->m_len_expr); + current_expr = current_expr_copy_273; + } + + + void replace_Logical(Logical_t* x) { + if (x) { } + } + + + void replace_Set(Set_t* x) { + self().replace_ttype(x->m_type); + } + + + void replace_List(List_t* x) { + self().replace_ttype(x->m_type); + } + + + void replace_Tuple(Tuple_t* x) { + for (size_t i = 0; i < x->n_type; i++) { + self().replace_ttype(x->m_type[i]); + } + } + + + void replace_StructType(StructType_t* x) { + for (size_t i = 0; i < x->n_data_member_types; i++) { + self().replace_ttype(x->m_data_member_types[i]); + } + for (size_t i = 0; i < x->n_member_function_types; i++) { + self().replace_ttype(x->m_member_function_types[i]); + } + } + + + void replace_EnumType(EnumType_t* x) { + if (x) { } + } + + + void replace_UnionType(UnionType_t* x) { + if (x) { } + } + + + void replace_ClassType(ClassType_t* x) { + if (x) { } + } + + + void replace_Dict(Dict_t* x) { + self().replace_ttype(x->m_key_type); + self().replace_ttype(x->m_value_type); + } + + + void replace_Pointer(Pointer_t* x) { + self().replace_ttype(x->m_type); + } + + + void replace_Allocatable(Allocatable_t* x) { + self().replace_ttype(x->m_type); + } + + + void replace_CPtr(CPtr_t* x) { + if (x) { } + } + + + void replace_SymbolicExpression(SymbolicExpression_t* x) { + if (x) { } + } + + + void replace_TypeParameter(TypeParameter_t* x) { + if (x) { } + } + + + void replace_Array(Array_t* x) { + self().replace_ttype(x->m_type); + for (size_t i = 0; i < x->n_dims; i++) { + ASR::expr_t** current_expr_copy_274 = current_expr; + current_expr = &(x->m_dims[i].m_length); + self().replace_expr(x->m_dims[i].m_length); + current_expr = current_expr_copy_274; + ASR::expr_t** current_expr_copy_275 = current_expr; + current_expr = &(x->m_dims[i].m_start); + self().replace_expr(x->m_dims[i].m_start); + current_expr = current_expr_copy_275; + } + } + + + void replace_FunctionType(FunctionType_t* x) { + for (size_t i = 0; i < x->n_arg_types; i++) { + self().replace_ttype(x->m_arg_types[i]); + } + self().replace_ttype(x->m_return_var_type); + for (size_t i = 0; i < x->n_restrictions; i++) { + } + } + + void replace_expr(ASR::expr_t* x) { + if( !x ) { + return ; + } + + switch(x->type) { + case ASR::exprType::IfExp: { + self().replace_IfExp(down_cast(x)); + break; + } + case ASR::exprType::ComplexConstructor: { + self().replace_ComplexConstructor(down_cast(x)); + break; + } + case ASR::exprType::NamedExpr: { + self().replace_NamedExpr(down_cast(x)); + break; + } + case ASR::exprType::FunctionCall: { + self().replace_FunctionCall(down_cast(x)); + break; + } + case ASR::exprType::IntrinsicElementalFunction: { + self().replace_IntrinsicElementalFunction(down_cast(x)); + break; + } + case ASR::exprType::IntrinsicArrayFunction: { + self().replace_IntrinsicArrayFunction(down_cast(x)); + break; + } + case ASR::exprType::IntrinsicImpureFunction: { + self().replace_IntrinsicImpureFunction(down_cast(x)); + break; + } + case ASR::exprType::TypeInquiry: { + self().replace_TypeInquiry(down_cast(x)); + break; + } + case ASR::exprType::StructConstructor: { + self().replace_StructConstructor(down_cast(x)); + break; + } + case ASR::exprType::StructConstant: { + self().replace_StructConstant(down_cast(x)); + break; + } + case ASR::exprType::EnumConstructor: { + self().replace_EnumConstructor(down_cast(x)); + break; + } + case ASR::exprType::UnionConstructor: { + self().replace_UnionConstructor(down_cast(x)); + break; + } + case ASR::exprType::ImpliedDoLoop: { + self().replace_ImpliedDoLoop(down_cast(x)); + break; + } + case ASR::exprType::IntegerConstant: { + self().replace_IntegerConstant(down_cast(x)); + break; + } + case ASR::exprType::IntegerBitNot: { + self().replace_IntegerBitNot(down_cast(x)); + break; + } + case ASR::exprType::IntegerUnaryMinus: { + self().replace_IntegerUnaryMinus(down_cast(x)); + break; + } + case ASR::exprType::IntegerCompare: { + self().replace_IntegerCompare(down_cast(x)); + break; + } + case ASR::exprType::IntegerBinOp: { + self().replace_IntegerBinOp(down_cast(x)); + break; + } + case ASR::exprType::UnsignedIntegerConstant: { + self().replace_UnsignedIntegerConstant(down_cast(x)); + break; + } + case ASR::exprType::UnsignedIntegerUnaryMinus: { + self().replace_UnsignedIntegerUnaryMinus(down_cast(x)); + break; + } + case ASR::exprType::UnsignedIntegerBitNot: { + self().replace_UnsignedIntegerBitNot(down_cast(x)); + break; + } + case ASR::exprType::UnsignedIntegerCompare: { + self().replace_UnsignedIntegerCompare(down_cast(x)); + break; + } + case ASR::exprType::UnsignedIntegerBinOp: { + self().replace_UnsignedIntegerBinOp(down_cast(x)); + break; + } + case ASR::exprType::RealConstant: { + self().replace_RealConstant(down_cast(x)); + break; + } + case ASR::exprType::RealUnaryMinus: { + self().replace_RealUnaryMinus(down_cast(x)); + break; + } + case ASR::exprType::RealCompare: { + self().replace_RealCompare(down_cast(x)); + break; + } + case ASR::exprType::RealBinOp: { + self().replace_RealBinOp(down_cast(x)); + break; + } + case ASR::exprType::RealCopySign: { + self().replace_RealCopySign(down_cast(x)); + break; + } + case ASR::exprType::ComplexConstant: { + self().replace_ComplexConstant(down_cast(x)); + break; + } + case ASR::exprType::ComplexUnaryMinus: { + self().replace_ComplexUnaryMinus(down_cast(x)); + break; + } + case ASR::exprType::ComplexCompare: { + self().replace_ComplexCompare(down_cast(x)); + break; + } + case ASR::exprType::ComplexBinOp: { + self().replace_ComplexBinOp(down_cast(x)); + break; + } + case ASR::exprType::LogicalConstant: { + self().replace_LogicalConstant(down_cast(x)); + break; + } + case ASR::exprType::LogicalNot: { + self().replace_LogicalNot(down_cast(x)); + break; + } + case ASR::exprType::LogicalCompare: { + self().replace_LogicalCompare(down_cast(x)); + break; + } + case ASR::exprType::LogicalBinOp: { + self().replace_LogicalBinOp(down_cast(x)); + break; + } + case ASR::exprType::ListConstant: { + self().replace_ListConstant(down_cast(x)); + break; + } + case ASR::exprType::ListLen: { + self().replace_ListLen(down_cast(x)); + break; + } + case ASR::exprType::ListConcat: { + self().replace_ListConcat(down_cast(x)); + break; + } + case ASR::exprType::ListCompare: { + self().replace_ListCompare(down_cast(x)); + break; + } + case ASR::exprType::ListCount: { + self().replace_ListCount(down_cast(x)); + break; + } + case ASR::exprType::ListContains: { + self().replace_ListContains(down_cast(x)); + break; + } + case ASR::exprType::SetConstant: { + self().replace_SetConstant(down_cast(x)); + break; + } + case ASR::exprType::SetLen: { + self().replace_SetLen(down_cast(x)); + break; + } + case ASR::exprType::TupleConstant: { + self().replace_TupleConstant(down_cast(x)); + break; + } + case ASR::exprType::TupleLen: { + self().replace_TupleLen(down_cast(x)); + break; + } + case ASR::exprType::TupleCompare: { + self().replace_TupleCompare(down_cast(x)); + break; + } + case ASR::exprType::TupleConcat: { + self().replace_TupleConcat(down_cast(x)); + break; + } + case ASR::exprType::TupleContains: { + self().replace_TupleContains(down_cast(x)); + break; + } + case ASR::exprType::StringConstant: { + self().replace_StringConstant(down_cast(x)); + break; + } + case ASR::exprType::StringConcat: { + self().replace_StringConcat(down_cast(x)); + break; + } + case ASR::exprType::StringRepeat: { + self().replace_StringRepeat(down_cast(x)); + break; + } + case ASR::exprType::StringLen: { + self().replace_StringLen(down_cast(x)); + break; + } + case ASR::exprType::StringItem: { + self().replace_StringItem(down_cast(x)); + break; + } + case ASR::exprType::StringSection: { + self().replace_StringSection(down_cast(x)); + break; + } + case ASR::exprType::StringCompare: { + self().replace_StringCompare(down_cast(x)); + break; + } + case ASR::exprType::StringContains: { + self().replace_StringContains(down_cast(x)); + break; + } + case ASR::exprType::StringOrd: { + self().replace_StringOrd(down_cast(x)); + break; + } + case ASR::exprType::StringChr: { + self().replace_StringChr(down_cast(x)); + break; + } + case ASR::exprType::StringFormat: { + self().replace_StringFormat(down_cast(x)); + break; + } + case ASR::exprType::StringPhysicalCast: { + self().replace_StringPhysicalCast(down_cast(x)); + break; + } + case ASR::exprType::CPtrCompare: { + self().replace_CPtrCompare(down_cast(x)); + break; + } + case ASR::exprType::SymbolicCompare: { + self().replace_SymbolicCompare(down_cast(x)); + break; + } + case ASR::exprType::DictConstant: { + self().replace_DictConstant(down_cast(x)); + break; + } + case ASR::exprType::DictLen: { + self().replace_DictLen(down_cast(x)); + break; + } + case ASR::exprType::Var: { + self().replace_Var(down_cast(x)); + break; + } + case ASR::exprType::FunctionParam: { + self().replace_FunctionParam(down_cast(x)); + break; + } + case ASR::exprType::ArrayConstructor: { + self().replace_ArrayConstructor(down_cast(x)); + break; + } + case ASR::exprType::ArrayConstant: { + self().replace_ArrayConstant(down_cast(x)); + break; + } + case ASR::exprType::ArrayItem: { + self().replace_ArrayItem(down_cast(x)); + break; + } + case ASR::exprType::ArraySection: { + self().replace_ArraySection(down_cast(x)); + break; + } + case ASR::exprType::ArraySize: { + self().replace_ArraySize(down_cast(x)); + break; + } + case ASR::exprType::ArrayBound: { + self().replace_ArrayBound(down_cast(x)); + break; + } + case ASR::exprType::ArrayTranspose: { + self().replace_ArrayTranspose(down_cast(x)); + break; + } + case ASR::exprType::ArrayPack: { + self().replace_ArrayPack(down_cast(x)); + break; + } + case ASR::exprType::ArrayReshape: { + self().replace_ArrayReshape(down_cast(x)); + break; + } + case ASR::exprType::ArrayAll: { + self().replace_ArrayAll(down_cast(x)); + break; + } + case ASR::exprType::ArrayBroadcast: { + self().replace_ArrayBroadcast(down_cast(x)); + break; + } + case ASR::exprType::BitCast: { + self().replace_BitCast(down_cast(x)); + break; + } + case ASR::exprType::StructInstanceMember: { + self().replace_StructInstanceMember(down_cast(x)); + break; + } + case ASR::exprType::StructStaticMember: { + self().replace_StructStaticMember(down_cast(x)); + break; + } + case ASR::exprType::EnumStaticMember: { + self().replace_EnumStaticMember(down_cast(x)); + break; + } + case ASR::exprType::UnionInstanceMember: { + self().replace_UnionInstanceMember(down_cast(x)); + break; + } + case ASR::exprType::EnumName: { + self().replace_EnumName(down_cast(x)); + break; + } + case ASR::exprType::EnumValue: { + self().replace_EnumValue(down_cast(x)); + break; + } + case ASR::exprType::OverloadedCompare: { + self().replace_OverloadedCompare(down_cast(x)); + break; + } + case ASR::exprType::OverloadedBinOp: { + self().replace_OverloadedBinOp(down_cast(x)); + break; + } + case ASR::exprType::OverloadedUnaryMinus: { + self().replace_OverloadedUnaryMinus(down_cast(x)); + break; + } + case ASR::exprType::OverloadedStringConcat: { + self().replace_OverloadedStringConcat(down_cast(x)); + break; + } + case ASR::exprType::Cast: { + self().replace_Cast(down_cast(x)); + break; + } + case ASR::exprType::ArrayPhysicalCast: { + self().replace_ArrayPhysicalCast(down_cast(x)); + break; + } + case ASR::exprType::ComplexRe: { + self().replace_ComplexRe(down_cast(x)); + break; + } + case ASR::exprType::ComplexIm: { + self().replace_ComplexIm(down_cast(x)); + break; + } + case ASR::exprType::DictItem: { + self().replace_DictItem(down_cast(x)); + break; + } + case ASR::exprType::CLoc: { + self().replace_CLoc(down_cast(x)); + break; + } + case ASR::exprType::PointerToCPtr: { + self().replace_PointerToCPtr(down_cast(x)); + break; + } + case ASR::exprType::GetPointer: { + self().replace_GetPointer(down_cast(x)); + break; + } + case ASR::exprType::ListItem: { + self().replace_ListItem(down_cast(x)); + break; + } + case ASR::exprType::TupleItem: { + self().replace_TupleItem(down_cast(x)); + break; + } + case ASR::exprType::ListSection: { + self().replace_ListSection(down_cast(x)); + break; + } + case ASR::exprType::ListRepeat: { + self().replace_ListRepeat(down_cast(x)); + break; + } + case ASR::exprType::DictPop: { + self().replace_DictPop(down_cast(x)); + break; + } + case ASR::exprType::SetPop: { + self().replace_SetPop(down_cast(x)); + break; + } + case ASR::exprType::SetContains: { + self().replace_SetContains(down_cast(x)); + break; + } + case ASR::exprType::DictContains: { + self().replace_DictContains(down_cast(x)); + break; + } + case ASR::exprType::IntegerBitLen: { + self().replace_IntegerBitLen(down_cast(x)); + break; + } + case ASR::exprType::Ichar: { + self().replace_Ichar(down_cast(x)); + break; + } + case ASR::exprType::Iachar: { + self().replace_Iachar(down_cast(x)); + break; + } + case ASR::exprType::SizeOfType: { + self().replace_SizeOfType(down_cast(x)); + break; + } + case ASR::exprType::PointerNullConstant: { + self().replace_PointerNullConstant(down_cast(x)); + break; + } + case ASR::exprType::PointerAssociated: { + self().replace_PointerAssociated(down_cast(x)); + break; + } + case ASR::exprType::RealSqrt: { + self().replace_RealSqrt(down_cast(x)); + break; + } + case ASR::exprType::ArrayIsContiguous: { + self().replace_ArrayIsContiguous(down_cast(x)); + break; + } + default: { + LCOMPILERS_ASSERT_MSG(false, "Replacement in " + std::to_string(x->type) + " expression is not supported yet."); + } + } + + } + void replace_ttype(ASR::ttype_t* x) { + if( !x ) { + return ; + } + + switch(x->type) { + case ASR::ttypeType::Integer: { + self().replace_Integer(down_cast(x)); + break; + } + case ASR::ttypeType::UnsignedInteger: { + self().replace_UnsignedInteger(down_cast(x)); + break; + } + case ASR::ttypeType::Real: { + self().replace_Real(down_cast(x)); + break; + } + case ASR::ttypeType::Complex: { + self().replace_Complex(down_cast(x)); + break; + } + case ASR::ttypeType::String: { + self().replace_String(down_cast(x)); + break; + } + case ASR::ttypeType::Logical: { + self().replace_Logical(down_cast(x)); + break; + } + case ASR::ttypeType::Set: { + self().replace_Set(down_cast(x)); + break; + } + case ASR::ttypeType::List: { + self().replace_List(down_cast(x)); + break; + } + case ASR::ttypeType::Tuple: { + self().replace_Tuple(down_cast(x)); + break; + } + case ASR::ttypeType::StructType: { + self().replace_StructType(down_cast(x)); + break; + } + case ASR::ttypeType::EnumType: { + self().replace_EnumType(down_cast(x)); + break; + } + case ASR::ttypeType::UnionType: { + self().replace_UnionType(down_cast(x)); + break; + } + case ASR::ttypeType::ClassType: { + self().replace_ClassType(down_cast(x)); + break; + } + case ASR::ttypeType::Dict: { + self().replace_Dict(down_cast(x)); + break; + } + case ASR::ttypeType::Pointer: { + self().replace_Pointer(down_cast(x)); + break; + } + case ASR::ttypeType::Allocatable: { + self().replace_Allocatable(down_cast(x)); + break; + } + case ASR::ttypeType::CPtr: { + self().replace_CPtr(down_cast(x)); + break; + } + case ASR::ttypeType::SymbolicExpression: { + self().replace_SymbolicExpression(down_cast(x)); + break; + } + case ASR::ttypeType::TypeParameter: { + self().replace_TypeParameter(down_cast(x)); + break; + } + case ASR::ttypeType::Array: { + self().replace_Array(down_cast(x)); + break; + } + case ASR::ttypeType::FunctionType: { + self().replace_FunctionType(down_cast(x)); + break; + } + default: { + LCOMPILERS_ASSERT_MSG(false, "Replacement in " + std::to_string(x->type) + " type is not supported yet."); + } + } + + } + +}; + + +} diff --git a/src/libasr/asr_expr_call_replacer_visitor.h b/src/libasr/asr_expr_call_replacer_visitor.h new file mode 100644 index 0000000000..7afe965b7b --- /dev/null +++ b/src/libasr/asr_expr_call_replacer_visitor.h @@ -0,0 +1,3878 @@ +#pragma once + +// Generated by grammar/asdl_cpp.py + +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace LCompilers::ASR { +/******************************************************************************/ +// Walk Visitor base class + +template +class CallReplacerOnExpressionsVisitor : public BaseVisitor +{ +private: + StructType& self() { return static_cast(*this); } +public: + bool call_replacer_on_value=true; + bool visit_expr_after_replacement=true; + ASR::expr_t** current_expr=nullptr; + SymbolTable* current_scope=nullptr; + + void call_replacer() {} + void transform_stmts(ASR::stmt_t **&m_body, size_t &n_body) { + for (size_t i = 0; i < n_body; i++) { + self().visit_stmt(*m_body[i]); + } + } + void visit_TranslationUnit(const TranslationUnit_t &x) { + SymbolTable* current_scope_copy = current_scope; + current_scope = x.m_symtab; + for (auto &a : x.m_symtab->get_scope()) { + this->visit_symbol(*a.second); + } + current_scope = current_scope_copy; + } + void visit_Program(const Program_t &x) { + Program_t& xx = const_cast(x); + SymbolTable* current_scope_copy = current_scope; + current_scope = x.m_symtab; + for (auto &a : x.m_symtab->get_scope()) { + this->visit_symbol(*a.second); + } + self().transform_stmts(xx.m_body, xx.n_body); + current_scope = current_scope_copy; + } + void visit_Module(const Module_t &x) { + SymbolTable* current_scope_copy = current_scope; + current_scope = x.m_symtab; + for (auto &a : x.m_symtab->get_scope()) { + this->visit_symbol(*a.second); + } + current_scope = current_scope_copy; + } + void visit_Function(const Function_t &x) { + Function_t& xx = const_cast(x); + SymbolTable* current_scope_copy = current_scope; + current_scope = x.m_symtab; + for (auto &a : x.m_symtab->get_scope()) { + this->visit_symbol(*a.second); + } + self().visit_ttype(*x.m_function_signature); + for (size_t i=0; i(&(x.m_args[i])); + self().call_replacer(); + current_expr = current_expr_copy_0; + if( x.m_args[i] && visit_expr_after_replacement ) + self().visit_expr(*x.m_args[i]); + } + self().transform_stmts(xx.m_body, xx.n_body); + if (x.m_return_var) { + ASR::expr_t** current_expr_copy_1 = current_expr; + current_expr = const_cast(&(x.m_return_var)); + self().call_replacer(); + current_expr = current_expr_copy_1; + if( x.m_return_var && visit_expr_after_replacement ) + self().visit_expr(*x.m_return_var); + } + current_scope = current_scope_copy; + } + void visit_GenericProcedure(const GenericProcedure_t &x) { + SymbolTable* current_scope_copy = current_scope; + current_scope = x.m_parent_symtab; + for (size_t i=0; iget_scope()) { + this->visit_symbol(*a.second); + } + for (size_t i=0; i(&(x.m_alignment)); + self().call_replacer(); + current_expr = current_expr_copy_2; + if( x.m_alignment && visit_expr_after_replacement ) + self().visit_expr(*x.m_alignment); + } + current_scope = current_scope_copy; + } + void visit_Enum(const Enum_t &x) { + SymbolTable* current_scope_copy = current_scope; + current_scope = x.m_symtab; + for (auto &a : x.m_symtab->get_scope()) { + this->visit_symbol(*a.second); + } + self().visit_ttype(*x.m_type); + current_scope = current_scope_copy; + } + void visit_Union(const Union_t &x) { + SymbolTable* current_scope_copy = current_scope; + current_scope = x.m_symtab; + for (auto &a : x.m_symtab->get_scope()) { + this->visit_symbol(*a.second); + } + for (size_t i=0; i(&(x.m_symbolic_value)); + self().call_replacer(); + current_expr = current_expr_copy_3; + } + if( x.m_symbolic_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_symbolic_value); + } + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_4 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_4; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + self().visit_ttype(*x.m_type); + current_scope = current_scope_copy; + } + void visit_Class(const Class_t &x) { + SymbolTable* current_scope_copy = current_scope; + current_scope = x.m_symtab; + for (auto &a : x.m_symtab->get_scope()) { + this->visit_symbol(*a.second); + } + current_scope = current_scope_copy; + } + void visit_ClassProcedure(const ClassProcedure_t &x) { + SymbolTable* current_scope_copy = current_scope; + current_scope = x.m_parent_symtab; + if ((bool&)x) { } // Suppress unused warning + current_scope = current_scope_copy; + } + void visit_AssociateBlock(const AssociateBlock_t &x) { + AssociateBlock_t& xx = const_cast(x); + SymbolTable* current_scope_copy = current_scope; + current_scope = x.m_symtab; + for (auto &a : x.m_symtab->get_scope()) { + this->visit_symbol(*a.second); + } + self().transform_stmts(xx.m_body, xx.n_body); + current_scope = current_scope_copy; + } + void visit_Block(const Block_t &x) { + Block_t& xx = const_cast(x); + SymbolTable* current_scope_copy = current_scope; + current_scope = x.m_symtab; + for (auto &a : x.m_symtab->get_scope()) { + this->visit_symbol(*a.second); + } + self().transform_stmts(xx.m_body, xx.n_body); + current_scope = current_scope_copy; + } + void visit_Requirement(const Requirement_t &x) { + SymbolTable* current_scope_copy = current_scope; + current_scope = x.m_symtab; + for (auto &a : x.m_symtab->get_scope()) { + this->visit_symbol(*a.second); + } + for (size_t i=0; iget_scope()) { + this->visit_symbol(*a.second); + } + for (size_t i=0; i(&(x.m_stat)); + self().call_replacer(); + current_expr = current_expr_copy_5; + if( x.m_stat && visit_expr_after_replacement ) + self().visit_expr(*x.m_stat); + } + if (x.m_errmsg) { + ASR::expr_t** current_expr_copy_6 = current_expr; + current_expr = const_cast(&(x.m_errmsg)); + self().call_replacer(); + current_expr = current_expr_copy_6; + if( x.m_errmsg && visit_expr_after_replacement ) + self().visit_expr(*x.m_errmsg); + } + if (x.m_source) { + ASR::expr_t** current_expr_copy_7 = current_expr; + current_expr = const_cast(&(x.m_source)); + self().call_replacer(); + current_expr = current_expr_copy_7; + if( x.m_source && visit_expr_after_replacement ) + self().visit_expr(*x.m_source); + } + } + void visit_ReAlloc(const ReAlloc_t &x) { + for (size_t i=0; i(&(x.m_target)); + self().call_replacer(); + current_expr = current_expr_copy_8; + if( x.m_target && visit_expr_after_replacement ) + self().visit_expr(*x.m_target); + ASR::expr_t** current_expr_copy_9 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_9; + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + if (x.m_overloaded) { + self().visit_stmt(*x.m_overloaded); + } + } + void visit_Associate(const Associate_t &x) { + ASR::expr_t** current_expr_copy_10 = current_expr; + current_expr = const_cast(&(x.m_target)); + self().call_replacer(); + current_expr = current_expr_copy_10; + if( x.m_target && visit_expr_after_replacement ) + self().visit_expr(*x.m_target); + ASR::expr_t** current_expr_copy_11 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_11; + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + void visit_Cycle(const Cycle_t &x) { + if ((bool&)x) { } // Suppress unused warning + } + void visit_ExplicitDeallocate(const ExplicitDeallocate_t &x) { + for (size_t i=0; i(&(x.m_vars[i])); + self().call_replacer(); + current_expr = current_expr_copy_12; + if( x.m_vars[i] && visit_expr_after_replacement ) + self().visit_expr(*x.m_vars[i]); + } + } + void visit_ImplicitDeallocate(const ImplicitDeallocate_t &x) { + for (size_t i=0; i(&(x.m_vars[i])); + self().call_replacer(); + current_expr = current_expr_copy_13; + if( x.m_vars[i] && visit_expr_after_replacement ) + self().visit_expr(*x.m_vars[i]); + } + } + void visit_DoConcurrentLoop(const DoConcurrentLoop_t &x) { + DoConcurrentLoop_t& xx = const_cast(x); + for (size_t i=0; i(&(x.m_shared[i])); + self().call_replacer(); + current_expr = current_expr_copy_14; + if( x.m_shared[i] && visit_expr_after_replacement ) + self().visit_expr(*x.m_shared[i]); + } + for (size_t i=0; i(&(x.m_local[i])); + self().call_replacer(); + current_expr = current_expr_copy_15; + if( x.m_local[i] && visit_expr_after_replacement ) + self().visit_expr(*x.m_local[i]); + } + for (size_t i=0; i(x); + self().visit_do_loop_head(x.m_head); + self().transform_stmts(xx.m_body, xx.n_body); + self().transform_stmts(xx.m_orelse, xx.n_orelse); + } + void visit_ErrorStop(const ErrorStop_t &x) { + if (x.m_code) { + ASR::expr_t** current_expr_copy_16 = current_expr; + current_expr = const_cast(&(x.m_code)); + self().call_replacer(); + current_expr = current_expr_copy_16; + if( x.m_code && visit_expr_after_replacement ) + self().visit_expr(*x.m_code); + } + } + void visit_Exit(const Exit_t &x) { + if ((bool&)x) { } // Suppress unused warning + } + void visit_ForAllSingle(const ForAllSingle_t &x) { + self().visit_do_loop_head(x.m_head); + self().visit_stmt(*x.m_assign_stmt); + } + void visit_ForEach(const ForEach_t &x) { + ForEach_t& xx = const_cast(x); + ASR::expr_t** current_expr_copy_17 = current_expr; + current_expr = const_cast(&(x.m_var)); + self().call_replacer(); + current_expr = current_expr_copy_17; + if( x.m_var && visit_expr_after_replacement ) + self().visit_expr(*x.m_var); + ASR::expr_t** current_expr_copy_18 = current_expr; + current_expr = const_cast(&(x.m_container)); + self().call_replacer(); + current_expr = current_expr_copy_18; + if( x.m_container && visit_expr_after_replacement ) + self().visit_expr(*x.m_container); + self().transform_stmts(xx.m_body, xx.n_body); + } + void visit_GoTo(const GoTo_t &x) { + if ((bool&)x) { } // Suppress unused warning + } + void visit_GoToTarget(const GoToTarget_t &x) { + if ((bool&)x) { } // Suppress unused warning + } + void visit_If(const If_t &x) { + If_t& xx = const_cast(x); + ASR::expr_t** current_expr_copy_19 = current_expr; + current_expr = const_cast(&(x.m_test)); + self().call_replacer(); + current_expr = current_expr_copy_19; + if( x.m_test && visit_expr_after_replacement ) + self().visit_expr(*x.m_test); + self().transform_stmts(xx.m_body, xx.n_body); + self().transform_stmts(xx.m_orelse, xx.n_orelse); + } + void visit_IfArithmetic(const IfArithmetic_t &x) { + ASR::expr_t** current_expr_copy_20 = current_expr; + current_expr = const_cast(&(x.m_test)); + self().call_replacer(); + current_expr = current_expr_copy_20; + if( x.m_test && visit_expr_after_replacement ) + self().visit_expr(*x.m_test); + } + void visit_Print(const Print_t &x) { + ASR::expr_t** current_expr_copy_21 = current_expr; + current_expr = const_cast(&(x.m_text)); + self().call_replacer(); + current_expr = current_expr_copy_21; + if( x.m_text && visit_expr_after_replacement ) + self().visit_expr(*x.m_text); + } + void visit_FileOpen(const FileOpen_t &x) { + if (x.m_newunit) { + ASR::expr_t** current_expr_copy_22 = current_expr; + current_expr = const_cast(&(x.m_newunit)); + self().call_replacer(); + current_expr = current_expr_copy_22; + if( x.m_newunit && visit_expr_after_replacement ) + self().visit_expr(*x.m_newunit); + } + if (x.m_filename) { + ASR::expr_t** current_expr_copy_23 = current_expr; + current_expr = const_cast(&(x.m_filename)); + self().call_replacer(); + current_expr = current_expr_copy_23; + if( x.m_filename && visit_expr_after_replacement ) + self().visit_expr(*x.m_filename); + } + if (x.m_status) { + ASR::expr_t** current_expr_copy_24 = current_expr; + current_expr = const_cast(&(x.m_status)); + self().call_replacer(); + current_expr = current_expr_copy_24; + if( x.m_status && visit_expr_after_replacement ) + self().visit_expr(*x.m_status); + } + if (x.m_form) { + ASR::expr_t** current_expr_copy_25 = current_expr; + current_expr = const_cast(&(x.m_form)); + self().call_replacer(); + current_expr = current_expr_copy_25; + if( x.m_form && visit_expr_after_replacement ) + self().visit_expr(*x.m_form); + } + } + void visit_FileClose(const FileClose_t &x) { + if (x.m_unit) { + ASR::expr_t** current_expr_copy_26 = current_expr; + current_expr = const_cast(&(x.m_unit)); + self().call_replacer(); + current_expr = current_expr_copy_26; + if( x.m_unit && visit_expr_after_replacement ) + self().visit_expr(*x.m_unit); + } + if (x.m_iostat) { + ASR::expr_t** current_expr_copy_27 = current_expr; + current_expr = const_cast(&(x.m_iostat)); + self().call_replacer(); + current_expr = current_expr_copy_27; + if( x.m_iostat && visit_expr_after_replacement ) + self().visit_expr(*x.m_iostat); + } + if (x.m_iomsg) { + ASR::expr_t** current_expr_copy_28 = current_expr; + current_expr = const_cast(&(x.m_iomsg)); + self().call_replacer(); + current_expr = current_expr_copy_28; + if( x.m_iomsg && visit_expr_after_replacement ) + self().visit_expr(*x.m_iomsg); + } + if (x.m_err) { + ASR::expr_t** current_expr_copy_29 = current_expr; + current_expr = const_cast(&(x.m_err)); + self().call_replacer(); + current_expr = current_expr_copy_29; + if( x.m_err && visit_expr_after_replacement ) + self().visit_expr(*x.m_err); + } + if (x.m_status) { + ASR::expr_t** current_expr_copy_30 = current_expr; + current_expr = const_cast(&(x.m_status)); + self().call_replacer(); + current_expr = current_expr_copy_30; + if( x.m_status && visit_expr_after_replacement ) + self().visit_expr(*x.m_status); + } + } + void visit_FileRead(const FileRead_t &x) { + if (x.m_unit) { + ASR::expr_t** current_expr_copy_31 = current_expr; + current_expr = const_cast(&(x.m_unit)); + self().call_replacer(); + current_expr = current_expr_copy_31; + if( x.m_unit && visit_expr_after_replacement ) + self().visit_expr(*x.m_unit); + } + if (x.m_fmt) { + ASR::expr_t** current_expr_copy_32 = current_expr; + current_expr = const_cast(&(x.m_fmt)); + self().call_replacer(); + current_expr = current_expr_copy_32; + if( x.m_fmt && visit_expr_after_replacement ) + self().visit_expr(*x.m_fmt); + } + if (x.m_iomsg) { + ASR::expr_t** current_expr_copy_33 = current_expr; + current_expr = const_cast(&(x.m_iomsg)); + self().call_replacer(); + current_expr = current_expr_copy_33; + if( x.m_iomsg && visit_expr_after_replacement ) + self().visit_expr(*x.m_iomsg); + } + if (x.m_iostat) { + ASR::expr_t** current_expr_copy_34 = current_expr; + current_expr = const_cast(&(x.m_iostat)); + self().call_replacer(); + current_expr = current_expr_copy_34; + if( x.m_iostat && visit_expr_after_replacement ) + self().visit_expr(*x.m_iostat); + } + if (x.m_size) { + ASR::expr_t** current_expr_copy_35 = current_expr; + current_expr = const_cast(&(x.m_size)); + self().call_replacer(); + current_expr = current_expr_copy_35; + if( x.m_size && visit_expr_after_replacement ) + self().visit_expr(*x.m_size); + } + if (x.m_id) { + ASR::expr_t** current_expr_copy_36 = current_expr; + current_expr = const_cast(&(x.m_id)); + self().call_replacer(); + current_expr = current_expr_copy_36; + if( x.m_id && visit_expr_after_replacement ) + self().visit_expr(*x.m_id); + } + for (size_t i=0; i(&(x.m_values[i])); + self().call_replacer(); + current_expr = current_expr_copy_37; + if( x.m_values[i] && visit_expr_after_replacement ) + self().visit_expr(*x.m_values[i]); + } + if (x.m_overloaded) { + self().visit_stmt(*x.m_overloaded); + } + } + void visit_FileBackspace(const FileBackspace_t &x) { + if (x.m_unit) { + ASR::expr_t** current_expr_copy_38 = current_expr; + current_expr = const_cast(&(x.m_unit)); + self().call_replacer(); + current_expr = current_expr_copy_38; + if( x.m_unit && visit_expr_after_replacement ) + self().visit_expr(*x.m_unit); + } + if (x.m_iostat) { + ASR::expr_t** current_expr_copy_39 = current_expr; + current_expr = const_cast(&(x.m_iostat)); + self().call_replacer(); + current_expr = current_expr_copy_39; + if( x.m_iostat && visit_expr_after_replacement ) + self().visit_expr(*x.m_iostat); + } + if (x.m_err) { + ASR::expr_t** current_expr_copy_40 = current_expr; + current_expr = const_cast(&(x.m_err)); + self().call_replacer(); + current_expr = current_expr_copy_40; + if( x.m_err && visit_expr_after_replacement ) + self().visit_expr(*x.m_err); + } + } + void visit_FileRewind(const FileRewind_t &x) { + if (x.m_unit) { + ASR::expr_t** current_expr_copy_41 = current_expr; + current_expr = const_cast(&(x.m_unit)); + self().call_replacer(); + current_expr = current_expr_copy_41; + if( x.m_unit && visit_expr_after_replacement ) + self().visit_expr(*x.m_unit); + } + if (x.m_iostat) { + ASR::expr_t** current_expr_copy_42 = current_expr; + current_expr = const_cast(&(x.m_iostat)); + self().call_replacer(); + current_expr = current_expr_copy_42; + if( x.m_iostat && visit_expr_after_replacement ) + self().visit_expr(*x.m_iostat); + } + if (x.m_err) { + ASR::expr_t** current_expr_copy_43 = current_expr; + current_expr = const_cast(&(x.m_err)); + self().call_replacer(); + current_expr = current_expr_copy_43; + if( x.m_err && visit_expr_after_replacement ) + self().visit_expr(*x.m_err); + } + } + void visit_FileInquire(const FileInquire_t &x) { + if (x.m_unit) { + ASR::expr_t** current_expr_copy_44 = current_expr; + current_expr = const_cast(&(x.m_unit)); + self().call_replacer(); + current_expr = current_expr_copy_44; + if( x.m_unit && visit_expr_after_replacement ) + self().visit_expr(*x.m_unit); + } + if (x.m_file) { + ASR::expr_t** current_expr_copy_45 = current_expr; + current_expr = const_cast(&(x.m_file)); + self().call_replacer(); + current_expr = current_expr_copy_45; + if( x.m_file && visit_expr_after_replacement ) + self().visit_expr(*x.m_file); + } + if (x.m_iostat) { + ASR::expr_t** current_expr_copy_46 = current_expr; + current_expr = const_cast(&(x.m_iostat)); + self().call_replacer(); + current_expr = current_expr_copy_46; + if( x.m_iostat && visit_expr_after_replacement ) + self().visit_expr(*x.m_iostat); + } + if (x.m_err) { + ASR::expr_t** current_expr_copy_47 = current_expr; + current_expr = const_cast(&(x.m_err)); + self().call_replacer(); + current_expr = current_expr_copy_47; + if( x.m_err && visit_expr_after_replacement ) + self().visit_expr(*x.m_err); + } + if (x.m_exist) { + ASR::expr_t** current_expr_copy_48 = current_expr; + current_expr = const_cast(&(x.m_exist)); + self().call_replacer(); + current_expr = current_expr_copy_48; + if( x.m_exist && visit_expr_after_replacement ) + self().visit_expr(*x.m_exist); + } + if (x.m_opened) { + ASR::expr_t** current_expr_copy_49 = current_expr; + current_expr = const_cast(&(x.m_opened)); + self().call_replacer(); + current_expr = current_expr_copy_49; + if( x.m_opened && visit_expr_after_replacement ) + self().visit_expr(*x.m_opened); + } + if (x.m_number) { + ASR::expr_t** current_expr_copy_50 = current_expr; + current_expr = const_cast(&(x.m_number)); + self().call_replacer(); + current_expr = current_expr_copy_50; + if( x.m_number && visit_expr_after_replacement ) + self().visit_expr(*x.m_number); + } + if (x.m_named) { + ASR::expr_t** current_expr_copy_51 = current_expr; + current_expr = const_cast(&(x.m_named)); + self().call_replacer(); + current_expr = current_expr_copy_51; + if( x.m_named && visit_expr_after_replacement ) + self().visit_expr(*x.m_named); + } + if (x.m_name) { + ASR::expr_t** current_expr_copy_52 = current_expr; + current_expr = const_cast(&(x.m_name)); + self().call_replacer(); + current_expr = current_expr_copy_52; + if( x.m_name && visit_expr_after_replacement ) + self().visit_expr(*x.m_name); + } + if (x.m_access) { + ASR::expr_t** current_expr_copy_53 = current_expr; + current_expr = const_cast(&(x.m_access)); + self().call_replacer(); + current_expr = current_expr_copy_53; + if( x.m_access && visit_expr_after_replacement ) + self().visit_expr(*x.m_access); + } + if (x.m_sequential) { + ASR::expr_t** current_expr_copy_54 = current_expr; + current_expr = const_cast(&(x.m_sequential)); + self().call_replacer(); + current_expr = current_expr_copy_54; + if( x.m_sequential && visit_expr_after_replacement ) + self().visit_expr(*x.m_sequential); + } + if (x.m_direct) { + ASR::expr_t** current_expr_copy_55 = current_expr; + current_expr = const_cast(&(x.m_direct)); + self().call_replacer(); + current_expr = current_expr_copy_55; + if( x.m_direct && visit_expr_after_replacement ) + self().visit_expr(*x.m_direct); + } + if (x.m_form) { + ASR::expr_t** current_expr_copy_56 = current_expr; + current_expr = const_cast(&(x.m_form)); + self().call_replacer(); + current_expr = current_expr_copy_56; + if( x.m_form && visit_expr_after_replacement ) + self().visit_expr(*x.m_form); + } + if (x.m_formatted) { + ASR::expr_t** current_expr_copy_57 = current_expr; + current_expr = const_cast(&(x.m_formatted)); + self().call_replacer(); + current_expr = current_expr_copy_57; + if( x.m_formatted && visit_expr_after_replacement ) + self().visit_expr(*x.m_formatted); + } + if (x.m_unformatted) { + ASR::expr_t** current_expr_copy_58 = current_expr; + current_expr = const_cast(&(x.m_unformatted)); + self().call_replacer(); + current_expr = current_expr_copy_58; + if( x.m_unformatted && visit_expr_after_replacement ) + self().visit_expr(*x.m_unformatted); + } + if (x.m_recl) { + ASR::expr_t** current_expr_copy_59 = current_expr; + current_expr = const_cast(&(x.m_recl)); + self().call_replacer(); + current_expr = current_expr_copy_59; + if( x.m_recl && visit_expr_after_replacement ) + self().visit_expr(*x.m_recl); + } + if (x.m_nextrec) { + ASR::expr_t** current_expr_copy_60 = current_expr; + current_expr = const_cast(&(x.m_nextrec)); + self().call_replacer(); + current_expr = current_expr_copy_60; + if( x.m_nextrec && visit_expr_after_replacement ) + self().visit_expr(*x.m_nextrec); + } + if (x.m_blank) { + ASR::expr_t** current_expr_copy_61 = current_expr; + current_expr = const_cast(&(x.m_blank)); + self().call_replacer(); + current_expr = current_expr_copy_61; + if( x.m_blank && visit_expr_after_replacement ) + self().visit_expr(*x.m_blank); + } + if (x.m_position) { + ASR::expr_t** current_expr_copy_62 = current_expr; + current_expr = const_cast(&(x.m_position)); + self().call_replacer(); + current_expr = current_expr_copy_62; + if( x.m_position && visit_expr_after_replacement ) + self().visit_expr(*x.m_position); + } + if (x.m_action) { + ASR::expr_t** current_expr_copy_63 = current_expr; + current_expr = const_cast(&(x.m_action)); + self().call_replacer(); + current_expr = current_expr_copy_63; + if( x.m_action && visit_expr_after_replacement ) + self().visit_expr(*x.m_action); + } + if (x.m_read) { + ASR::expr_t** current_expr_copy_64 = current_expr; + current_expr = const_cast(&(x.m_read)); + self().call_replacer(); + current_expr = current_expr_copy_64; + if( x.m_read && visit_expr_after_replacement ) + self().visit_expr(*x.m_read); + } + if (x.m_write) { + ASR::expr_t** current_expr_copy_65 = current_expr; + current_expr = const_cast(&(x.m_write)); + self().call_replacer(); + current_expr = current_expr_copy_65; + if( x.m_write && visit_expr_after_replacement ) + self().visit_expr(*x.m_write); + } + if (x.m_readwrite) { + ASR::expr_t** current_expr_copy_66 = current_expr; + current_expr = const_cast(&(x.m_readwrite)); + self().call_replacer(); + current_expr = current_expr_copy_66; + if( x.m_readwrite && visit_expr_after_replacement ) + self().visit_expr(*x.m_readwrite); + } + if (x.m_delim) { + ASR::expr_t** current_expr_copy_67 = current_expr; + current_expr = const_cast(&(x.m_delim)); + self().call_replacer(); + current_expr = current_expr_copy_67; + if( x.m_delim && visit_expr_after_replacement ) + self().visit_expr(*x.m_delim); + } + if (x.m_pad) { + ASR::expr_t** current_expr_copy_68 = current_expr; + current_expr = const_cast(&(x.m_pad)); + self().call_replacer(); + current_expr = current_expr_copy_68; + if( x.m_pad && visit_expr_after_replacement ) + self().visit_expr(*x.m_pad); + } + if (x.m_flen) { + ASR::expr_t** current_expr_copy_69 = current_expr; + current_expr = const_cast(&(x.m_flen)); + self().call_replacer(); + current_expr = current_expr_copy_69; + if( x.m_flen && visit_expr_after_replacement ) + self().visit_expr(*x.m_flen); + } + if (x.m_blocksize) { + ASR::expr_t** current_expr_copy_70 = current_expr; + current_expr = const_cast(&(x.m_blocksize)); + self().call_replacer(); + current_expr = current_expr_copy_70; + if( x.m_blocksize && visit_expr_after_replacement ) + self().visit_expr(*x.m_blocksize); + } + if (x.m_convert) { + ASR::expr_t** current_expr_copy_71 = current_expr; + current_expr = const_cast(&(x.m_convert)); + self().call_replacer(); + current_expr = current_expr_copy_71; + if( x.m_convert && visit_expr_after_replacement ) + self().visit_expr(*x.m_convert); + } + if (x.m_carriagecontrol) { + ASR::expr_t** current_expr_copy_72 = current_expr; + current_expr = const_cast(&(x.m_carriagecontrol)); + self().call_replacer(); + current_expr = current_expr_copy_72; + if( x.m_carriagecontrol && visit_expr_after_replacement ) + self().visit_expr(*x.m_carriagecontrol); + } + if (x.m_size) { + ASR::expr_t** current_expr_copy_73 = current_expr; + current_expr = const_cast(&(x.m_size)); + self().call_replacer(); + current_expr = current_expr_copy_73; + if( x.m_size && visit_expr_after_replacement ) + self().visit_expr(*x.m_size); + } + if (x.m_iolength) { + ASR::expr_t** current_expr_copy_74 = current_expr; + current_expr = const_cast(&(x.m_iolength)); + self().call_replacer(); + current_expr = current_expr_copy_74; + if( x.m_iolength && visit_expr_after_replacement ) + self().visit_expr(*x.m_iolength); + } + } + void visit_FileWrite(const FileWrite_t &x) { + if (x.m_unit) { + ASR::expr_t** current_expr_copy_75 = current_expr; + current_expr = const_cast(&(x.m_unit)); + self().call_replacer(); + current_expr = current_expr_copy_75; + if( x.m_unit && visit_expr_after_replacement ) + self().visit_expr(*x.m_unit); + } + if (x.m_iomsg) { + ASR::expr_t** current_expr_copy_76 = current_expr; + current_expr = const_cast(&(x.m_iomsg)); + self().call_replacer(); + current_expr = current_expr_copy_76; + if( x.m_iomsg && visit_expr_after_replacement ) + self().visit_expr(*x.m_iomsg); + } + if (x.m_iostat) { + ASR::expr_t** current_expr_copy_77 = current_expr; + current_expr = const_cast(&(x.m_iostat)); + self().call_replacer(); + current_expr = current_expr_copy_77; + if( x.m_iostat && visit_expr_after_replacement ) + self().visit_expr(*x.m_iostat); + } + if (x.m_id) { + ASR::expr_t** current_expr_copy_78 = current_expr; + current_expr = const_cast(&(x.m_id)); + self().call_replacer(); + current_expr = current_expr_copy_78; + if( x.m_id && visit_expr_after_replacement ) + self().visit_expr(*x.m_id); + } + for (size_t i=0; i(&(x.m_values[i])); + self().call_replacer(); + current_expr = current_expr_copy_79; + if( x.m_values[i] && visit_expr_after_replacement ) + self().visit_expr(*x.m_values[i]); + } + if (x.m_separator) { + ASR::expr_t** current_expr_copy_80 = current_expr; + current_expr = const_cast(&(x.m_separator)); + self().call_replacer(); + current_expr = current_expr_copy_80; + if( x.m_separator && visit_expr_after_replacement ) + self().visit_expr(*x.m_separator); + } + if (x.m_end) { + ASR::expr_t** current_expr_copy_81 = current_expr; + current_expr = const_cast(&(x.m_end)); + self().call_replacer(); + current_expr = current_expr_copy_81; + if( x.m_end && visit_expr_after_replacement ) + self().visit_expr(*x.m_end); + } + if (x.m_overloaded) { + self().visit_stmt(*x.m_overloaded); + } + } + void visit_Return(const Return_t &x) { + if ((bool&)x) { } // Suppress unused warning + } + void visit_Select(const Select_t &x) { + Select_t& xx = const_cast(x); + ASR::expr_t** current_expr_copy_82 = current_expr; + current_expr = const_cast(&(x.m_test)); + self().call_replacer(); + current_expr = current_expr_copy_82; + if( x.m_test && visit_expr_after_replacement ) + self().visit_expr(*x.m_test); + for (size_t i=0; i(&(x.m_code)); + self().call_replacer(); + current_expr = current_expr_copy_83; + if( x.m_code && visit_expr_after_replacement ) + self().visit_expr(*x.m_code); + } + } + void visit_Assert(const Assert_t &x) { + ASR::expr_t** current_expr_copy_84 = current_expr; + current_expr = const_cast(&(x.m_test)); + self().call_replacer(); + current_expr = current_expr_copy_84; + if( x.m_test && visit_expr_after_replacement ) + self().visit_expr(*x.m_test); + if (x.m_msg) { + ASR::expr_t** current_expr_copy_85 = current_expr; + current_expr = const_cast(&(x.m_msg)); + self().call_replacer(); + current_expr = current_expr_copy_85; + if( x.m_msg && visit_expr_after_replacement ) + self().visit_expr(*x.m_msg); + } + } + void visit_SubroutineCall(const SubroutineCall_t &x) { + for (size_t i=0; i(&(x.m_dt)); + self().call_replacer(); + current_expr = current_expr_copy_86; + if( x.m_dt && visit_expr_after_replacement ) + self().visit_expr(*x.m_dt); + } + } + void visit_IntrinsicImpureSubroutine(const IntrinsicImpureSubroutine_t &x) { + for (size_t i=0; i(&(x.m_args[i])); + self().call_replacer(); + current_expr = current_expr_copy_87; + if( x.m_args[i] && visit_expr_after_replacement ) + self().visit_expr(*x.m_args[i]); + } + } + void visit_Where(const Where_t &x) { + Where_t& xx = const_cast(x); + ASR::expr_t** current_expr_copy_88 = current_expr; + current_expr = const_cast(&(x.m_test)); + self().call_replacer(); + current_expr = current_expr_copy_88; + if( x.m_test && visit_expr_after_replacement ) + self().visit_expr(*x.m_test); + self().transform_stmts(xx.m_body, xx.n_body); + self().transform_stmts(xx.m_orelse, xx.n_orelse); + } + void visit_WhileLoop(const WhileLoop_t &x) { + WhileLoop_t& xx = const_cast(x); + ASR::expr_t** current_expr_copy_89 = current_expr; + current_expr = const_cast(&(x.m_test)); + self().call_replacer(); + current_expr = current_expr_copy_89; + if( x.m_test && visit_expr_after_replacement ) + self().visit_expr(*x.m_test); + self().transform_stmts(xx.m_body, xx.n_body); + self().transform_stmts(xx.m_orelse, xx.n_orelse); + } + void visit_Nullify(const Nullify_t &x) { + for (size_t i=0; i(&(x.m_vars[i])); + self().call_replacer(); + current_expr = current_expr_copy_90; + if( x.m_vars[i] && visit_expr_after_replacement ) + self().visit_expr(*x.m_vars[i]); + } + } + void visit_Flush(const Flush_t &x) { + ASR::expr_t** current_expr_copy_91 = current_expr; + current_expr = const_cast(&(x.m_unit)); + self().call_replacer(); + current_expr = current_expr_copy_91; + if( x.m_unit && visit_expr_after_replacement ) + self().visit_expr(*x.m_unit); + if (x.m_err) { + ASR::expr_t** current_expr_copy_92 = current_expr; + current_expr = const_cast(&(x.m_err)); + self().call_replacer(); + current_expr = current_expr_copy_92; + if( x.m_err && visit_expr_after_replacement ) + self().visit_expr(*x.m_err); + } + if (x.m_iomsg) { + ASR::expr_t** current_expr_copy_93 = current_expr; + current_expr = const_cast(&(x.m_iomsg)); + self().call_replacer(); + current_expr = current_expr_copy_93; + if( x.m_iomsg && visit_expr_after_replacement ) + self().visit_expr(*x.m_iomsg); + } + if (x.m_iostat) { + ASR::expr_t** current_expr_copy_94 = current_expr; + current_expr = const_cast(&(x.m_iostat)); + self().call_replacer(); + current_expr = current_expr_copy_94; + if( x.m_iostat && visit_expr_after_replacement ) + self().visit_expr(*x.m_iostat); + } + } + void visit_ListAppend(const ListAppend_t &x) { + ASR::expr_t** current_expr_copy_95 = current_expr; + current_expr = const_cast(&(x.m_a)); + self().call_replacer(); + current_expr = current_expr_copy_95; + if( x.m_a && visit_expr_after_replacement ) + self().visit_expr(*x.m_a); + ASR::expr_t** current_expr_copy_96 = current_expr; + current_expr = const_cast(&(x.m_ele)); + self().call_replacer(); + current_expr = current_expr_copy_96; + if( x.m_ele && visit_expr_after_replacement ) + self().visit_expr(*x.m_ele); + } + void visit_AssociateBlockCall(const AssociateBlockCall_t &x) { + if ((bool&)x) { } // Suppress unused warning + } + void visit_SelectType(const SelectType_t &x) { + SelectType_t& xx = const_cast(x); + ASR::expr_t** current_expr_copy_97 = current_expr; + current_expr = const_cast(&(x.m_selector)); + self().call_replacer(); + current_expr = current_expr_copy_97; + if( x.m_selector && visit_expr_after_replacement ) + self().visit_expr(*x.m_selector); + for (size_t i=0; i(&(x.m_cptr)); + self().call_replacer(); + current_expr = current_expr_copy_98; + if( x.m_cptr && visit_expr_after_replacement ) + self().visit_expr(*x.m_cptr); + ASR::expr_t** current_expr_copy_99 = current_expr; + current_expr = const_cast(&(x.m_ptr)); + self().call_replacer(); + current_expr = current_expr_copy_99; + if( x.m_ptr && visit_expr_after_replacement ) + self().visit_expr(*x.m_ptr); + if (x.m_shape) { + ASR::expr_t** current_expr_copy_100 = current_expr; + current_expr = const_cast(&(x.m_shape)); + self().call_replacer(); + current_expr = current_expr_copy_100; + if( x.m_shape && visit_expr_after_replacement ) + self().visit_expr(*x.m_shape); + } + if (x.m_lower_bounds) { + ASR::expr_t** current_expr_copy_101 = current_expr; + current_expr = const_cast(&(x.m_lower_bounds)); + self().call_replacer(); + current_expr = current_expr_copy_101; + if( x.m_lower_bounds && visit_expr_after_replacement ) + self().visit_expr(*x.m_lower_bounds); + } + } + void visit_BlockCall(const BlockCall_t &x) { + if ((bool&)x) { } // Suppress unused warning + } + void visit_SetInsert(const SetInsert_t &x) { + ASR::expr_t** current_expr_copy_102 = current_expr; + current_expr = const_cast(&(x.m_a)); + self().call_replacer(); + current_expr = current_expr_copy_102; + if( x.m_a && visit_expr_after_replacement ) + self().visit_expr(*x.m_a); + ASR::expr_t** current_expr_copy_103 = current_expr; + current_expr = const_cast(&(x.m_ele)); + self().call_replacer(); + current_expr = current_expr_copy_103; + if( x.m_ele && visit_expr_after_replacement ) + self().visit_expr(*x.m_ele); + } + void visit_SetRemove(const SetRemove_t &x) { + ASR::expr_t** current_expr_copy_104 = current_expr; + current_expr = const_cast(&(x.m_a)); + self().call_replacer(); + current_expr = current_expr_copy_104; + if( x.m_a && visit_expr_after_replacement ) + self().visit_expr(*x.m_a); + ASR::expr_t** current_expr_copy_105 = current_expr; + current_expr = const_cast(&(x.m_ele)); + self().call_replacer(); + current_expr = current_expr_copy_105; + if( x.m_ele && visit_expr_after_replacement ) + self().visit_expr(*x.m_ele); + } + void visit_SetDiscard(const SetDiscard_t &x) { + ASR::expr_t** current_expr_copy_106 = current_expr; + current_expr = const_cast(&(x.m_a)); + self().call_replacer(); + current_expr = current_expr_copy_106; + if( x.m_a && visit_expr_after_replacement ) + self().visit_expr(*x.m_a); + ASR::expr_t** current_expr_copy_107 = current_expr; + current_expr = const_cast(&(x.m_ele)); + self().call_replacer(); + current_expr = current_expr_copy_107; + if( x.m_ele && visit_expr_after_replacement ) + self().visit_expr(*x.m_ele); + } + void visit_ListInsert(const ListInsert_t &x) { + ASR::expr_t** current_expr_copy_108 = current_expr; + current_expr = const_cast(&(x.m_a)); + self().call_replacer(); + current_expr = current_expr_copy_108; + if( x.m_a && visit_expr_after_replacement ) + self().visit_expr(*x.m_a); + ASR::expr_t** current_expr_copy_109 = current_expr; + current_expr = const_cast(&(x.m_pos)); + self().call_replacer(); + current_expr = current_expr_copy_109; + if( x.m_pos && visit_expr_after_replacement ) + self().visit_expr(*x.m_pos); + ASR::expr_t** current_expr_copy_110 = current_expr; + current_expr = const_cast(&(x.m_ele)); + self().call_replacer(); + current_expr = current_expr_copy_110; + if( x.m_ele && visit_expr_after_replacement ) + self().visit_expr(*x.m_ele); + } + void visit_ListRemove(const ListRemove_t &x) { + ASR::expr_t** current_expr_copy_111 = current_expr; + current_expr = const_cast(&(x.m_a)); + self().call_replacer(); + current_expr = current_expr_copy_111; + if( x.m_a && visit_expr_after_replacement ) + self().visit_expr(*x.m_a); + ASR::expr_t** current_expr_copy_112 = current_expr; + current_expr = const_cast(&(x.m_ele)); + self().call_replacer(); + current_expr = current_expr_copy_112; + if( x.m_ele && visit_expr_after_replacement ) + self().visit_expr(*x.m_ele); + } + void visit_ListClear(const ListClear_t &x) { + ASR::expr_t** current_expr_copy_113 = current_expr; + current_expr = const_cast(&(x.m_a)); + self().call_replacer(); + current_expr = current_expr_copy_113; + if( x.m_a && visit_expr_after_replacement ) + self().visit_expr(*x.m_a); + } + void visit_DictInsert(const DictInsert_t &x) { + ASR::expr_t** current_expr_copy_114 = current_expr; + current_expr = const_cast(&(x.m_a)); + self().call_replacer(); + current_expr = current_expr_copy_114; + if( x.m_a && visit_expr_after_replacement ) + self().visit_expr(*x.m_a); + ASR::expr_t** current_expr_copy_115 = current_expr; + current_expr = const_cast(&(x.m_key)); + self().call_replacer(); + current_expr = current_expr_copy_115; + if( x.m_key && visit_expr_after_replacement ) + self().visit_expr(*x.m_key); + ASR::expr_t** current_expr_copy_116 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_116; + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + void visit_DictClear(const DictClear_t &x) { + ASR::expr_t** current_expr_copy_117 = current_expr; + current_expr = const_cast(&(x.m_a)); + self().call_replacer(); + current_expr = current_expr_copy_117; + if( x.m_a && visit_expr_after_replacement ) + self().visit_expr(*x.m_a); + } + void visit_SetClear(const SetClear_t &x) { + ASR::expr_t** current_expr_copy_118 = current_expr; + current_expr = const_cast(&(x.m_a)); + self().call_replacer(); + current_expr = current_expr_copy_118; + if( x.m_a && visit_expr_after_replacement ) + self().visit_expr(*x.m_a); + } + void visit_Expr(const Expr_t &x) { + ASR::expr_t** current_expr_copy_119 = current_expr; + current_expr = const_cast(&(x.m_expression)); + self().call_replacer(); + current_expr = current_expr_copy_119; + if( x.m_expression && visit_expr_after_replacement ) + self().visit_expr(*x.m_expression); + } + void visit_IfExp(const IfExp_t &x) { + ASR::expr_t** current_expr_copy_120 = current_expr; + current_expr = const_cast(&(x.m_test)); + self().call_replacer(); + current_expr = current_expr_copy_120; + if( x.m_test && visit_expr_after_replacement ) + self().visit_expr(*x.m_test); + ASR::expr_t** current_expr_copy_121 = current_expr; + current_expr = const_cast(&(x.m_body)); + self().call_replacer(); + current_expr = current_expr_copy_121; + if( x.m_body && visit_expr_after_replacement ) + self().visit_expr(*x.m_body); + ASR::expr_t** current_expr_copy_122 = current_expr; + current_expr = const_cast(&(x.m_orelse)); + self().call_replacer(); + current_expr = current_expr_copy_122; + if( x.m_orelse && visit_expr_after_replacement ) + self().visit_expr(*x.m_orelse); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_123 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_123; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_ComplexConstructor(const ComplexConstructor_t &x) { + ASR::expr_t** current_expr_copy_124 = current_expr; + current_expr = const_cast(&(x.m_re)); + self().call_replacer(); + current_expr = current_expr_copy_124; + if( x.m_re && visit_expr_after_replacement ) + self().visit_expr(*x.m_re); + ASR::expr_t** current_expr_copy_125 = current_expr; + current_expr = const_cast(&(x.m_im)); + self().call_replacer(); + current_expr = current_expr_copy_125; + if( x.m_im && visit_expr_after_replacement ) + self().visit_expr(*x.m_im); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_126 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_126; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_NamedExpr(const NamedExpr_t &x) { + ASR::expr_t** current_expr_copy_127 = current_expr; + current_expr = const_cast(&(x.m_target)); + self().call_replacer(); + current_expr = current_expr_copy_127; + if( x.m_target && visit_expr_after_replacement ) + self().visit_expr(*x.m_target); + ASR::expr_t** current_expr_copy_128 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_128; + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + self().visit_ttype(*x.m_type); + } + void visit_FunctionCall(const FunctionCall_t &x) { + for (size_t i=0; i(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_129; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + if (x.m_dt) { + ASR::expr_t** current_expr_copy_130 = current_expr; + current_expr = const_cast(&(x.m_dt)); + self().call_replacer(); + current_expr = current_expr_copy_130; + if( x.m_dt && visit_expr_after_replacement ) + self().visit_expr(*x.m_dt); + } + } + void visit_IntrinsicElementalFunction(const IntrinsicElementalFunction_t &x) { + for (size_t i=0; i(&(x.m_args[i])); + self().call_replacer(); + current_expr = current_expr_copy_131; + if( x.m_args[i] && visit_expr_after_replacement ) + self().visit_expr(*x.m_args[i]); + } + if (x.m_type) { + self().visit_ttype(*x.m_type); + } + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_132 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_132; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_IntrinsicArrayFunction(const IntrinsicArrayFunction_t &x) { + for (size_t i=0; i(&(x.m_args[i])); + self().call_replacer(); + current_expr = current_expr_copy_133; + if( x.m_args[i] && visit_expr_after_replacement ) + self().visit_expr(*x.m_args[i]); + } + if (x.m_type) { + self().visit_ttype(*x.m_type); + } + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_134 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_134; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_IntrinsicImpureFunction(const IntrinsicImpureFunction_t &x) { + for (size_t i=0; i(&(x.m_args[i])); + self().call_replacer(); + current_expr = current_expr_copy_135; + if( x.m_args[i] && visit_expr_after_replacement ) + self().visit_expr(*x.m_args[i]); + } + if (x.m_type) { + self().visit_ttype(*x.m_type); + } + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_136 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_136; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_TypeInquiry(const TypeInquiry_t &x) { + self().visit_ttype(*x.m_arg_type); + if (x.m_arg) { + ASR::expr_t** current_expr_copy_137 = current_expr; + current_expr = const_cast(&(x.m_arg)); + self().call_replacer(); + current_expr = current_expr_copy_137; + if( x.m_arg && visit_expr_after_replacement ) + self().visit_expr(*x.m_arg); + } + self().visit_ttype(*x.m_type); + ASR::expr_t** current_expr_copy_138 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_138; + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + void visit_StructConstructor(const StructConstructor_t &x) { + for (size_t i=0; i(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_139; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_StructConstant(const StructConstant_t &x) { + for (size_t i=0; i(&(x.m_args[i])); + self().call_replacer(); + current_expr = current_expr_copy_140; + if( x.m_args[i] && visit_expr_after_replacement ) + self().visit_expr(*x.m_args[i]); + } + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_141 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_141; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_UnionConstructor(const UnionConstructor_t &x) { + for (size_t i=0; i(&(x.m_args[i])); + self().call_replacer(); + current_expr = current_expr_copy_142; + if( x.m_args[i] && visit_expr_after_replacement ) + self().visit_expr(*x.m_args[i]); + } + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_143 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_143; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_ImpliedDoLoop(const ImpliedDoLoop_t &x) { + for (size_t i=0; i(&(x.m_values[i])); + self().call_replacer(); + current_expr = current_expr_copy_144; + if( x.m_values[i] && visit_expr_after_replacement ) + self().visit_expr(*x.m_values[i]); + } + ASR::expr_t** current_expr_copy_145 = current_expr; + current_expr = const_cast(&(x.m_var)); + self().call_replacer(); + current_expr = current_expr_copy_145; + if( x.m_var && visit_expr_after_replacement ) + self().visit_expr(*x.m_var); + ASR::expr_t** current_expr_copy_146 = current_expr; + current_expr = const_cast(&(x.m_start)); + self().call_replacer(); + current_expr = current_expr_copy_146; + if( x.m_start && visit_expr_after_replacement ) + self().visit_expr(*x.m_start); + ASR::expr_t** current_expr_copy_147 = current_expr; + current_expr = const_cast(&(x.m_end)); + self().call_replacer(); + current_expr = current_expr_copy_147; + if( x.m_end && visit_expr_after_replacement ) + self().visit_expr(*x.m_end); + if (x.m_increment) { + ASR::expr_t** current_expr_copy_148 = current_expr; + current_expr = const_cast(&(x.m_increment)); + self().call_replacer(); + current_expr = current_expr_copy_148; + if( x.m_increment && visit_expr_after_replacement ) + self().visit_expr(*x.m_increment); + } + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_149 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_149; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_IntegerConstant(const IntegerConstant_t &x) { + self().visit_ttype(*x.m_type); + } + void visit_IntegerBitNot(const IntegerBitNot_t &x) { + ASR::expr_t** current_expr_copy_150 = current_expr; + current_expr = const_cast(&(x.m_arg)); + self().call_replacer(); + current_expr = current_expr_copy_150; + if( x.m_arg && visit_expr_after_replacement ) + self().visit_expr(*x.m_arg); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_151 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_151; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_IntegerUnaryMinus(const IntegerUnaryMinus_t &x) { + ASR::expr_t** current_expr_copy_152 = current_expr; + current_expr = const_cast(&(x.m_arg)); + self().call_replacer(); + current_expr = current_expr_copy_152; + if( x.m_arg && visit_expr_after_replacement ) + self().visit_expr(*x.m_arg); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_153 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_153; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_IntegerCompare(const IntegerCompare_t &x) { + ASR::expr_t** current_expr_copy_154 = current_expr; + current_expr = const_cast(&(x.m_left)); + self().call_replacer(); + current_expr = current_expr_copy_154; + if( x.m_left && visit_expr_after_replacement ) + self().visit_expr(*x.m_left); + ASR::expr_t** current_expr_copy_155 = current_expr; + current_expr = const_cast(&(x.m_right)); + self().call_replacer(); + current_expr = current_expr_copy_155; + if( x.m_right && visit_expr_after_replacement ) + self().visit_expr(*x.m_right); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_156 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_156; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_IntegerBinOp(const IntegerBinOp_t &x) { + ASR::expr_t** current_expr_copy_157 = current_expr; + current_expr = const_cast(&(x.m_left)); + self().call_replacer(); + current_expr = current_expr_copy_157; + if( x.m_left && visit_expr_after_replacement ) + self().visit_expr(*x.m_left); + ASR::expr_t** current_expr_copy_158 = current_expr; + current_expr = const_cast(&(x.m_right)); + self().call_replacer(); + current_expr = current_expr_copy_158; + if( x.m_right && visit_expr_after_replacement ) + self().visit_expr(*x.m_right); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_159 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_159; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_UnsignedIntegerConstant(const UnsignedIntegerConstant_t &x) { + self().visit_ttype(*x.m_type); + } + void visit_UnsignedIntegerUnaryMinus(const UnsignedIntegerUnaryMinus_t &x) { + ASR::expr_t** current_expr_copy_160 = current_expr; + current_expr = const_cast(&(x.m_arg)); + self().call_replacer(); + current_expr = current_expr_copy_160; + if( x.m_arg && visit_expr_after_replacement ) + self().visit_expr(*x.m_arg); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_161 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_161; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_UnsignedIntegerBitNot(const UnsignedIntegerBitNot_t &x) { + ASR::expr_t** current_expr_copy_162 = current_expr; + current_expr = const_cast(&(x.m_arg)); + self().call_replacer(); + current_expr = current_expr_copy_162; + if( x.m_arg && visit_expr_after_replacement ) + self().visit_expr(*x.m_arg); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_163 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_163; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_UnsignedIntegerCompare(const UnsignedIntegerCompare_t &x) { + ASR::expr_t** current_expr_copy_164 = current_expr; + current_expr = const_cast(&(x.m_left)); + self().call_replacer(); + current_expr = current_expr_copy_164; + if( x.m_left && visit_expr_after_replacement ) + self().visit_expr(*x.m_left); + ASR::expr_t** current_expr_copy_165 = current_expr; + current_expr = const_cast(&(x.m_right)); + self().call_replacer(); + current_expr = current_expr_copy_165; + if( x.m_right && visit_expr_after_replacement ) + self().visit_expr(*x.m_right); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_166 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_166; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_UnsignedIntegerBinOp(const UnsignedIntegerBinOp_t &x) { + ASR::expr_t** current_expr_copy_167 = current_expr; + current_expr = const_cast(&(x.m_left)); + self().call_replacer(); + current_expr = current_expr_copy_167; + if( x.m_left && visit_expr_after_replacement ) + self().visit_expr(*x.m_left); + ASR::expr_t** current_expr_copy_168 = current_expr; + current_expr = const_cast(&(x.m_right)); + self().call_replacer(); + current_expr = current_expr_copy_168; + if( x.m_right && visit_expr_after_replacement ) + self().visit_expr(*x.m_right); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_169 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_169; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_RealConstant(const RealConstant_t &x) { + self().visit_ttype(*x.m_type); + } + void visit_RealUnaryMinus(const RealUnaryMinus_t &x) { + ASR::expr_t** current_expr_copy_170 = current_expr; + current_expr = const_cast(&(x.m_arg)); + self().call_replacer(); + current_expr = current_expr_copy_170; + if( x.m_arg && visit_expr_after_replacement ) + self().visit_expr(*x.m_arg); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_171 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_171; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_RealCompare(const RealCompare_t &x) { + ASR::expr_t** current_expr_copy_172 = current_expr; + current_expr = const_cast(&(x.m_left)); + self().call_replacer(); + current_expr = current_expr_copy_172; + if( x.m_left && visit_expr_after_replacement ) + self().visit_expr(*x.m_left); + ASR::expr_t** current_expr_copy_173 = current_expr; + current_expr = const_cast(&(x.m_right)); + self().call_replacer(); + current_expr = current_expr_copy_173; + if( x.m_right && visit_expr_after_replacement ) + self().visit_expr(*x.m_right); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_174 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_174; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_RealBinOp(const RealBinOp_t &x) { + ASR::expr_t** current_expr_copy_175 = current_expr; + current_expr = const_cast(&(x.m_left)); + self().call_replacer(); + current_expr = current_expr_copy_175; + if( x.m_left && visit_expr_after_replacement ) + self().visit_expr(*x.m_left); + ASR::expr_t** current_expr_copy_176 = current_expr; + current_expr = const_cast(&(x.m_right)); + self().call_replacer(); + current_expr = current_expr_copy_176; + if( x.m_right && visit_expr_after_replacement ) + self().visit_expr(*x.m_right); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_177 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_177; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_RealCopySign(const RealCopySign_t &x) { + ASR::expr_t** current_expr_copy_178 = current_expr; + current_expr = const_cast(&(x.m_target)); + self().call_replacer(); + current_expr = current_expr_copy_178; + if( x.m_target && visit_expr_after_replacement ) + self().visit_expr(*x.m_target); + ASR::expr_t** current_expr_copy_179 = current_expr; + current_expr = const_cast(&(x.m_source)); + self().call_replacer(); + current_expr = current_expr_copy_179; + if( x.m_source && visit_expr_after_replacement ) + self().visit_expr(*x.m_source); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_180 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_180; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_ComplexConstant(const ComplexConstant_t &x) { + self().visit_ttype(*x.m_type); + } + void visit_ComplexUnaryMinus(const ComplexUnaryMinus_t &x) { + ASR::expr_t** current_expr_copy_181 = current_expr; + current_expr = const_cast(&(x.m_arg)); + self().call_replacer(); + current_expr = current_expr_copy_181; + if( x.m_arg && visit_expr_after_replacement ) + self().visit_expr(*x.m_arg); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_182 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_182; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_ComplexCompare(const ComplexCompare_t &x) { + ASR::expr_t** current_expr_copy_183 = current_expr; + current_expr = const_cast(&(x.m_left)); + self().call_replacer(); + current_expr = current_expr_copy_183; + if( x.m_left && visit_expr_after_replacement ) + self().visit_expr(*x.m_left); + ASR::expr_t** current_expr_copy_184 = current_expr; + current_expr = const_cast(&(x.m_right)); + self().call_replacer(); + current_expr = current_expr_copy_184; + if( x.m_right && visit_expr_after_replacement ) + self().visit_expr(*x.m_right); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_185 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_185; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_ComplexBinOp(const ComplexBinOp_t &x) { + ASR::expr_t** current_expr_copy_186 = current_expr; + current_expr = const_cast(&(x.m_left)); + self().call_replacer(); + current_expr = current_expr_copy_186; + if( x.m_left && visit_expr_after_replacement ) + self().visit_expr(*x.m_left); + ASR::expr_t** current_expr_copy_187 = current_expr; + current_expr = const_cast(&(x.m_right)); + self().call_replacer(); + current_expr = current_expr_copy_187; + if( x.m_right && visit_expr_after_replacement ) + self().visit_expr(*x.m_right); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_188 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_188; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_LogicalConstant(const LogicalConstant_t &x) { + self().visit_ttype(*x.m_type); + } + void visit_LogicalNot(const LogicalNot_t &x) { + ASR::expr_t** current_expr_copy_189 = current_expr; + current_expr = const_cast(&(x.m_arg)); + self().call_replacer(); + current_expr = current_expr_copy_189; + if( x.m_arg && visit_expr_after_replacement ) + self().visit_expr(*x.m_arg); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_190 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_190; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_LogicalCompare(const LogicalCompare_t &x) { + ASR::expr_t** current_expr_copy_191 = current_expr; + current_expr = const_cast(&(x.m_left)); + self().call_replacer(); + current_expr = current_expr_copy_191; + if( x.m_left && visit_expr_after_replacement ) + self().visit_expr(*x.m_left); + ASR::expr_t** current_expr_copy_192 = current_expr; + current_expr = const_cast(&(x.m_right)); + self().call_replacer(); + current_expr = current_expr_copy_192; + if( x.m_right && visit_expr_after_replacement ) + self().visit_expr(*x.m_right); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_193 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_193; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_LogicalBinOp(const LogicalBinOp_t &x) { + ASR::expr_t** current_expr_copy_194 = current_expr; + current_expr = const_cast(&(x.m_left)); + self().call_replacer(); + current_expr = current_expr_copy_194; + if( x.m_left && visit_expr_after_replacement ) + self().visit_expr(*x.m_left); + ASR::expr_t** current_expr_copy_195 = current_expr; + current_expr = const_cast(&(x.m_right)); + self().call_replacer(); + current_expr = current_expr_copy_195; + if( x.m_right && visit_expr_after_replacement ) + self().visit_expr(*x.m_right); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_196 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_196; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_ListConstant(const ListConstant_t &x) { + for (size_t i=0; i(&(x.m_args[i])); + self().call_replacer(); + current_expr = current_expr_copy_197; + if( x.m_args[i] && visit_expr_after_replacement ) + self().visit_expr(*x.m_args[i]); + } + self().visit_ttype(*x.m_type); + } + void visit_ListLen(const ListLen_t &x) { + ASR::expr_t** current_expr_copy_198 = current_expr; + current_expr = const_cast(&(x.m_arg)); + self().call_replacer(); + current_expr = current_expr_copy_198; + if( x.m_arg && visit_expr_after_replacement ) + self().visit_expr(*x.m_arg); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_199 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_199; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_ListConcat(const ListConcat_t &x) { + ASR::expr_t** current_expr_copy_200 = current_expr; + current_expr = const_cast(&(x.m_left)); + self().call_replacer(); + current_expr = current_expr_copy_200; + if( x.m_left && visit_expr_after_replacement ) + self().visit_expr(*x.m_left); + ASR::expr_t** current_expr_copy_201 = current_expr; + current_expr = const_cast(&(x.m_right)); + self().call_replacer(); + current_expr = current_expr_copy_201; + if( x.m_right && visit_expr_after_replacement ) + self().visit_expr(*x.m_right); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_202 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_202; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_ListCompare(const ListCompare_t &x) { + ASR::expr_t** current_expr_copy_203 = current_expr; + current_expr = const_cast(&(x.m_left)); + self().call_replacer(); + current_expr = current_expr_copy_203; + if( x.m_left && visit_expr_after_replacement ) + self().visit_expr(*x.m_left); + ASR::expr_t** current_expr_copy_204 = current_expr; + current_expr = const_cast(&(x.m_right)); + self().call_replacer(); + current_expr = current_expr_copy_204; + if( x.m_right && visit_expr_after_replacement ) + self().visit_expr(*x.m_right); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_205 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_205; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_ListCount(const ListCount_t &x) { + ASR::expr_t** current_expr_copy_206 = current_expr; + current_expr = const_cast(&(x.m_arg)); + self().call_replacer(); + current_expr = current_expr_copy_206; + if( x.m_arg && visit_expr_after_replacement ) + self().visit_expr(*x.m_arg); + ASR::expr_t** current_expr_copy_207 = current_expr; + current_expr = const_cast(&(x.m_ele)); + self().call_replacer(); + current_expr = current_expr_copy_207; + if( x.m_ele && visit_expr_after_replacement ) + self().visit_expr(*x.m_ele); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_208 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_208; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_ListContains(const ListContains_t &x) { + ASR::expr_t** current_expr_copy_209 = current_expr; + current_expr = const_cast(&(x.m_left)); + self().call_replacer(); + current_expr = current_expr_copy_209; + if( x.m_left && visit_expr_after_replacement ) + self().visit_expr(*x.m_left); + ASR::expr_t** current_expr_copy_210 = current_expr; + current_expr = const_cast(&(x.m_right)); + self().call_replacer(); + current_expr = current_expr_copy_210; + if( x.m_right && visit_expr_after_replacement ) + self().visit_expr(*x.m_right); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_211 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_211; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_SetConstant(const SetConstant_t &x) { + for (size_t i=0; i(&(x.m_elements[i])); + self().call_replacer(); + current_expr = current_expr_copy_212; + if( x.m_elements[i] && visit_expr_after_replacement ) + self().visit_expr(*x.m_elements[i]); + } + self().visit_ttype(*x.m_type); + } + void visit_SetLen(const SetLen_t &x) { + ASR::expr_t** current_expr_copy_213 = current_expr; + current_expr = const_cast(&(x.m_arg)); + self().call_replacer(); + current_expr = current_expr_copy_213; + if( x.m_arg && visit_expr_after_replacement ) + self().visit_expr(*x.m_arg); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_214 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_214; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_TupleConstant(const TupleConstant_t &x) { + for (size_t i=0; i(&(x.m_elements[i])); + self().call_replacer(); + current_expr = current_expr_copy_215; + if( x.m_elements[i] && visit_expr_after_replacement ) + self().visit_expr(*x.m_elements[i]); + } + self().visit_ttype(*x.m_type); + } + void visit_TupleLen(const TupleLen_t &x) { + ASR::expr_t** current_expr_copy_216 = current_expr; + current_expr = const_cast(&(x.m_arg)); + self().call_replacer(); + current_expr = current_expr_copy_216; + if( x.m_arg && visit_expr_after_replacement ) + self().visit_expr(*x.m_arg); + self().visit_ttype(*x.m_type); + ASR::expr_t** current_expr_copy_217 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_217; + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + void visit_TupleCompare(const TupleCompare_t &x) { + ASR::expr_t** current_expr_copy_218 = current_expr; + current_expr = const_cast(&(x.m_left)); + self().call_replacer(); + current_expr = current_expr_copy_218; + if( x.m_left && visit_expr_after_replacement ) + self().visit_expr(*x.m_left); + ASR::expr_t** current_expr_copy_219 = current_expr; + current_expr = const_cast(&(x.m_right)); + self().call_replacer(); + current_expr = current_expr_copy_219; + if( x.m_right && visit_expr_after_replacement ) + self().visit_expr(*x.m_right); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_220 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_220; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_TupleConcat(const TupleConcat_t &x) { + ASR::expr_t** current_expr_copy_221 = current_expr; + current_expr = const_cast(&(x.m_left)); + self().call_replacer(); + current_expr = current_expr_copy_221; + if( x.m_left && visit_expr_after_replacement ) + self().visit_expr(*x.m_left); + ASR::expr_t** current_expr_copy_222 = current_expr; + current_expr = const_cast(&(x.m_right)); + self().call_replacer(); + current_expr = current_expr_copy_222; + if( x.m_right && visit_expr_after_replacement ) + self().visit_expr(*x.m_right); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_223 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_223; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_TupleContains(const TupleContains_t &x) { + ASR::expr_t** current_expr_copy_224 = current_expr; + current_expr = const_cast(&(x.m_left)); + self().call_replacer(); + current_expr = current_expr_copy_224; + if( x.m_left && visit_expr_after_replacement ) + self().visit_expr(*x.m_left); + ASR::expr_t** current_expr_copy_225 = current_expr; + current_expr = const_cast(&(x.m_right)); + self().call_replacer(); + current_expr = current_expr_copy_225; + if( x.m_right && visit_expr_after_replacement ) + self().visit_expr(*x.m_right); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_226 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_226; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_StringConstant(const StringConstant_t &x) { + self().visit_ttype(*x.m_type); + } + void visit_StringConcat(const StringConcat_t &x) { + ASR::expr_t** current_expr_copy_227 = current_expr; + current_expr = const_cast(&(x.m_left)); + self().call_replacer(); + current_expr = current_expr_copy_227; + if( x.m_left && visit_expr_after_replacement ) + self().visit_expr(*x.m_left); + ASR::expr_t** current_expr_copy_228 = current_expr; + current_expr = const_cast(&(x.m_right)); + self().call_replacer(); + current_expr = current_expr_copy_228; + if( x.m_right && visit_expr_after_replacement ) + self().visit_expr(*x.m_right); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_229 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_229; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_StringRepeat(const StringRepeat_t &x) { + ASR::expr_t** current_expr_copy_230 = current_expr; + current_expr = const_cast(&(x.m_left)); + self().call_replacer(); + current_expr = current_expr_copy_230; + if( x.m_left && visit_expr_after_replacement ) + self().visit_expr(*x.m_left); + ASR::expr_t** current_expr_copy_231 = current_expr; + current_expr = const_cast(&(x.m_right)); + self().call_replacer(); + current_expr = current_expr_copy_231; + if( x.m_right && visit_expr_after_replacement ) + self().visit_expr(*x.m_right); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_232 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_232; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_StringLen(const StringLen_t &x) { + ASR::expr_t** current_expr_copy_233 = current_expr; + current_expr = const_cast(&(x.m_arg)); + self().call_replacer(); + current_expr = current_expr_copy_233; + if( x.m_arg && visit_expr_after_replacement ) + self().visit_expr(*x.m_arg); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_234 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_234; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_StringItem(const StringItem_t &x) { + ASR::expr_t** current_expr_copy_235 = current_expr; + current_expr = const_cast(&(x.m_arg)); + self().call_replacer(); + current_expr = current_expr_copy_235; + if( x.m_arg && visit_expr_after_replacement ) + self().visit_expr(*x.m_arg); + ASR::expr_t** current_expr_copy_236 = current_expr; + current_expr = const_cast(&(x.m_idx)); + self().call_replacer(); + current_expr = current_expr_copy_236; + if( x.m_idx && visit_expr_after_replacement ) + self().visit_expr(*x.m_idx); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_237 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_237; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_StringSection(const StringSection_t &x) { + ASR::expr_t** current_expr_copy_238 = current_expr; + current_expr = const_cast(&(x.m_arg)); + self().call_replacer(); + current_expr = current_expr_copy_238; + if( x.m_arg && visit_expr_after_replacement ) + self().visit_expr(*x.m_arg); + if (x.m_start) { + ASR::expr_t** current_expr_copy_239 = current_expr; + current_expr = const_cast(&(x.m_start)); + self().call_replacer(); + current_expr = current_expr_copy_239; + if( x.m_start && visit_expr_after_replacement ) + self().visit_expr(*x.m_start); + } + if (x.m_end) { + ASR::expr_t** current_expr_copy_240 = current_expr; + current_expr = const_cast(&(x.m_end)); + self().call_replacer(); + current_expr = current_expr_copy_240; + if( x.m_end && visit_expr_after_replacement ) + self().visit_expr(*x.m_end); + } + if (x.m_step) { + ASR::expr_t** current_expr_copy_241 = current_expr; + current_expr = const_cast(&(x.m_step)); + self().call_replacer(); + current_expr = current_expr_copy_241; + if( x.m_step && visit_expr_after_replacement ) + self().visit_expr(*x.m_step); + } + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_242 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_242; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_StringCompare(const StringCompare_t &x) { + ASR::expr_t** current_expr_copy_243 = current_expr; + current_expr = const_cast(&(x.m_left)); + self().call_replacer(); + current_expr = current_expr_copy_243; + if( x.m_left && visit_expr_after_replacement ) + self().visit_expr(*x.m_left); + ASR::expr_t** current_expr_copy_244 = current_expr; + current_expr = const_cast(&(x.m_right)); + self().call_replacer(); + current_expr = current_expr_copy_244; + if( x.m_right && visit_expr_after_replacement ) + self().visit_expr(*x.m_right); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_245 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_245; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_StringContains(const StringContains_t &x) { + ASR::expr_t** current_expr_copy_246 = current_expr; + current_expr = const_cast(&(x.m_substr)); + self().call_replacer(); + current_expr = current_expr_copy_246; + if( x.m_substr && visit_expr_after_replacement ) + self().visit_expr(*x.m_substr); + ASR::expr_t** current_expr_copy_247 = current_expr; + current_expr = const_cast(&(x.m_str)); + self().call_replacer(); + current_expr = current_expr_copy_247; + if( x.m_str && visit_expr_after_replacement ) + self().visit_expr(*x.m_str); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_248 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_248; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_StringOrd(const StringOrd_t &x) { + ASR::expr_t** current_expr_copy_249 = current_expr; + current_expr = const_cast(&(x.m_arg)); + self().call_replacer(); + current_expr = current_expr_copy_249; + if( x.m_arg && visit_expr_after_replacement ) + self().visit_expr(*x.m_arg); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_250 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_250; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_StringChr(const StringChr_t &x) { + ASR::expr_t** current_expr_copy_251 = current_expr; + current_expr = const_cast(&(x.m_arg)); + self().call_replacer(); + current_expr = current_expr_copy_251; + if( x.m_arg && visit_expr_after_replacement ) + self().visit_expr(*x.m_arg); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_252 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_252; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_StringFormat(const StringFormat_t &x) { + if (x.m_fmt) { + ASR::expr_t** current_expr_copy_253 = current_expr; + current_expr = const_cast(&(x.m_fmt)); + self().call_replacer(); + current_expr = current_expr_copy_253; + if( x.m_fmt && visit_expr_after_replacement ) + self().visit_expr(*x.m_fmt); + } + for (size_t i=0; i(&(x.m_args[i])); + self().call_replacer(); + current_expr = current_expr_copy_254; + if( x.m_args[i] && visit_expr_after_replacement ) + self().visit_expr(*x.m_args[i]); + } + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_255 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_255; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_StringPhysicalCast(const StringPhysicalCast_t &x) { + ASR::expr_t** current_expr_copy_256 = current_expr; + current_expr = const_cast(&(x.m_arg)); + self().call_replacer(); + current_expr = current_expr_copy_256; + if( x.m_arg && visit_expr_after_replacement ) + self().visit_expr(*x.m_arg); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_257 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_257; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_CPtrCompare(const CPtrCompare_t &x) { + ASR::expr_t** current_expr_copy_258 = current_expr; + current_expr = const_cast(&(x.m_left)); + self().call_replacer(); + current_expr = current_expr_copy_258; + if( x.m_left && visit_expr_after_replacement ) + self().visit_expr(*x.m_left); + ASR::expr_t** current_expr_copy_259 = current_expr; + current_expr = const_cast(&(x.m_right)); + self().call_replacer(); + current_expr = current_expr_copy_259; + if( x.m_right && visit_expr_after_replacement ) + self().visit_expr(*x.m_right); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_260 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_260; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_SymbolicCompare(const SymbolicCompare_t &x) { + ASR::expr_t** current_expr_copy_261 = current_expr; + current_expr = const_cast(&(x.m_left)); + self().call_replacer(); + current_expr = current_expr_copy_261; + if( x.m_left && visit_expr_after_replacement ) + self().visit_expr(*x.m_left); + ASR::expr_t** current_expr_copy_262 = current_expr; + current_expr = const_cast(&(x.m_right)); + self().call_replacer(); + current_expr = current_expr_copy_262; + if( x.m_right && visit_expr_after_replacement ) + self().visit_expr(*x.m_right); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_263 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_263; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_DictConstant(const DictConstant_t &x) { + for (size_t i=0; i(&(x.m_keys[i])); + self().call_replacer(); + current_expr = current_expr_copy_264; + if( x.m_keys[i] && visit_expr_after_replacement ) + self().visit_expr(*x.m_keys[i]); + } + for (size_t i=0; i(&(x.m_values[i])); + self().call_replacer(); + current_expr = current_expr_copy_265; + if( x.m_values[i] && visit_expr_after_replacement ) + self().visit_expr(*x.m_values[i]); + } + self().visit_ttype(*x.m_type); + } + void visit_DictLen(const DictLen_t &x) { + ASR::expr_t** current_expr_copy_266 = current_expr; + current_expr = const_cast(&(x.m_arg)); + self().call_replacer(); + current_expr = current_expr_copy_266; + if( x.m_arg && visit_expr_after_replacement ) + self().visit_expr(*x.m_arg); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_267 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_267; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_Var(const Var_t &x) { + if ((bool&)x) { } // Suppress unused warning + } + void visit_FunctionParam(const FunctionParam_t &x) { + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_268 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_268; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_ArrayConstructor(const ArrayConstructor_t &x) { + for (size_t i=0; i(&(x.m_args[i])); + self().call_replacer(); + current_expr = current_expr_copy_269; + if( x.m_args[i] && visit_expr_after_replacement ) + self().visit_expr(*x.m_args[i]); + } + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_270 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_270; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_ArrayConstant(const ArrayConstant_t &x) { + self().visit_ttype(*x.m_type); + } + void visit_ArrayItem(const ArrayItem_t &x) { + ASR::expr_t** current_expr_copy_271 = current_expr; + current_expr = const_cast(&(x.m_v)); + self().call_replacer(); + current_expr = current_expr_copy_271; + if( x.m_v && visit_expr_after_replacement ) + self().visit_expr(*x.m_v); + for (size_t i=0; i(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_272; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_ArraySection(const ArraySection_t &x) { + ASR::expr_t** current_expr_copy_273 = current_expr; + current_expr = const_cast(&(x.m_v)); + self().call_replacer(); + current_expr = current_expr_copy_273; + if( x.m_v && visit_expr_after_replacement ) + self().visit_expr(*x.m_v); + for (size_t i=0; i(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_274; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_ArraySize(const ArraySize_t &x) { + ASR::expr_t** current_expr_copy_275 = current_expr; + current_expr = const_cast(&(x.m_v)); + self().call_replacer(); + current_expr = current_expr_copy_275; + if( x.m_v && visit_expr_after_replacement ) + self().visit_expr(*x.m_v); + if (x.m_dim) { + ASR::expr_t** current_expr_copy_276 = current_expr; + current_expr = const_cast(&(x.m_dim)); + self().call_replacer(); + current_expr = current_expr_copy_276; + if( x.m_dim && visit_expr_after_replacement ) + self().visit_expr(*x.m_dim); + } + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_277 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_277; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_ArrayBound(const ArrayBound_t &x) { + ASR::expr_t** current_expr_copy_278 = current_expr; + current_expr = const_cast(&(x.m_v)); + self().call_replacer(); + current_expr = current_expr_copy_278; + if( x.m_v && visit_expr_after_replacement ) + self().visit_expr(*x.m_v); + if (x.m_dim) { + ASR::expr_t** current_expr_copy_279 = current_expr; + current_expr = const_cast(&(x.m_dim)); + self().call_replacer(); + current_expr = current_expr_copy_279; + if( x.m_dim && visit_expr_after_replacement ) + self().visit_expr(*x.m_dim); + } + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_280 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_280; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_ArrayTranspose(const ArrayTranspose_t &x) { + ASR::expr_t** current_expr_copy_281 = current_expr; + current_expr = const_cast(&(x.m_matrix)); + self().call_replacer(); + current_expr = current_expr_copy_281; + if( x.m_matrix && visit_expr_after_replacement ) + self().visit_expr(*x.m_matrix); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_282 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_282; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_ArrayPack(const ArrayPack_t &x) { + ASR::expr_t** current_expr_copy_283 = current_expr; + current_expr = const_cast(&(x.m_array)); + self().call_replacer(); + current_expr = current_expr_copy_283; + if( x.m_array && visit_expr_after_replacement ) + self().visit_expr(*x.m_array); + ASR::expr_t** current_expr_copy_284 = current_expr; + current_expr = const_cast(&(x.m_mask)); + self().call_replacer(); + current_expr = current_expr_copy_284; + if( x.m_mask && visit_expr_after_replacement ) + self().visit_expr(*x.m_mask); + if (x.m_vector) { + ASR::expr_t** current_expr_copy_285 = current_expr; + current_expr = const_cast(&(x.m_vector)); + self().call_replacer(); + current_expr = current_expr_copy_285; + if( x.m_vector && visit_expr_after_replacement ) + self().visit_expr(*x.m_vector); + } + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_286 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_286; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_ArrayReshape(const ArrayReshape_t &x) { + ASR::expr_t** current_expr_copy_287 = current_expr; + current_expr = const_cast(&(x.m_array)); + self().call_replacer(); + current_expr = current_expr_copy_287; + if( x.m_array && visit_expr_after_replacement ) + self().visit_expr(*x.m_array); + ASR::expr_t** current_expr_copy_288 = current_expr; + current_expr = const_cast(&(x.m_shape)); + self().call_replacer(); + current_expr = current_expr_copy_288; + if( x.m_shape && visit_expr_after_replacement ) + self().visit_expr(*x.m_shape); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_289 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_289; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_ArrayAll(const ArrayAll_t &x) { + ASR::expr_t** current_expr_copy_290 = current_expr; + current_expr = const_cast(&(x.m_mask)); + self().call_replacer(); + current_expr = current_expr_copy_290; + if( x.m_mask && visit_expr_after_replacement ) + self().visit_expr(*x.m_mask); + if (x.m_dim) { + ASR::expr_t** current_expr_copy_291 = current_expr; + current_expr = const_cast(&(x.m_dim)); + self().call_replacer(); + current_expr = current_expr_copy_291; + if( x.m_dim && visit_expr_after_replacement ) + self().visit_expr(*x.m_dim); + } + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_292 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_292; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_ArrayBroadcast(const ArrayBroadcast_t &x) { + ASR::expr_t** current_expr_copy_293 = current_expr; + current_expr = const_cast(&(x.m_array)); + self().call_replacer(); + current_expr = current_expr_copy_293; + if( x.m_array && visit_expr_after_replacement ) + self().visit_expr(*x.m_array); + ASR::expr_t** current_expr_copy_294 = current_expr; + current_expr = const_cast(&(x.m_shape)); + self().call_replacer(); + current_expr = current_expr_copy_294; + if( x.m_shape && visit_expr_after_replacement ) + self().visit_expr(*x.m_shape); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_295 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_295; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_BitCast(const BitCast_t &x) { + ASR::expr_t** current_expr_copy_296 = current_expr; + current_expr = const_cast(&(x.m_source)); + self().call_replacer(); + current_expr = current_expr_copy_296; + if( x.m_source && visit_expr_after_replacement ) + self().visit_expr(*x.m_source); + ASR::expr_t** current_expr_copy_297 = current_expr; + current_expr = const_cast(&(x.m_mold)); + self().call_replacer(); + current_expr = current_expr_copy_297; + if( x.m_mold && visit_expr_after_replacement ) + self().visit_expr(*x.m_mold); + if (x.m_size) { + ASR::expr_t** current_expr_copy_298 = current_expr; + current_expr = const_cast(&(x.m_size)); + self().call_replacer(); + current_expr = current_expr_copy_298; + if( x.m_size && visit_expr_after_replacement ) + self().visit_expr(*x.m_size); + } + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_299 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_299; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_StructInstanceMember(const StructInstanceMember_t &x) { + ASR::expr_t** current_expr_copy_300 = current_expr; + current_expr = const_cast(&(x.m_v)); + self().call_replacer(); + current_expr = current_expr_copy_300; + if( x.m_v && visit_expr_after_replacement ) + self().visit_expr(*x.m_v); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_301 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_301; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_StructStaticMember(const StructStaticMember_t &x) { + ASR::expr_t** current_expr_copy_302 = current_expr; + current_expr = const_cast(&(x.m_v)); + self().call_replacer(); + current_expr = current_expr_copy_302; + if( x.m_v && visit_expr_after_replacement ) + self().visit_expr(*x.m_v); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_303 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_303; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_EnumStaticMember(const EnumStaticMember_t &x) { + ASR::expr_t** current_expr_copy_304 = current_expr; + current_expr = const_cast(&(x.m_v)); + self().call_replacer(); + current_expr = current_expr_copy_304; + if( x.m_v && visit_expr_after_replacement ) + self().visit_expr(*x.m_v); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_305 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_305; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_UnionInstanceMember(const UnionInstanceMember_t &x) { + ASR::expr_t** current_expr_copy_306 = current_expr; + current_expr = const_cast(&(x.m_v)); + self().call_replacer(); + current_expr = current_expr_copy_306; + if( x.m_v && visit_expr_after_replacement ) + self().visit_expr(*x.m_v); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_307 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_307; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_EnumName(const EnumName_t &x) { + ASR::expr_t** current_expr_copy_308 = current_expr; + current_expr = const_cast(&(x.m_v)); + self().call_replacer(); + current_expr = current_expr_copy_308; + if( x.m_v && visit_expr_after_replacement ) + self().visit_expr(*x.m_v); + self().visit_ttype(*x.m_enum_type); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_309 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_309; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_EnumValue(const EnumValue_t &x) { + ASR::expr_t** current_expr_copy_310 = current_expr; + current_expr = const_cast(&(x.m_v)); + self().call_replacer(); + current_expr = current_expr_copy_310; + if( x.m_v && visit_expr_after_replacement ) + self().visit_expr(*x.m_v); + self().visit_ttype(*x.m_enum_type); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_311 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_311; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_OverloadedCompare(const OverloadedCompare_t &x) { + ASR::expr_t** current_expr_copy_312 = current_expr; + current_expr = const_cast(&(x.m_left)); + self().call_replacer(); + current_expr = current_expr_copy_312; + if( x.m_left && visit_expr_after_replacement ) + self().visit_expr(*x.m_left); + ASR::expr_t** current_expr_copy_313 = current_expr; + current_expr = const_cast(&(x.m_right)); + self().call_replacer(); + current_expr = current_expr_copy_313; + if( x.m_right && visit_expr_after_replacement ) + self().visit_expr(*x.m_right); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_314 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_314; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + ASR::expr_t** current_expr_copy_315 = current_expr; + current_expr = const_cast(&(x.m_overloaded)); + self().call_replacer(); + current_expr = current_expr_copy_315; + if( x.m_overloaded && visit_expr_after_replacement ) + self().visit_expr(*x.m_overloaded); + } + void visit_OverloadedBinOp(const OverloadedBinOp_t &x) { + ASR::expr_t** current_expr_copy_316 = current_expr; + current_expr = const_cast(&(x.m_left)); + self().call_replacer(); + current_expr = current_expr_copy_316; + if( x.m_left && visit_expr_after_replacement ) + self().visit_expr(*x.m_left); + ASR::expr_t** current_expr_copy_317 = current_expr; + current_expr = const_cast(&(x.m_right)); + self().call_replacer(); + current_expr = current_expr_copy_317; + if( x.m_right && visit_expr_after_replacement ) + self().visit_expr(*x.m_right); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_318 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_318; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + ASR::expr_t** current_expr_copy_319 = current_expr; + current_expr = const_cast(&(x.m_overloaded)); + self().call_replacer(); + current_expr = current_expr_copy_319; + if( x.m_overloaded && visit_expr_after_replacement ) + self().visit_expr(*x.m_overloaded); + } + void visit_OverloadedUnaryMinus(const OverloadedUnaryMinus_t &x) { + ASR::expr_t** current_expr_copy_320 = current_expr; + current_expr = const_cast(&(x.m_arg)); + self().call_replacer(); + current_expr = current_expr_copy_320; + if( x.m_arg && visit_expr_after_replacement ) + self().visit_expr(*x.m_arg); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_321 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_321; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + ASR::expr_t** current_expr_copy_322 = current_expr; + current_expr = const_cast(&(x.m_overloaded)); + self().call_replacer(); + current_expr = current_expr_copy_322; + if( x.m_overloaded && visit_expr_after_replacement ) + self().visit_expr(*x.m_overloaded); + } + void visit_OverloadedStringConcat(const OverloadedStringConcat_t &x) { + ASR::expr_t** current_expr_copy_323 = current_expr; + current_expr = const_cast(&(x.m_left)); + self().call_replacer(); + current_expr = current_expr_copy_323; + if( x.m_left && visit_expr_after_replacement ) + self().visit_expr(*x.m_left); + ASR::expr_t** current_expr_copy_324 = current_expr; + current_expr = const_cast(&(x.m_right)); + self().call_replacer(); + current_expr = current_expr_copy_324; + if( x.m_right && visit_expr_after_replacement ) + self().visit_expr(*x.m_right); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_325 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_325; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + ASR::expr_t** current_expr_copy_326 = current_expr; + current_expr = const_cast(&(x.m_overloaded)); + self().call_replacer(); + current_expr = current_expr_copy_326; + if( x.m_overloaded && visit_expr_after_replacement ) + self().visit_expr(*x.m_overloaded); + } + void visit_Cast(const Cast_t &x) { + ASR::expr_t** current_expr_copy_327 = current_expr; + current_expr = const_cast(&(x.m_arg)); + self().call_replacer(); + current_expr = current_expr_copy_327; + if( x.m_arg && visit_expr_after_replacement ) + self().visit_expr(*x.m_arg); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_328 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_328; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_ArrayPhysicalCast(const ArrayPhysicalCast_t &x) { + ASR::expr_t** current_expr_copy_329 = current_expr; + current_expr = const_cast(&(x.m_arg)); + self().call_replacer(); + current_expr = current_expr_copy_329; + if( x.m_arg && visit_expr_after_replacement ) + self().visit_expr(*x.m_arg); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_330 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_330; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_ComplexRe(const ComplexRe_t &x) { + ASR::expr_t** current_expr_copy_331 = current_expr; + current_expr = const_cast(&(x.m_arg)); + self().call_replacer(); + current_expr = current_expr_copy_331; + if( x.m_arg && visit_expr_after_replacement ) + self().visit_expr(*x.m_arg); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_332 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_332; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_ComplexIm(const ComplexIm_t &x) { + ASR::expr_t** current_expr_copy_333 = current_expr; + current_expr = const_cast(&(x.m_arg)); + self().call_replacer(); + current_expr = current_expr_copy_333; + if( x.m_arg && visit_expr_after_replacement ) + self().visit_expr(*x.m_arg); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_334 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_334; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_DictItem(const DictItem_t &x) { + ASR::expr_t** current_expr_copy_335 = current_expr; + current_expr = const_cast(&(x.m_a)); + self().call_replacer(); + current_expr = current_expr_copy_335; + if( x.m_a && visit_expr_after_replacement ) + self().visit_expr(*x.m_a); + ASR::expr_t** current_expr_copy_336 = current_expr; + current_expr = const_cast(&(x.m_key)); + self().call_replacer(); + current_expr = current_expr_copy_336; + if( x.m_key && visit_expr_after_replacement ) + self().visit_expr(*x.m_key); + if (x.m_default) { + ASR::expr_t** current_expr_copy_337 = current_expr; + current_expr = const_cast(&(x.m_default)); + self().call_replacer(); + current_expr = current_expr_copy_337; + if( x.m_default && visit_expr_after_replacement ) + self().visit_expr(*x.m_default); + } + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_338 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_338; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_CLoc(const CLoc_t &x) { + ASR::expr_t** current_expr_copy_339 = current_expr; + current_expr = const_cast(&(x.m_arg)); + self().call_replacer(); + current_expr = current_expr_copy_339; + if( x.m_arg && visit_expr_after_replacement ) + self().visit_expr(*x.m_arg); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_340 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_340; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_PointerToCPtr(const PointerToCPtr_t &x) { + ASR::expr_t** current_expr_copy_341 = current_expr; + current_expr = const_cast(&(x.m_arg)); + self().call_replacer(); + current_expr = current_expr_copy_341; + if( x.m_arg && visit_expr_after_replacement ) + self().visit_expr(*x.m_arg); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_342 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_342; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_GetPointer(const GetPointer_t &x) { + ASR::expr_t** current_expr_copy_343 = current_expr; + current_expr = const_cast(&(x.m_arg)); + self().call_replacer(); + current_expr = current_expr_copy_343; + if( x.m_arg && visit_expr_after_replacement ) + self().visit_expr(*x.m_arg); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_344 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_344; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_ListItem(const ListItem_t &x) { + ASR::expr_t** current_expr_copy_345 = current_expr; + current_expr = const_cast(&(x.m_a)); + self().call_replacer(); + current_expr = current_expr_copy_345; + if( x.m_a && visit_expr_after_replacement ) + self().visit_expr(*x.m_a); + ASR::expr_t** current_expr_copy_346 = current_expr; + current_expr = const_cast(&(x.m_pos)); + self().call_replacer(); + current_expr = current_expr_copy_346; + if( x.m_pos && visit_expr_after_replacement ) + self().visit_expr(*x.m_pos); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_347 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_347; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_TupleItem(const TupleItem_t &x) { + ASR::expr_t** current_expr_copy_348 = current_expr; + current_expr = const_cast(&(x.m_a)); + self().call_replacer(); + current_expr = current_expr_copy_348; + if( x.m_a && visit_expr_after_replacement ) + self().visit_expr(*x.m_a); + ASR::expr_t** current_expr_copy_349 = current_expr; + current_expr = const_cast(&(x.m_pos)); + self().call_replacer(); + current_expr = current_expr_copy_349; + if( x.m_pos && visit_expr_after_replacement ) + self().visit_expr(*x.m_pos); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_350 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_350; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_ListSection(const ListSection_t &x) { + ASR::expr_t** current_expr_copy_351 = current_expr; + current_expr = const_cast(&(x.m_a)); + self().call_replacer(); + current_expr = current_expr_copy_351; + if( x.m_a && visit_expr_after_replacement ) + self().visit_expr(*x.m_a); + self().visit_array_index(x.m_section); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_352 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_352; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_ListRepeat(const ListRepeat_t &x) { + ASR::expr_t** current_expr_copy_353 = current_expr; + current_expr = const_cast(&(x.m_left)); + self().call_replacer(); + current_expr = current_expr_copy_353; + if( x.m_left && visit_expr_after_replacement ) + self().visit_expr(*x.m_left); + ASR::expr_t** current_expr_copy_354 = current_expr; + current_expr = const_cast(&(x.m_right)); + self().call_replacer(); + current_expr = current_expr_copy_354; + if( x.m_right && visit_expr_after_replacement ) + self().visit_expr(*x.m_right); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_355 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_355; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_DictPop(const DictPop_t &x) { + ASR::expr_t** current_expr_copy_356 = current_expr; + current_expr = const_cast(&(x.m_a)); + self().call_replacer(); + current_expr = current_expr_copy_356; + if( x.m_a && visit_expr_after_replacement ) + self().visit_expr(*x.m_a); + ASR::expr_t** current_expr_copy_357 = current_expr; + current_expr = const_cast(&(x.m_key)); + self().call_replacer(); + current_expr = current_expr_copy_357; + if( x.m_key && visit_expr_after_replacement ) + self().visit_expr(*x.m_key); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_358 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_358; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_SetPop(const SetPop_t &x) { + ASR::expr_t** current_expr_copy_359 = current_expr; + current_expr = const_cast(&(x.m_a)); + self().call_replacer(); + current_expr = current_expr_copy_359; + if( x.m_a && visit_expr_after_replacement ) + self().visit_expr(*x.m_a); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_360 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_360; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_SetContains(const SetContains_t &x) { + ASR::expr_t** current_expr_copy_361 = current_expr; + current_expr = const_cast(&(x.m_left)); + self().call_replacer(); + current_expr = current_expr_copy_361; + if( x.m_left && visit_expr_after_replacement ) + self().visit_expr(*x.m_left); + ASR::expr_t** current_expr_copy_362 = current_expr; + current_expr = const_cast(&(x.m_right)); + self().call_replacer(); + current_expr = current_expr_copy_362; + if( x.m_right && visit_expr_after_replacement ) + self().visit_expr(*x.m_right); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_363 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_363; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_DictContains(const DictContains_t &x) { + ASR::expr_t** current_expr_copy_364 = current_expr; + current_expr = const_cast(&(x.m_left)); + self().call_replacer(); + current_expr = current_expr_copy_364; + if( x.m_left && visit_expr_after_replacement ) + self().visit_expr(*x.m_left); + ASR::expr_t** current_expr_copy_365 = current_expr; + current_expr = const_cast(&(x.m_right)); + self().call_replacer(); + current_expr = current_expr_copy_365; + if( x.m_right && visit_expr_after_replacement ) + self().visit_expr(*x.m_right); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_366 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_366; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_IntegerBitLen(const IntegerBitLen_t &x) { + ASR::expr_t** current_expr_copy_367 = current_expr; + current_expr = const_cast(&(x.m_a)); + self().call_replacer(); + current_expr = current_expr_copy_367; + if( x.m_a && visit_expr_after_replacement ) + self().visit_expr(*x.m_a); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_368 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_368; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_Ichar(const Ichar_t &x) { + ASR::expr_t** current_expr_copy_369 = current_expr; + current_expr = const_cast(&(x.m_arg)); + self().call_replacer(); + current_expr = current_expr_copy_369; + if( x.m_arg && visit_expr_after_replacement ) + self().visit_expr(*x.m_arg); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_370 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_370; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_Iachar(const Iachar_t &x) { + ASR::expr_t** current_expr_copy_371 = current_expr; + current_expr = const_cast(&(x.m_arg)); + self().call_replacer(); + current_expr = current_expr_copy_371; + if( x.m_arg && visit_expr_after_replacement ) + self().visit_expr(*x.m_arg); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_372 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_372; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_SizeOfType(const SizeOfType_t &x) { + self().visit_ttype(*x.m_arg); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_373 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_373; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_PointerNullConstant(const PointerNullConstant_t &x) { + self().visit_ttype(*x.m_type); + } + void visit_PointerAssociated(const PointerAssociated_t &x) { + ASR::expr_t** current_expr_copy_374 = current_expr; + current_expr = const_cast(&(x.m_ptr)); + self().call_replacer(); + current_expr = current_expr_copy_374; + if( x.m_ptr && visit_expr_after_replacement ) + self().visit_expr(*x.m_ptr); + if (x.m_tgt) { + ASR::expr_t** current_expr_copy_375 = current_expr; + current_expr = const_cast(&(x.m_tgt)); + self().call_replacer(); + current_expr = current_expr_copy_375; + if( x.m_tgt && visit_expr_after_replacement ) + self().visit_expr(*x.m_tgt); + } + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_376 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_376; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_RealSqrt(const RealSqrt_t &x) { + ASR::expr_t** current_expr_copy_377 = current_expr; + current_expr = const_cast(&(x.m_arg)); + self().call_replacer(); + current_expr = current_expr_copy_377; + if( x.m_arg && visit_expr_after_replacement ) + self().visit_expr(*x.m_arg); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_378 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_378; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_ArrayIsContiguous(const ArrayIsContiguous_t &x) { + ASR::expr_t** current_expr_copy_379 = current_expr; + current_expr = const_cast(&(x.m_array)); + self().call_replacer(); + current_expr = current_expr_copy_379; + if( x.m_array && visit_expr_after_replacement ) + self().visit_expr(*x.m_array); + self().visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_380 = current_expr; + current_expr = const_cast(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_380; + } + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_Integer(const Integer_t &x) { + if ((bool&)x) { } // Suppress unused warning + } + void visit_UnsignedInteger(const UnsignedInteger_t &x) { + if ((bool&)x) { } // Suppress unused warning + } + void visit_Real(const Real_t &x) { + if ((bool&)x) { } // Suppress unused warning + } + void visit_Complex(const Complex_t &x) { + if ((bool&)x) { } // Suppress unused warning + } + void visit_String(const String_t &x) { + if (x.m_len_expr) { + ASR::expr_t** current_expr_copy_381 = current_expr; + current_expr = const_cast(&(x.m_len_expr)); + self().call_replacer(); + current_expr = current_expr_copy_381; + if( x.m_len_expr && visit_expr_after_replacement ) + self().visit_expr(*x.m_len_expr); + } + } + void visit_Logical(const Logical_t &x) { + if ((bool&)x) { } // Suppress unused warning + } + void visit_Set(const Set_t &x) { + self().visit_ttype(*x.m_type); + } + void visit_List(const List_t &x) { + self().visit_ttype(*x.m_type); + } + void visit_Tuple(const Tuple_t &x) { + for (size_t i=0; i(&(x.m_start)); + self().call_replacer(); + current_expr = current_expr_copy_382; + if( x.m_start && visit_expr_after_replacement ) + self().visit_expr(*x.m_start); + } + if (x.m_length) { + ASR::expr_t** current_expr_copy_383 = current_expr; + current_expr = const_cast(&(x.m_length)); + self().call_replacer(); + current_expr = current_expr_copy_383; + if( x.m_length && visit_expr_after_replacement ) + self().visit_expr(*x.m_length); + } + } + void visit_alloc_arg(const alloc_arg_t &x) { + ASR::expr_t** current_expr_copy_384 = current_expr; + current_expr = const_cast(&(x.m_a)); + self().call_replacer(); + current_expr = current_expr_copy_384; + if( x.m_a && visit_expr_after_replacement ) + self().visit_expr(*x.m_a); + for (size_t i=0; i(&(x.m_len_expr)); + self().call_replacer(); + current_expr = current_expr_copy_385; + if( x.m_len_expr && visit_expr_after_replacement ) + self().visit_expr(*x.m_len_expr); + } + if (x.m_type) { + self().visit_ttype(*x.m_type); + } + } + void visit_Attribute(const Attribute_t &x) { + for (size_t i=0; i(&(x.m_value)); + self().call_replacer(); + current_expr = current_expr_copy_386; + if( x.m_value && visit_expr_after_replacement ) + self().visit_expr(*x.m_value); + } + } + void visit_reduction_expr(const reduction_expr_t &x) { + ASR::expr_t** current_expr_copy_387 = current_expr; + current_expr = const_cast(&(x.m_arg)); + self().call_replacer(); + current_expr = current_expr_copy_387; + if( x.m_arg && visit_expr_after_replacement ) + self().visit_expr(*x.m_arg); + } + void visit_Bind(const Bind_t &x) { + if ((bool&)x) { } // Suppress unused warning + } + void visit_array_index(const array_index_t &x) { + if (x.m_left) { + ASR::expr_t** current_expr_copy_388 = current_expr; + current_expr = const_cast(&(x.m_left)); + self().call_replacer(); + current_expr = current_expr_copy_388; + if( x.m_left && visit_expr_after_replacement ) + self().visit_expr(*x.m_left); + } + if (x.m_right) { + ASR::expr_t** current_expr_copy_389 = current_expr; + current_expr = const_cast(&(x.m_right)); + self().call_replacer(); + current_expr = current_expr_copy_389; + if( x.m_right && visit_expr_after_replacement ) + self().visit_expr(*x.m_right); + } + if (x.m_step) { + ASR::expr_t** current_expr_copy_390 = current_expr; + current_expr = const_cast(&(x.m_step)); + self().call_replacer(); + current_expr = current_expr_copy_390; + if( x.m_step && visit_expr_after_replacement ) + self().visit_expr(*x.m_step); + } + } + void visit_do_loop_head(const do_loop_head_t &x) { + if (x.m_v) { + ASR::expr_t** current_expr_copy_391 = current_expr; + current_expr = const_cast(&(x.m_v)); + self().call_replacer(); + current_expr = current_expr_copy_391; + if( x.m_v && visit_expr_after_replacement ) + self().visit_expr(*x.m_v); + } + if (x.m_start) { + ASR::expr_t** current_expr_copy_392 = current_expr; + current_expr = const_cast(&(x.m_start)); + self().call_replacer(); + current_expr = current_expr_copy_392; + if( x.m_start && visit_expr_after_replacement ) + self().visit_expr(*x.m_start); + } + if (x.m_end) { + ASR::expr_t** current_expr_copy_393 = current_expr; + current_expr = const_cast(&(x.m_end)); + self().call_replacer(); + current_expr = current_expr_copy_393; + if( x.m_end && visit_expr_after_replacement ) + self().visit_expr(*x.m_end); + } + if (x.m_increment) { + ASR::expr_t** current_expr_copy_394 = current_expr; + current_expr = const_cast(&(x.m_increment)); + self().call_replacer(); + current_expr = current_expr_copy_394; + if( x.m_increment && visit_expr_after_replacement ) + self().visit_expr(*x.m_increment); + } + } + void visit_CaseStmt(const CaseStmt_t &x) { + CaseStmt_t& xx = const_cast(x); + for (size_t i=0; i(&(x.m_test[i])); + self().call_replacer(); + current_expr = current_expr_copy_395; + if( x.m_test[i] && visit_expr_after_replacement ) + self().visit_expr(*x.m_test[i]); + } + self().transform_stmts(xx.m_body, xx.n_body); + } + void visit_CaseStmt_Range(const CaseStmt_Range_t &x) { + CaseStmt_Range_t& xx = const_cast(x); + if (x.m_start) { + ASR::expr_t** current_expr_copy_396 = current_expr; + current_expr = const_cast(&(x.m_start)); + self().call_replacer(); + current_expr = current_expr_copy_396; + if( x.m_start && visit_expr_after_replacement ) + self().visit_expr(*x.m_start); + } + if (x.m_end) { + ASR::expr_t** current_expr_copy_397 = current_expr; + current_expr = const_cast(&(x.m_end)); + self().call_replacer(); + current_expr = current_expr_copy_397; + if( x.m_end && visit_expr_after_replacement ) + self().visit_expr(*x.m_end); + } + self().transform_stmts(xx.m_body, xx.n_body); + } + void visit_TypeStmtName(const TypeStmtName_t &x) { + TypeStmtName_t& xx = const_cast(x); + self().transform_stmts(xx.m_body, xx.n_body); + if ((bool&)x) { } // Suppress unused warning + } + void visit_ClassStmt(const ClassStmt_t &x) { + ClassStmt_t& xx = const_cast(x); + self().transform_stmts(xx.m_body, xx.n_body); + if ((bool&)x) { } // Suppress unused warning + } + void visit_TypeStmtType(const TypeStmtType_t &x) { + TypeStmtType_t& xx = const_cast(x); + self().visit_ttype(*x.m_type); + self().transform_stmts(xx.m_body, xx.n_body); + } + void visit_Require(const Require_t &x) { + if ((bool&)x) { } // Suppress unused warning + } +}; + + +} diff --git a/src/libasr/asr_expr_stmt_duplicator_visitor.h b/src/libasr/asr_expr_stmt_duplicator_visitor.h new file mode 100644 index 0000000000..c42a94b060 --- /dev/null +++ b/src/libasr/asr_expr_stmt_duplicator_visitor.h @@ -0,0 +1,2444 @@ +#pragma once + +// Generated by grammar/asdl_cpp.py + +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace LCompilers::ASR { +/******************************************************************************/ +// Expression and statement Duplicator class + +template +class BaseExprStmtDuplicator { +public: + StructType& self() { return static_cast(*this); } + + Allocator &al; + bool success; + bool allow_procedure_calls; + bool allow_reshape; + + BaseExprStmtDuplicator(Allocator& al_) : al(al_), success(false), allow_procedure_calls(true), allow_reshape(true) {} + + + ASR::asr_t* duplicate_Allocate(Allocate_t* x) { + Vec m_args; + m_args.reserve(al, x->n_args); + for (size_t i = 0; i < x->n_args; i++) { + ASR::alloc_arg_t alloc_arg_copy; + alloc_arg_copy.loc = x->m_args[i].loc; + alloc_arg_copy.m_a = self().duplicate_expr(x->m_args[i].m_a); + alloc_arg_copy.m_len_expr = self().duplicate_expr(x->m_args[i].m_len_expr); + alloc_arg_copy.m_type = self().duplicate_ttype(x->m_args[i].m_type); + alloc_arg_copy.n_dims = x->m_args[i].n_dims; + Vec dims_copy; + dims_copy.reserve(al, alloc_arg_copy.n_dims); + for (size_t j = 0; j < alloc_arg_copy.n_dims; j++) { + ASR::dimension_t dim_copy; + dim_copy.loc = x->m_args[i].m_dims[j].loc; + dim_copy.m_start = self().duplicate_expr(x->m_args[i].m_dims[j].m_start); + dim_copy.m_length = self().duplicate_expr(x->m_args[i].m_dims[j].m_length); + dims_copy.push_back(al, dim_copy); + } + alloc_arg_copy.m_dims = dims_copy.p; + m_args.push_back(al, alloc_arg_copy); + } + expr_t* m_stat = self().duplicate_expr(x->m_stat); + expr_t* m_errmsg = self().duplicate_expr(x->m_errmsg); + expr_t* m_source = self().duplicate_expr(x->m_source); + return make_Allocate_t(al, x->base.base.loc, m_args.p, x->n_args, m_stat, m_errmsg, m_source); + } + + + ASR::asr_t* duplicate_ReAlloc(ReAlloc_t* x) { + Vec m_args; + m_args.reserve(al, x->n_args); + for (size_t i = 0; i < x->n_args; i++) { + ASR::alloc_arg_t alloc_arg_copy; + alloc_arg_copy.loc = x->m_args[i].loc; + alloc_arg_copy.m_a = self().duplicate_expr(x->m_args[i].m_a); + alloc_arg_copy.m_len_expr = self().duplicate_expr(x->m_args[i].m_len_expr); + alloc_arg_copy.m_type = self().duplicate_ttype(x->m_args[i].m_type); + alloc_arg_copy.n_dims = x->m_args[i].n_dims; + Vec dims_copy; + dims_copy.reserve(al, alloc_arg_copy.n_dims); + for (size_t j = 0; j < alloc_arg_copy.n_dims; j++) { + ASR::dimension_t dim_copy; + dim_copy.loc = x->m_args[i].m_dims[j].loc; + dim_copy.m_start = self().duplicate_expr(x->m_args[i].m_dims[j].m_start); + dim_copy.m_length = self().duplicate_expr(x->m_args[i].m_dims[j].m_length); + dims_copy.push_back(al, dim_copy); + } + alloc_arg_copy.m_dims = dims_copy.p; + m_args.push_back(al, alloc_arg_copy); + } + return make_ReAlloc_t(al, x->base.base.loc, m_args.p, x->n_args); + } + + + ASR::asr_t* duplicate_Assign(Assign_t* x) { + return make_Assign_t(al, x->base.base.loc, x->m_label, x->m_variable); + } + + + ASR::asr_t* duplicate_Assignment(Assignment_t* x) { + expr_t* m_target = self().duplicate_expr(x->m_target); + expr_t* m_value = self().duplicate_expr(x->m_value); + stmt_t* m_overloaded = self().duplicate_stmt(x->m_overloaded); + return make_Assignment_t(al, x->base.base.loc, m_target, m_value, m_overloaded); + } + + + ASR::asr_t* duplicate_Associate(Associate_t* x) { + expr_t* m_target = self().duplicate_expr(x->m_target); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_Associate_t(al, x->base.base.loc, m_target, m_value); + } + + + ASR::asr_t* duplicate_Cycle(Cycle_t* x) { + return make_Cycle_t(al, x->base.base.loc, x->m_stmt_name); + } + + + ASR::asr_t* duplicate_ExplicitDeallocate(ExplicitDeallocate_t* x) { + Vec m_vars; + m_vars.reserve(al, x->n_vars); + for (size_t i = 0; i < x->n_vars; i++) { + m_vars.push_back(al, self().duplicate_expr(x->m_vars[i])); + } + return make_ExplicitDeallocate_t(al, x->base.base.loc, m_vars.p, x->n_vars); + } + + + ASR::asr_t* duplicate_ImplicitDeallocate(ImplicitDeallocate_t* x) { + Vec m_vars; + m_vars.reserve(al, x->n_vars); + for (size_t i = 0; i < x->n_vars; i++) { + m_vars.push_back(al, self().duplicate_expr(x->m_vars[i])); + } + return make_ImplicitDeallocate_t(al, x->base.base.loc, m_vars.p, x->n_vars); + } + + + ASR::asr_t* duplicate_DoConcurrentLoop(DoConcurrentLoop_t* x) { + Vec m_head; + m_head.reserve(al, x->n_head); + for (size_t i = 0; i < x->n_head; i++) { + ASR::do_loop_head_t head; + head.loc = x->m_head[i].loc; + head.m_v = duplicate_expr(x->m_head[i].m_v); + head.m_start = duplicate_expr(x->m_head[i].m_start); + head.m_end = duplicate_expr(x->m_head[i].m_end); + head.m_increment = duplicate_expr(x->m_head[i].m_increment); + m_head.push_back(al, head); + } + Vec m_shared; + m_shared.reserve(al, x->n_shared); + for (size_t i = 0; i < x->n_shared; i++) { + m_shared.push_back(al, self().duplicate_expr(x->m_shared[i])); + } + Vec m_local; + m_local.reserve(al, x->n_local); + for (size_t i = 0; i < x->n_local; i++) { + m_local.push_back(al, self().duplicate_expr(x->m_local[i])); + } + Vec m_body; + m_body.reserve(al, x->n_body); + for (size_t i = 0; i < x->n_body; i++) { + m_body.push_back(al, self().duplicate_stmt(x->m_body[i])); + } + return make_DoConcurrentLoop_t(al, x->base.base.loc, m_head.p, x->n_head, m_shared.p, x->n_shared, m_local.p, x->n_local, x->m_reduction, x->n_reduction, m_body.p, x->n_body); + } + + + ASR::asr_t* duplicate_DoLoop(DoLoop_t* x) { + ASR::do_loop_head_t m_head; + m_head.loc = x->m_head.loc; + m_head.m_v = duplicate_expr(x->m_head.m_v); + m_head.m_start = duplicate_expr(x->m_head.m_start); + m_head.m_end = duplicate_expr(x->m_head.m_end); + m_head.m_increment = duplicate_expr(x->m_head.m_increment); + Vec m_body; + m_body.reserve(al, x->n_body); + for (size_t i = 0; i < x->n_body; i++) { + m_body.push_back(al, self().duplicate_stmt(x->m_body[i])); + } + Vec m_orelse; + m_orelse.reserve(al, x->n_orelse); + for (size_t i = 0; i < x->n_orelse; i++) { + m_orelse.push_back(al, self().duplicate_stmt(x->m_orelse[i])); + } + return make_DoLoop_t(al, x->base.base.loc, x->m_name, m_head, m_body.p, x->n_body, m_orelse.p, x->n_orelse); + } + + + ASR::asr_t* duplicate_ErrorStop(ErrorStop_t* x) { + expr_t* m_code = self().duplicate_expr(x->m_code); + return make_ErrorStop_t(al, x->base.base.loc, m_code); + } + + + ASR::asr_t* duplicate_Exit(Exit_t* x) { + return make_Exit_t(al, x->base.base.loc, x->m_stmt_name); + } + + + ASR::asr_t* duplicate_ForAllSingle(ForAllSingle_t* x) { + ASR::do_loop_head_t m_head; + m_head.loc = x->m_head.loc; + m_head.m_v = duplicate_expr(x->m_head.m_v); + m_head.m_start = duplicate_expr(x->m_head.m_start); + m_head.m_end = duplicate_expr(x->m_head.m_end); + m_head.m_increment = duplicate_expr(x->m_head.m_increment); + stmt_t* m_assign_stmt = self().duplicate_stmt(x->m_assign_stmt); + return make_ForAllSingle_t(al, x->base.base.loc, m_head, m_assign_stmt); + } + + + ASR::asr_t* duplicate_ForEach(ForEach_t* x) { + expr_t* m_var = self().duplicate_expr(x->m_var); + expr_t* m_container = self().duplicate_expr(x->m_container); + Vec m_body; + m_body.reserve(al, x->n_body); + for (size_t i = 0; i < x->n_body; i++) { + m_body.push_back(al, self().duplicate_stmt(x->m_body[i])); + } + return make_ForEach_t(al, x->base.base.loc, m_var, m_container, m_body.p, x->n_body); + } + + + ASR::asr_t* duplicate_GoTo(GoTo_t* x) { + return make_GoTo_t(al, x->base.base.loc, x->m_target_id, x->m_name); + } + + + ASR::asr_t* duplicate_GoToTarget(GoToTarget_t* x) { + return make_GoToTarget_t(al, x->base.base.loc, x->m_id, x->m_name); + } + + + ASR::asr_t* duplicate_If(If_t* x) { + expr_t* m_test = self().duplicate_expr(x->m_test); + Vec m_body; + m_body.reserve(al, x->n_body); + for (size_t i = 0; i < x->n_body; i++) { + m_body.push_back(al, self().duplicate_stmt(x->m_body[i])); + } + Vec m_orelse; + m_orelse.reserve(al, x->n_orelse); + for (size_t i = 0; i < x->n_orelse; i++) { + m_orelse.push_back(al, self().duplicate_stmt(x->m_orelse[i])); + } + return make_If_t(al, x->base.base.loc, m_test, m_body.p, x->n_body, m_orelse.p, x->n_orelse); + } + + + ASR::asr_t* duplicate_IfArithmetic(IfArithmetic_t* x) { + expr_t* m_test = self().duplicate_expr(x->m_test); + return make_IfArithmetic_t(al, x->base.base.loc, m_test, x->m_lt_label, x->m_eq_label, x->m_gt_label); + } + + + ASR::asr_t* duplicate_Print(Print_t* x) { + expr_t* m_text = self().duplicate_expr(x->m_text); + return make_Print_t(al, x->base.base.loc, m_text); + } + + + ASR::asr_t* duplicate_FileOpen(FileOpen_t* x) { + expr_t* m_newunit = self().duplicate_expr(x->m_newunit); + expr_t* m_filename = self().duplicate_expr(x->m_filename); + expr_t* m_status = self().duplicate_expr(x->m_status); + expr_t* m_form = self().duplicate_expr(x->m_form); + return make_FileOpen_t(al, x->base.base.loc, x->m_label, m_newunit, m_filename, m_status, m_form); + } + + + ASR::asr_t* duplicate_FileClose(FileClose_t* x) { + expr_t* m_unit = self().duplicate_expr(x->m_unit); + expr_t* m_iostat = self().duplicate_expr(x->m_iostat); + expr_t* m_iomsg = self().duplicate_expr(x->m_iomsg); + expr_t* m_err = self().duplicate_expr(x->m_err); + expr_t* m_status = self().duplicate_expr(x->m_status); + return make_FileClose_t(al, x->base.base.loc, x->m_label, m_unit, m_iostat, m_iomsg, m_err, m_status); + } + + + ASR::asr_t* duplicate_FileRead(FileRead_t* x) { + expr_t* m_unit = self().duplicate_expr(x->m_unit); + expr_t* m_fmt = self().duplicate_expr(x->m_fmt); + expr_t* m_iomsg = self().duplicate_expr(x->m_iomsg); + expr_t* m_iostat = self().duplicate_expr(x->m_iostat); + expr_t* m_size = self().duplicate_expr(x->m_size); + expr_t* m_id = self().duplicate_expr(x->m_id); + Vec m_values; + m_values.reserve(al, x->n_values); + for (size_t i = 0; i < x->n_values; i++) { + m_values.push_back(al, self().duplicate_expr(x->m_values[i])); + } + stmt_t* m_overloaded = self().duplicate_stmt(x->m_overloaded); + return make_FileRead_t(al, x->base.base.loc, x->m_label, m_unit, m_fmt, m_iomsg, m_iostat, m_size, m_id, m_values.p, x->n_values, m_overloaded); + } + + + ASR::asr_t* duplicate_FileBackspace(FileBackspace_t* x) { + expr_t* m_unit = self().duplicate_expr(x->m_unit); + expr_t* m_iostat = self().duplicate_expr(x->m_iostat); + expr_t* m_err = self().duplicate_expr(x->m_err); + return make_FileBackspace_t(al, x->base.base.loc, x->m_label, m_unit, m_iostat, m_err); + } + + + ASR::asr_t* duplicate_FileRewind(FileRewind_t* x) { + expr_t* m_unit = self().duplicate_expr(x->m_unit); + expr_t* m_iostat = self().duplicate_expr(x->m_iostat); + expr_t* m_err = self().duplicate_expr(x->m_err); + return make_FileRewind_t(al, x->base.base.loc, x->m_label, m_unit, m_iostat, m_err); + } + + + ASR::asr_t* duplicate_FileInquire(FileInquire_t* x) { + expr_t* m_unit = self().duplicate_expr(x->m_unit); + expr_t* m_file = self().duplicate_expr(x->m_file); + expr_t* m_iostat = self().duplicate_expr(x->m_iostat); + expr_t* m_err = self().duplicate_expr(x->m_err); + expr_t* m_exist = self().duplicate_expr(x->m_exist); + expr_t* m_opened = self().duplicate_expr(x->m_opened); + expr_t* m_number = self().duplicate_expr(x->m_number); + expr_t* m_named = self().duplicate_expr(x->m_named); + expr_t* m_name = self().duplicate_expr(x->m_name); + expr_t* m_access = self().duplicate_expr(x->m_access); + expr_t* m_sequential = self().duplicate_expr(x->m_sequential); + expr_t* m_direct = self().duplicate_expr(x->m_direct); + expr_t* m_form = self().duplicate_expr(x->m_form); + expr_t* m_formatted = self().duplicate_expr(x->m_formatted); + expr_t* m_unformatted = self().duplicate_expr(x->m_unformatted); + expr_t* m_recl = self().duplicate_expr(x->m_recl); + expr_t* m_nextrec = self().duplicate_expr(x->m_nextrec); + expr_t* m_blank = self().duplicate_expr(x->m_blank); + expr_t* m_position = self().duplicate_expr(x->m_position); + expr_t* m_action = self().duplicate_expr(x->m_action); + expr_t* m_read = self().duplicate_expr(x->m_read); + expr_t* m_write = self().duplicate_expr(x->m_write); + expr_t* m_readwrite = self().duplicate_expr(x->m_readwrite); + expr_t* m_delim = self().duplicate_expr(x->m_delim); + expr_t* m_pad = self().duplicate_expr(x->m_pad); + expr_t* m_flen = self().duplicate_expr(x->m_flen); + expr_t* m_blocksize = self().duplicate_expr(x->m_blocksize); + expr_t* m_convert = self().duplicate_expr(x->m_convert); + expr_t* m_carriagecontrol = self().duplicate_expr(x->m_carriagecontrol); + expr_t* m_size = self().duplicate_expr(x->m_size); + expr_t* m_iolength = self().duplicate_expr(x->m_iolength); + return make_FileInquire_t(al, x->base.base.loc, x->m_label, m_unit, m_file, m_iostat, m_err, m_exist, m_opened, m_number, m_named, m_name, m_access, m_sequential, m_direct, m_form, m_formatted, m_unformatted, m_recl, m_nextrec, m_blank, m_position, m_action, m_read, m_write, m_readwrite, m_delim, m_pad, m_flen, m_blocksize, m_convert, m_carriagecontrol, m_size, m_iolength); + } + + + ASR::asr_t* duplicate_FileWrite(FileWrite_t* x) { + expr_t* m_unit = self().duplicate_expr(x->m_unit); + expr_t* m_iomsg = self().duplicate_expr(x->m_iomsg); + expr_t* m_iostat = self().duplicate_expr(x->m_iostat); + expr_t* m_id = self().duplicate_expr(x->m_id); + Vec m_values; + m_values.reserve(al, x->n_values); + for (size_t i = 0; i < x->n_values; i++) { + m_values.push_back(al, self().duplicate_expr(x->m_values[i])); + } + expr_t* m_separator = self().duplicate_expr(x->m_separator); + expr_t* m_end = self().duplicate_expr(x->m_end); + stmt_t* m_overloaded = self().duplicate_stmt(x->m_overloaded); + return make_FileWrite_t(al, x->base.base.loc, x->m_label, m_unit, m_iomsg, m_iostat, m_id, m_values.p, x->n_values, m_separator, m_end, m_overloaded); + } + + + ASR::asr_t* duplicate_Return(Return_t* x) { + return make_Return_t(al, x->base.base.loc); + } + + + ASR::asr_t* duplicate_Select(Select_t* x) { + expr_t* m_test = self().duplicate_expr(x->m_test); + Vec m_body; + m_body.reserve(al, x->n_body); + for (size_t i = 0; i < x->n_body; i++) { + m_body.push_back(al, self().duplicate_case_stmt(x->m_body[i])); + } + Vec m_default; + m_default.reserve(al, x->n_default); + for (size_t i = 0; i < x->n_default; i++) { + m_default.push_back(al, self().duplicate_stmt(x->m_default[i])); + } + return make_Select_t(al, x->base.base.loc, m_test, m_body.p, x->n_body, m_default.p, x->n_default, x->m_enable_fall_through); + } + + + ASR::asr_t* duplicate_Stop(Stop_t* x) { + expr_t* m_code = self().duplicate_expr(x->m_code); + return make_Stop_t(al, x->base.base.loc, m_code); + } + + + ASR::asr_t* duplicate_Assert(Assert_t* x) { + expr_t* m_test = self().duplicate_expr(x->m_test); + expr_t* m_msg = self().duplicate_expr(x->m_msg); + return make_Assert_t(al, x->base.base.loc, m_test, m_msg); + } + + + ASR::asr_t* duplicate_SubroutineCall(SubroutineCall_t* x) { + symbol_t* m_name = x->m_name; + symbol_t* m_original_name = x->m_original_name; + Vec m_args; + m_args.reserve(al, x->n_args); + for (size_t i = 0; i < x->n_args; i++) { + ASR::call_arg_t call_arg_copy; + call_arg_copy.loc = x->m_args[i].loc; + call_arg_copy.m_value = self().duplicate_expr(x->m_args[i].m_value); + m_args.push_back(al, call_arg_copy); + } + expr_t* m_dt = self().duplicate_expr(x->m_dt); + return make_SubroutineCall_t(al, x->base.base.loc, m_name, m_original_name, m_args.p, x->n_args, m_dt); + } + + + ASR::asr_t* duplicate_IntrinsicImpureSubroutine(IntrinsicImpureSubroutine_t* x) { + Vec m_args; + m_args.reserve(al, x->n_args); + for (size_t i = 0; i < x->n_args; i++) { + m_args.push_back(al, self().duplicate_expr(x->m_args[i])); + } + return make_IntrinsicImpureSubroutine_t(al, x->base.base.loc, x->m_sub_intrinsic_id, m_args.p, x->n_args, x->m_overload_id); + } + + + ASR::asr_t* duplicate_Where(Where_t* x) { + expr_t* m_test = self().duplicate_expr(x->m_test); + Vec m_body; + m_body.reserve(al, x->n_body); + for (size_t i = 0; i < x->n_body; i++) { + m_body.push_back(al, self().duplicate_stmt(x->m_body[i])); + } + Vec m_orelse; + m_orelse.reserve(al, x->n_orelse); + for (size_t i = 0; i < x->n_orelse; i++) { + m_orelse.push_back(al, self().duplicate_stmt(x->m_orelse[i])); + } + return make_Where_t(al, x->base.base.loc, m_test, m_body.p, x->n_body, m_orelse.p, x->n_orelse); + } + + + ASR::asr_t* duplicate_WhileLoop(WhileLoop_t* x) { + expr_t* m_test = self().duplicate_expr(x->m_test); + Vec m_body; + m_body.reserve(al, x->n_body); + for (size_t i = 0; i < x->n_body; i++) { + m_body.push_back(al, self().duplicate_stmt(x->m_body[i])); + } + Vec m_orelse; + m_orelse.reserve(al, x->n_orelse); + for (size_t i = 0; i < x->n_orelse; i++) { + m_orelse.push_back(al, self().duplicate_stmt(x->m_orelse[i])); + } + return make_WhileLoop_t(al, x->base.base.loc, x->m_name, m_test, m_body.p, x->n_body, m_orelse.p, x->n_orelse); + } + + + ASR::asr_t* duplicate_Nullify(Nullify_t* x) { + Vec m_vars; + m_vars.reserve(al, x->n_vars); + for (size_t i = 0; i < x->n_vars; i++) { + m_vars.push_back(al, self().duplicate_expr(x->m_vars[i])); + } + return make_Nullify_t(al, x->base.base.loc, m_vars.p, x->n_vars); + } + + + ASR::asr_t* duplicate_Flush(Flush_t* x) { + expr_t* m_unit = self().duplicate_expr(x->m_unit); + expr_t* m_err = self().duplicate_expr(x->m_err); + expr_t* m_iomsg = self().duplicate_expr(x->m_iomsg); + expr_t* m_iostat = self().duplicate_expr(x->m_iostat); + return make_Flush_t(al, x->base.base.loc, x->m_label, m_unit, m_err, m_iomsg, m_iostat); + } + + + ASR::asr_t* duplicate_ListAppend(ListAppend_t* x) { + expr_t* m_a = self().duplicate_expr(x->m_a); + expr_t* m_ele = self().duplicate_expr(x->m_ele); + return make_ListAppend_t(al, x->base.base.loc, m_a, m_ele); + } + + + ASR::asr_t* duplicate_AssociateBlockCall(AssociateBlockCall_t* x) { + symbol_t* m_m = x->m_m; + return make_AssociateBlockCall_t(al, x->base.base.loc, m_m); + } + + + ASR::asr_t* duplicate_SelectType(SelectType_t* x) { + expr_t* m_selector = self().duplicate_expr(x->m_selector); + Vec m_default; + m_default.reserve(al, x->n_default); + for (size_t i = 0; i < x->n_default; i++) { + m_default.push_back(al, self().duplicate_stmt(x->m_default[i])); + } + return make_SelectType_t(al, x->base.base.loc, m_selector, x->m_body, x->n_body, m_default.p, x->n_default); + } + + + ASR::asr_t* duplicate_CPtrToPointer(CPtrToPointer_t* x) { + expr_t* m_cptr = self().duplicate_expr(x->m_cptr); + expr_t* m_ptr = self().duplicate_expr(x->m_ptr); + expr_t* m_shape = self().duplicate_expr(x->m_shape); + expr_t* m_lower_bounds = self().duplicate_expr(x->m_lower_bounds); + return make_CPtrToPointer_t(al, x->base.base.loc, m_cptr, m_ptr, m_shape, m_lower_bounds); + } + + + ASR::asr_t* duplicate_BlockCall(BlockCall_t* x) { + symbol_t* m_m = x->m_m; + return make_BlockCall_t(al, x->base.base.loc, x->m_label, m_m); + } + + + ASR::asr_t* duplicate_SetInsert(SetInsert_t* x) { + expr_t* m_a = self().duplicate_expr(x->m_a); + expr_t* m_ele = self().duplicate_expr(x->m_ele); + return make_SetInsert_t(al, x->base.base.loc, m_a, m_ele); + } + + + ASR::asr_t* duplicate_SetRemove(SetRemove_t* x) { + expr_t* m_a = self().duplicate_expr(x->m_a); + expr_t* m_ele = self().duplicate_expr(x->m_ele); + return make_SetRemove_t(al, x->base.base.loc, m_a, m_ele); + } + + + ASR::asr_t* duplicate_SetDiscard(SetDiscard_t* x) { + expr_t* m_a = self().duplicate_expr(x->m_a); + expr_t* m_ele = self().duplicate_expr(x->m_ele); + return make_SetDiscard_t(al, x->base.base.loc, m_a, m_ele); + } + + + ASR::asr_t* duplicate_ListInsert(ListInsert_t* x) { + expr_t* m_a = self().duplicate_expr(x->m_a); + expr_t* m_pos = self().duplicate_expr(x->m_pos); + expr_t* m_ele = self().duplicate_expr(x->m_ele); + return make_ListInsert_t(al, x->base.base.loc, m_a, m_pos, m_ele); + } + + + ASR::asr_t* duplicate_ListRemove(ListRemove_t* x) { + expr_t* m_a = self().duplicate_expr(x->m_a); + expr_t* m_ele = self().duplicate_expr(x->m_ele); + return make_ListRemove_t(al, x->base.base.loc, m_a, m_ele); + } + + + ASR::asr_t* duplicate_ListClear(ListClear_t* x) { + expr_t* m_a = self().duplicate_expr(x->m_a); + return make_ListClear_t(al, x->base.base.loc, m_a); + } + + + ASR::asr_t* duplicate_DictInsert(DictInsert_t* x) { + expr_t* m_a = self().duplicate_expr(x->m_a); + expr_t* m_key = self().duplicate_expr(x->m_key); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_DictInsert_t(al, x->base.base.loc, m_a, m_key, m_value); + } + + + ASR::asr_t* duplicate_DictClear(DictClear_t* x) { + expr_t* m_a = self().duplicate_expr(x->m_a); + return make_DictClear_t(al, x->base.base.loc, m_a); + } + + + ASR::asr_t* duplicate_SetClear(SetClear_t* x) { + expr_t* m_a = self().duplicate_expr(x->m_a); + return make_SetClear_t(al, x->base.base.loc, m_a); + } + + + ASR::asr_t* duplicate_Expr(Expr_t* x) { + expr_t* m_expression = self().duplicate_expr(x->m_expression); + return make_Expr_t(al, x->base.base.loc, m_expression); + } + + + ASR::asr_t* duplicate_IfExp(IfExp_t* x) { + expr_t* m_test = self().duplicate_expr(x->m_test); + expr_t* m_body = self().duplicate_expr(x->m_body); + expr_t* m_orelse = self().duplicate_expr(x->m_orelse); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_IfExp_t(al, x->base.base.loc, m_test, m_body, m_orelse, m_type, m_value); + } + + + ASR::asr_t* duplicate_ComplexConstructor(ComplexConstructor_t* x) { + expr_t* m_re = self().duplicate_expr(x->m_re); + expr_t* m_im = self().duplicate_expr(x->m_im); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_ComplexConstructor_t(al, x->base.base.loc, m_re, m_im, m_type, m_value); + } + + + ASR::asr_t* duplicate_NamedExpr(NamedExpr_t* x) { + expr_t* m_target = self().duplicate_expr(x->m_target); + expr_t* m_value = self().duplicate_expr(x->m_value); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + return make_NamedExpr_t(al, x->base.base.loc, m_target, m_value, m_type); + } + + + ASR::asr_t* duplicate_FunctionCall(FunctionCall_t* x) { + symbol_t* m_name = x->m_name; + symbol_t* m_original_name = x->m_original_name; + Vec m_args; + m_args.reserve(al, x->n_args); + for (size_t i = 0; i < x->n_args; i++) { + ASR::call_arg_t call_arg_copy; + call_arg_copy.loc = x->m_args[i].loc; + call_arg_copy.m_value = self().duplicate_expr(x->m_args[i].m_value); + m_args.push_back(al, call_arg_copy); + } + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + expr_t* m_dt = self().duplicate_expr(x->m_dt); + return make_FunctionCall_t(al, x->base.base.loc, m_name, m_original_name, m_args.p, x->n_args, m_type, m_value, m_dt); + } + + + ASR::asr_t* duplicate_IntrinsicElementalFunction(IntrinsicElementalFunction_t* x) { + Vec m_args; + m_args.reserve(al, x->n_args); + for (size_t i = 0; i < x->n_args; i++) { + m_args.push_back(al, self().duplicate_expr(x->m_args[i])); + } + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_IntrinsicElementalFunction_t(al, x->base.base.loc, x->m_intrinsic_id, m_args.p, x->n_args, x->m_overload_id, m_type, m_value); + } + + + ASR::asr_t* duplicate_IntrinsicArrayFunction(IntrinsicArrayFunction_t* x) { + Vec m_args; + m_args.reserve(al, x->n_args); + for (size_t i = 0; i < x->n_args; i++) { + m_args.push_back(al, self().duplicate_expr(x->m_args[i])); + } + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_IntrinsicArrayFunction_t(al, x->base.base.loc, x->m_arr_intrinsic_id, m_args.p, x->n_args, x->m_overload_id, m_type, m_value); + } + + + ASR::asr_t* duplicate_IntrinsicImpureFunction(IntrinsicImpureFunction_t* x) { + Vec m_args; + m_args.reserve(al, x->n_args); + for (size_t i = 0; i < x->n_args; i++) { + m_args.push_back(al, self().duplicate_expr(x->m_args[i])); + } + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_IntrinsicImpureFunction_t(al, x->base.base.loc, x->m_impure_intrinsic_id, m_args.p, x->n_args, x->m_overload_id, m_type, m_value); + } + + + ASR::asr_t* duplicate_TypeInquiry(TypeInquiry_t* x) { + ttype_t* m_arg_type = self().duplicate_ttype(x->m_arg_type); + expr_t* m_arg = self().duplicate_expr(x->m_arg); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_TypeInquiry_t(al, x->base.base.loc, x->m_inquiry_id, m_arg_type, m_arg, m_type, m_value); + } + + + ASR::asr_t* duplicate_StructConstructor(StructConstructor_t* x) { + symbol_t* m_dt_sym = x->m_dt_sym; + Vec m_args; + m_args.reserve(al, x->n_args); + for (size_t i = 0; i < x->n_args; i++) { + ASR::call_arg_t call_arg_copy; + call_arg_copy.loc = x->m_args[i].loc; + call_arg_copy.m_value = self().duplicate_expr(x->m_args[i].m_value); + m_args.push_back(al, call_arg_copy); + } + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_StructConstructor_t(al, x->base.base.loc, m_dt_sym, m_args.p, x->n_args, m_type, m_value); + } + + + ASR::asr_t* duplicate_StructConstant(StructConstant_t* x) { + symbol_t* m_dt_sym = x->m_dt_sym; + Vec m_args; + m_args.reserve(al, x->n_args); + for (size_t i = 0; i < x->n_args; i++) { + ASR::call_arg_t call_arg_copy; + call_arg_copy.loc = x->m_args[i].loc; + call_arg_copy.m_value = self().duplicate_expr(x->m_args[i].m_value); + m_args.push_back(al, call_arg_copy); + } + ttype_t* m_type = self().duplicate_ttype(x->m_type); + return make_StructConstant_t(al, x->base.base.loc, m_dt_sym, m_args.p, x->n_args, m_type); + } + + + ASR::asr_t* duplicate_EnumConstructor(EnumConstructor_t* x) { + symbol_t* m_dt_sym = x->m_dt_sym; + Vec m_args; + m_args.reserve(al, x->n_args); + for (size_t i = 0; i < x->n_args; i++) { + m_args.push_back(al, self().duplicate_expr(x->m_args[i])); + } + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_EnumConstructor_t(al, x->base.base.loc, m_dt_sym, m_args.p, x->n_args, m_type, m_value); + } + + + ASR::asr_t* duplicate_UnionConstructor(UnionConstructor_t* x) { + symbol_t* m_dt_sym = x->m_dt_sym; + Vec m_args; + m_args.reserve(al, x->n_args); + for (size_t i = 0; i < x->n_args; i++) { + m_args.push_back(al, self().duplicate_expr(x->m_args[i])); + } + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_UnionConstructor_t(al, x->base.base.loc, m_dt_sym, m_args.p, x->n_args, m_type, m_value); + } + + + ASR::asr_t* duplicate_ImpliedDoLoop(ImpliedDoLoop_t* x) { + Vec m_values; + m_values.reserve(al, x->n_values); + for (size_t i = 0; i < x->n_values; i++) { + m_values.push_back(al, self().duplicate_expr(x->m_values[i])); + } + expr_t* m_var = self().duplicate_expr(x->m_var); + expr_t* m_start = self().duplicate_expr(x->m_start); + expr_t* m_end = self().duplicate_expr(x->m_end); + expr_t* m_increment = self().duplicate_expr(x->m_increment); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_ImpliedDoLoop_t(al, x->base.base.loc, m_values.p, x->n_values, m_var, m_start, m_end, m_increment, m_type, m_value); + } + + + ASR::asr_t* duplicate_IntegerConstant(IntegerConstant_t* x) { + ttype_t* m_type = self().duplicate_ttype(x->m_type); + return make_IntegerConstant_t(al, x->base.base.loc, x->m_n, m_type, x->m_intboz_type); + } + + + ASR::asr_t* duplicate_IntegerBitNot(IntegerBitNot_t* x) { + expr_t* m_arg = self().duplicate_expr(x->m_arg); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_IntegerBitNot_t(al, x->base.base.loc, m_arg, m_type, m_value); + } + + + ASR::asr_t* duplicate_IntegerUnaryMinus(IntegerUnaryMinus_t* x) { + expr_t* m_arg = self().duplicate_expr(x->m_arg); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_IntegerUnaryMinus_t(al, x->base.base.loc, m_arg, m_type, m_value); + } + + + ASR::asr_t* duplicate_IntegerCompare(IntegerCompare_t* x) { + expr_t* m_left = self().duplicate_expr(x->m_left); + expr_t* m_right = self().duplicate_expr(x->m_right); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_IntegerCompare_t(al, x->base.base.loc, m_left, x->m_op, m_right, m_type, m_value); + } + + + ASR::asr_t* duplicate_IntegerBinOp(IntegerBinOp_t* x) { + expr_t* m_left = self().duplicate_expr(x->m_left); + expr_t* m_right = self().duplicate_expr(x->m_right); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_IntegerBinOp_t(al, x->base.base.loc, m_left, x->m_op, m_right, m_type, m_value); + } + + + ASR::asr_t* duplicate_UnsignedIntegerConstant(UnsignedIntegerConstant_t* x) { + ttype_t* m_type = self().duplicate_ttype(x->m_type); + return make_UnsignedIntegerConstant_t(al, x->base.base.loc, x->m_n, m_type); + } + + + ASR::asr_t* duplicate_UnsignedIntegerUnaryMinus(UnsignedIntegerUnaryMinus_t* x) { + expr_t* m_arg = self().duplicate_expr(x->m_arg); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_UnsignedIntegerUnaryMinus_t(al, x->base.base.loc, m_arg, m_type, m_value); + } + + + ASR::asr_t* duplicate_UnsignedIntegerBitNot(UnsignedIntegerBitNot_t* x) { + expr_t* m_arg = self().duplicate_expr(x->m_arg); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_UnsignedIntegerBitNot_t(al, x->base.base.loc, m_arg, m_type, m_value); + } + + + ASR::asr_t* duplicate_UnsignedIntegerCompare(UnsignedIntegerCompare_t* x) { + expr_t* m_left = self().duplicate_expr(x->m_left); + expr_t* m_right = self().duplicate_expr(x->m_right); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_UnsignedIntegerCompare_t(al, x->base.base.loc, m_left, x->m_op, m_right, m_type, m_value); + } + + + ASR::asr_t* duplicate_UnsignedIntegerBinOp(UnsignedIntegerBinOp_t* x) { + expr_t* m_left = self().duplicate_expr(x->m_left); + expr_t* m_right = self().duplicate_expr(x->m_right); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_UnsignedIntegerBinOp_t(al, x->base.base.loc, m_left, x->m_op, m_right, m_type, m_value); + } + + + ASR::asr_t* duplicate_RealConstant(RealConstant_t* x) { + ttype_t* m_type = self().duplicate_ttype(x->m_type); + return make_RealConstant_t(al, x->base.base.loc, x->m_r, m_type); + } + + + ASR::asr_t* duplicate_RealUnaryMinus(RealUnaryMinus_t* x) { + expr_t* m_arg = self().duplicate_expr(x->m_arg); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_RealUnaryMinus_t(al, x->base.base.loc, m_arg, m_type, m_value); + } + + + ASR::asr_t* duplicate_RealCompare(RealCompare_t* x) { + expr_t* m_left = self().duplicate_expr(x->m_left); + expr_t* m_right = self().duplicate_expr(x->m_right); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_RealCompare_t(al, x->base.base.loc, m_left, x->m_op, m_right, m_type, m_value); + } + + + ASR::asr_t* duplicate_RealBinOp(RealBinOp_t* x) { + expr_t* m_left = self().duplicate_expr(x->m_left); + expr_t* m_right = self().duplicate_expr(x->m_right); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_RealBinOp_t(al, x->base.base.loc, m_left, x->m_op, m_right, m_type, m_value); + } + + + ASR::asr_t* duplicate_RealCopySign(RealCopySign_t* x) { + expr_t* m_target = self().duplicate_expr(x->m_target); + expr_t* m_source = self().duplicate_expr(x->m_source); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_RealCopySign_t(al, x->base.base.loc, m_target, m_source, m_type, m_value); + } + + + ASR::asr_t* duplicate_ComplexConstant(ComplexConstant_t* x) { + ttype_t* m_type = self().duplicate_ttype(x->m_type); + return make_ComplexConstant_t(al, x->base.base.loc, x->m_re, x->m_im, m_type); + } + + + ASR::asr_t* duplicate_ComplexUnaryMinus(ComplexUnaryMinus_t* x) { + expr_t* m_arg = self().duplicate_expr(x->m_arg); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_ComplexUnaryMinus_t(al, x->base.base.loc, m_arg, m_type, m_value); + } + + + ASR::asr_t* duplicate_ComplexCompare(ComplexCompare_t* x) { + expr_t* m_left = self().duplicate_expr(x->m_left); + expr_t* m_right = self().duplicate_expr(x->m_right); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_ComplexCompare_t(al, x->base.base.loc, m_left, x->m_op, m_right, m_type, m_value); + } + + + ASR::asr_t* duplicate_ComplexBinOp(ComplexBinOp_t* x) { + expr_t* m_left = self().duplicate_expr(x->m_left); + expr_t* m_right = self().duplicate_expr(x->m_right); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_ComplexBinOp_t(al, x->base.base.loc, m_left, x->m_op, m_right, m_type, m_value); + } + + + ASR::asr_t* duplicate_LogicalConstant(LogicalConstant_t* x) { + ttype_t* m_type = self().duplicate_ttype(x->m_type); + return make_LogicalConstant_t(al, x->base.base.loc, x->m_value, m_type); + } + + + ASR::asr_t* duplicate_LogicalNot(LogicalNot_t* x) { + expr_t* m_arg = self().duplicate_expr(x->m_arg); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_LogicalNot_t(al, x->base.base.loc, m_arg, m_type, m_value); + } + + + ASR::asr_t* duplicate_LogicalCompare(LogicalCompare_t* x) { + expr_t* m_left = self().duplicate_expr(x->m_left); + expr_t* m_right = self().duplicate_expr(x->m_right); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_LogicalCompare_t(al, x->base.base.loc, m_left, x->m_op, m_right, m_type, m_value); + } + + + ASR::asr_t* duplicate_LogicalBinOp(LogicalBinOp_t* x) { + expr_t* m_left = self().duplicate_expr(x->m_left); + expr_t* m_right = self().duplicate_expr(x->m_right); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_LogicalBinOp_t(al, x->base.base.loc, m_left, x->m_op, m_right, m_type, m_value); + } + + + ASR::asr_t* duplicate_ListConstant(ListConstant_t* x) { + Vec m_args; + m_args.reserve(al, x->n_args); + for (size_t i = 0; i < x->n_args; i++) { + m_args.push_back(al, self().duplicate_expr(x->m_args[i])); + } + ttype_t* m_type = self().duplicate_ttype(x->m_type); + return make_ListConstant_t(al, x->base.base.loc, m_args.p, x->n_args, m_type); + } + + + ASR::asr_t* duplicate_ListLen(ListLen_t* x) { + expr_t* m_arg = self().duplicate_expr(x->m_arg); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_ListLen_t(al, x->base.base.loc, m_arg, m_type, m_value); + } + + + ASR::asr_t* duplicate_ListConcat(ListConcat_t* x) { + expr_t* m_left = self().duplicate_expr(x->m_left); + expr_t* m_right = self().duplicate_expr(x->m_right); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_ListConcat_t(al, x->base.base.loc, m_left, m_right, m_type, m_value); + } + + + ASR::asr_t* duplicate_ListCompare(ListCompare_t* x) { + expr_t* m_left = self().duplicate_expr(x->m_left); + expr_t* m_right = self().duplicate_expr(x->m_right); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_ListCompare_t(al, x->base.base.loc, m_left, x->m_op, m_right, m_type, m_value); + } + + + ASR::asr_t* duplicate_ListCount(ListCount_t* x) { + expr_t* m_arg = self().duplicate_expr(x->m_arg); + expr_t* m_ele = self().duplicate_expr(x->m_ele); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_ListCount_t(al, x->base.base.loc, m_arg, m_ele, m_type, m_value); + } + + + ASR::asr_t* duplicate_ListContains(ListContains_t* x) { + expr_t* m_left = self().duplicate_expr(x->m_left); + expr_t* m_right = self().duplicate_expr(x->m_right); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_ListContains_t(al, x->base.base.loc, m_left, m_right, m_type, m_value); + } + + + ASR::asr_t* duplicate_SetConstant(SetConstant_t* x) { + Vec m_elements; + m_elements.reserve(al, x->n_elements); + for (size_t i = 0; i < x->n_elements; i++) { + m_elements.push_back(al, self().duplicate_expr(x->m_elements[i])); + } + ttype_t* m_type = self().duplicate_ttype(x->m_type); + return make_SetConstant_t(al, x->base.base.loc, m_elements.p, x->n_elements, m_type); + } + + + ASR::asr_t* duplicate_SetLen(SetLen_t* x) { + expr_t* m_arg = self().duplicate_expr(x->m_arg); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_SetLen_t(al, x->base.base.loc, m_arg, m_type, m_value); + } + + + ASR::asr_t* duplicate_TupleConstant(TupleConstant_t* x) { + Vec m_elements; + m_elements.reserve(al, x->n_elements); + for (size_t i = 0; i < x->n_elements; i++) { + m_elements.push_back(al, self().duplicate_expr(x->m_elements[i])); + } + ttype_t* m_type = self().duplicate_ttype(x->m_type); + return make_TupleConstant_t(al, x->base.base.loc, m_elements.p, x->n_elements, m_type); + } + + + ASR::asr_t* duplicate_TupleLen(TupleLen_t* x) { + expr_t* m_arg = self().duplicate_expr(x->m_arg); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_TupleLen_t(al, x->base.base.loc, m_arg, m_type, m_value); + } + + + ASR::asr_t* duplicate_TupleCompare(TupleCompare_t* x) { + expr_t* m_left = self().duplicate_expr(x->m_left); + expr_t* m_right = self().duplicate_expr(x->m_right); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_TupleCompare_t(al, x->base.base.loc, m_left, x->m_op, m_right, m_type, m_value); + } + + + ASR::asr_t* duplicate_TupleConcat(TupleConcat_t* x) { + expr_t* m_left = self().duplicate_expr(x->m_left); + expr_t* m_right = self().duplicate_expr(x->m_right); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_TupleConcat_t(al, x->base.base.loc, m_left, m_right, m_type, m_value); + } + + + ASR::asr_t* duplicate_TupleContains(TupleContains_t* x) { + expr_t* m_left = self().duplicate_expr(x->m_left); + expr_t* m_right = self().duplicate_expr(x->m_right); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_TupleContains_t(al, x->base.base.loc, m_left, m_right, m_type, m_value); + } + + + ASR::asr_t* duplicate_StringConstant(StringConstant_t* x) { + ttype_t* m_type = self().duplicate_ttype(x->m_type); + return make_StringConstant_t(al, x->base.base.loc, x->m_s, m_type); + } + + + ASR::asr_t* duplicate_StringConcat(StringConcat_t* x) { + expr_t* m_left = self().duplicate_expr(x->m_left); + expr_t* m_right = self().duplicate_expr(x->m_right); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_StringConcat_t(al, x->base.base.loc, m_left, m_right, m_type, m_value); + } + + + ASR::asr_t* duplicate_StringRepeat(StringRepeat_t* x) { + expr_t* m_left = self().duplicate_expr(x->m_left); + expr_t* m_right = self().duplicate_expr(x->m_right); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_StringRepeat_t(al, x->base.base.loc, m_left, m_right, m_type, m_value); + } + + + ASR::asr_t* duplicate_StringLen(StringLen_t* x) { + expr_t* m_arg = self().duplicate_expr(x->m_arg); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_StringLen_t(al, x->base.base.loc, m_arg, m_type, m_value); + } + + + ASR::asr_t* duplicate_StringItem(StringItem_t* x) { + expr_t* m_arg = self().duplicate_expr(x->m_arg); + expr_t* m_idx = self().duplicate_expr(x->m_idx); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_StringItem_t(al, x->base.base.loc, m_arg, m_idx, m_type, m_value); + } + + + ASR::asr_t* duplicate_StringSection(StringSection_t* x) { + expr_t* m_arg = self().duplicate_expr(x->m_arg); + expr_t* m_start = self().duplicate_expr(x->m_start); + expr_t* m_end = self().duplicate_expr(x->m_end); + expr_t* m_step = self().duplicate_expr(x->m_step); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_StringSection_t(al, x->base.base.loc, m_arg, m_start, m_end, m_step, m_type, m_value); + } + + + ASR::asr_t* duplicate_StringCompare(StringCompare_t* x) { + expr_t* m_left = self().duplicate_expr(x->m_left); + expr_t* m_right = self().duplicate_expr(x->m_right); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_StringCompare_t(al, x->base.base.loc, m_left, x->m_op, m_right, m_type, m_value); + } + + + ASR::asr_t* duplicate_StringContains(StringContains_t* x) { + expr_t* m_substr = self().duplicate_expr(x->m_substr); + expr_t* m_str = self().duplicate_expr(x->m_str); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_StringContains_t(al, x->base.base.loc, m_substr, m_str, m_type, m_value); + } + + + ASR::asr_t* duplicate_StringOrd(StringOrd_t* x) { + expr_t* m_arg = self().duplicate_expr(x->m_arg); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_StringOrd_t(al, x->base.base.loc, m_arg, m_type, m_value); + } + + + ASR::asr_t* duplicate_StringChr(StringChr_t* x) { + expr_t* m_arg = self().duplicate_expr(x->m_arg); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_StringChr_t(al, x->base.base.loc, m_arg, m_type, m_value); + } + + + ASR::asr_t* duplicate_StringFormat(StringFormat_t* x) { + expr_t* m_fmt = self().duplicate_expr(x->m_fmt); + Vec m_args; + m_args.reserve(al, x->n_args); + for (size_t i = 0; i < x->n_args; i++) { + m_args.push_back(al, self().duplicate_expr(x->m_args[i])); + } + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_StringFormat_t(al, x->base.base.loc, m_fmt, m_args.p, x->n_args, x->m_kind, m_type, m_value); + } + + + ASR::asr_t* duplicate_StringPhysicalCast(StringPhysicalCast_t* x) { + expr_t* m_arg = self().duplicate_expr(x->m_arg); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_StringPhysicalCast_t(al, x->base.base.loc, m_arg, x->m_old, x->m_new, m_type, m_value); + } + + + ASR::asr_t* duplicate_CPtrCompare(CPtrCompare_t* x) { + expr_t* m_left = self().duplicate_expr(x->m_left); + expr_t* m_right = self().duplicate_expr(x->m_right); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_CPtrCompare_t(al, x->base.base.loc, m_left, x->m_op, m_right, m_type, m_value); + } + + + ASR::asr_t* duplicate_SymbolicCompare(SymbolicCompare_t* x) { + expr_t* m_left = self().duplicate_expr(x->m_left); + expr_t* m_right = self().duplicate_expr(x->m_right); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_SymbolicCompare_t(al, x->base.base.loc, m_left, x->m_op, m_right, m_type, m_value); + } + + + ASR::asr_t* duplicate_DictConstant(DictConstant_t* x) { + Vec m_keys; + m_keys.reserve(al, x->n_keys); + for (size_t i = 0; i < x->n_keys; i++) { + m_keys.push_back(al, self().duplicate_expr(x->m_keys[i])); + } + Vec m_values; + m_values.reserve(al, x->n_values); + for (size_t i = 0; i < x->n_values; i++) { + m_values.push_back(al, self().duplicate_expr(x->m_values[i])); + } + ttype_t* m_type = self().duplicate_ttype(x->m_type); + return make_DictConstant_t(al, x->base.base.loc, m_keys.p, x->n_keys, m_values.p, x->n_values, m_type); + } + + + ASR::asr_t* duplicate_DictLen(DictLen_t* x) { + expr_t* m_arg = self().duplicate_expr(x->m_arg); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_DictLen_t(al, x->base.base.loc, m_arg, m_type, m_value); + } + + + ASR::asr_t* duplicate_Var(Var_t* x) { + symbol_t* m_v = x->m_v; + return make_Var_t(al, x->base.base.loc, m_v); + } + + + ASR::asr_t* duplicate_FunctionParam(FunctionParam_t* x) { + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_FunctionParam_t(al, x->base.base.loc, x->m_param_number, m_type, m_value); + } + + + ASR::asr_t* duplicate_ArrayConstructor(ArrayConstructor_t* x) { + Vec m_args; + m_args.reserve(al, x->n_args); + for (size_t i = 0; i < x->n_args; i++) { + m_args.push_back(al, self().duplicate_expr(x->m_args[i])); + } + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_ArrayConstructor_t(al, x->base.base.loc, m_args.p, x->n_args, m_type, m_value, x->m_storage_format); + } + + + ASR::asr_t* duplicate_ArrayConstant(ArrayConstant_t* x) { + ttype_t* m_type = self().duplicate_ttype(x->m_type); + return make_ArrayConstant_t(al, x->base.base.loc, x->m_n_data, x->m_data, m_type, x->m_storage_format); + } + + + ASR::asr_t* duplicate_ArrayItem(ArrayItem_t* x) { + expr_t* m_v = self().duplicate_expr(x->m_v); + Vec m_args; + m_args.reserve(al, x->n_args); + for (size_t i = 0; i < x->n_args; i++) { + ASR::array_index_t array_index_copy; + array_index_copy.loc = x->m_args[i].loc; + array_index_copy.m_left = duplicate_expr(x->m_args[i].m_left); + array_index_copy.m_right = duplicate_expr(x->m_args[i].m_right); + array_index_copy.m_step = duplicate_expr(x->m_args[i].m_step); + m_args.push_back(al, array_index_copy); + } + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_ArrayItem_t(al, x->base.base.loc, m_v, m_args.p, x->n_args, m_type, x->m_storage_format, m_value); + } + + + ASR::asr_t* duplicate_ArraySection(ArraySection_t* x) { + expr_t* m_v = self().duplicate_expr(x->m_v); + Vec m_args; + m_args.reserve(al, x->n_args); + for (size_t i = 0; i < x->n_args; i++) { + ASR::array_index_t array_index_copy; + array_index_copy.loc = x->m_args[i].loc; + array_index_copy.m_left = duplicate_expr(x->m_args[i].m_left); + array_index_copy.m_right = duplicate_expr(x->m_args[i].m_right); + array_index_copy.m_step = duplicate_expr(x->m_args[i].m_step); + m_args.push_back(al, array_index_copy); + } + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_ArraySection_t(al, x->base.base.loc, m_v, m_args.p, x->n_args, m_type, m_value); + } + + + ASR::asr_t* duplicate_ArraySize(ArraySize_t* x) { + expr_t* m_v = self().duplicate_expr(x->m_v); + expr_t* m_dim = self().duplicate_expr(x->m_dim); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_ArraySize_t(al, x->base.base.loc, m_v, m_dim, m_type, m_value); + } + + + ASR::asr_t* duplicate_ArrayBound(ArrayBound_t* x) { + expr_t* m_v = self().duplicate_expr(x->m_v); + expr_t* m_dim = self().duplicate_expr(x->m_dim); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_ArrayBound_t(al, x->base.base.loc, m_v, m_dim, m_type, x->m_bound, m_value); + } + + + ASR::asr_t* duplicate_ArrayTranspose(ArrayTranspose_t* x) { + expr_t* m_matrix = self().duplicate_expr(x->m_matrix); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_ArrayTranspose_t(al, x->base.base.loc, m_matrix, m_type, m_value); + } + + + ASR::asr_t* duplicate_ArrayPack(ArrayPack_t* x) { + expr_t* m_array = self().duplicate_expr(x->m_array); + expr_t* m_mask = self().duplicate_expr(x->m_mask); + expr_t* m_vector = self().duplicate_expr(x->m_vector); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_ArrayPack_t(al, x->base.base.loc, m_array, m_mask, m_vector, m_type, m_value); + } + + + ASR::asr_t* duplicate_ArrayReshape(ArrayReshape_t* x) { + expr_t* m_array = self().duplicate_expr(x->m_array); + expr_t* m_shape = self().duplicate_expr(x->m_shape); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_ArrayReshape_t(al, x->base.base.loc, m_array, m_shape, m_type, m_value); + } + + + ASR::asr_t* duplicate_ArrayAll(ArrayAll_t* x) { + expr_t* m_mask = self().duplicate_expr(x->m_mask); + expr_t* m_dim = self().duplicate_expr(x->m_dim); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_ArrayAll_t(al, x->base.base.loc, m_mask, m_dim, m_type, m_value); + } + + + ASR::asr_t* duplicate_ArrayBroadcast(ArrayBroadcast_t* x) { + expr_t* m_array = self().duplicate_expr(x->m_array); + expr_t* m_shape = self().duplicate_expr(x->m_shape); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_ArrayBroadcast_t(al, x->base.base.loc, m_array, m_shape, m_type, m_value); + } + + + ASR::asr_t* duplicate_BitCast(BitCast_t* x) { + expr_t* m_source = self().duplicate_expr(x->m_source); + expr_t* m_mold = self().duplicate_expr(x->m_mold); + expr_t* m_size = self().duplicate_expr(x->m_size); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_BitCast_t(al, x->base.base.loc, m_source, m_mold, m_size, m_type, m_value); + } + + + ASR::asr_t* duplicate_StructInstanceMember(StructInstanceMember_t* x) { + expr_t* m_v = self().duplicate_expr(x->m_v); + symbol_t* m_m = x->m_m; + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_StructInstanceMember_t(al, x->base.base.loc, m_v, m_m, m_type, m_value); + } + + + ASR::asr_t* duplicate_StructStaticMember(StructStaticMember_t* x) { + expr_t* m_v = self().duplicate_expr(x->m_v); + symbol_t* m_m = x->m_m; + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_StructStaticMember_t(al, x->base.base.loc, m_v, m_m, m_type, m_value); + } + + + ASR::asr_t* duplicate_EnumStaticMember(EnumStaticMember_t* x) { + expr_t* m_v = self().duplicate_expr(x->m_v); + symbol_t* m_m = x->m_m; + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_EnumStaticMember_t(al, x->base.base.loc, m_v, m_m, m_type, m_value); + } + + + ASR::asr_t* duplicate_UnionInstanceMember(UnionInstanceMember_t* x) { + expr_t* m_v = self().duplicate_expr(x->m_v); + symbol_t* m_m = x->m_m; + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_UnionInstanceMember_t(al, x->base.base.loc, m_v, m_m, m_type, m_value); + } + + + ASR::asr_t* duplicate_EnumName(EnumName_t* x) { + expr_t* m_v = self().duplicate_expr(x->m_v); + ttype_t* m_enum_type = self().duplicate_ttype(x->m_enum_type); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_EnumName_t(al, x->base.base.loc, m_v, m_enum_type, m_type, m_value); + } + + + ASR::asr_t* duplicate_EnumValue(EnumValue_t* x) { + expr_t* m_v = self().duplicate_expr(x->m_v); + ttype_t* m_enum_type = self().duplicate_ttype(x->m_enum_type); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_EnumValue_t(al, x->base.base.loc, m_v, m_enum_type, m_type, m_value); + } + + + ASR::asr_t* duplicate_OverloadedCompare(OverloadedCompare_t* x) { + expr_t* m_left = self().duplicate_expr(x->m_left); + expr_t* m_right = self().duplicate_expr(x->m_right); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + expr_t* m_overloaded = self().duplicate_expr(x->m_overloaded); + return make_OverloadedCompare_t(al, x->base.base.loc, m_left, x->m_op, m_right, m_type, m_value, m_overloaded); + } + + + ASR::asr_t* duplicate_OverloadedBinOp(OverloadedBinOp_t* x) { + expr_t* m_left = self().duplicate_expr(x->m_left); + expr_t* m_right = self().duplicate_expr(x->m_right); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + expr_t* m_overloaded = self().duplicate_expr(x->m_overloaded); + return make_OverloadedBinOp_t(al, x->base.base.loc, m_left, x->m_op, m_right, m_type, m_value, m_overloaded); + } + + + ASR::asr_t* duplicate_OverloadedUnaryMinus(OverloadedUnaryMinus_t* x) { + expr_t* m_arg = self().duplicate_expr(x->m_arg); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + expr_t* m_overloaded = self().duplicate_expr(x->m_overloaded); + return make_OverloadedUnaryMinus_t(al, x->base.base.loc, m_arg, m_type, m_value, m_overloaded); + } + + + ASR::asr_t* duplicate_OverloadedStringConcat(OverloadedStringConcat_t* x) { + expr_t* m_left = self().duplicate_expr(x->m_left); + expr_t* m_right = self().duplicate_expr(x->m_right); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + expr_t* m_overloaded = self().duplicate_expr(x->m_overloaded); + return make_OverloadedStringConcat_t(al, x->base.base.loc, m_left, m_right, m_type, m_value, m_overloaded); + } + + + ASR::asr_t* duplicate_Cast(Cast_t* x) { + expr_t* m_arg = self().duplicate_expr(x->m_arg); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_Cast_t(al, x->base.base.loc, m_arg, x->m_kind, m_type, m_value); + } + + + ASR::asr_t* duplicate_ArrayPhysicalCast(ArrayPhysicalCast_t* x) { + expr_t* m_arg = self().duplicate_expr(x->m_arg); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_ArrayPhysicalCast_t(al, x->base.base.loc, m_arg, x->m_old, x->m_new, m_type, m_value); + } + + + ASR::asr_t* duplicate_ComplexRe(ComplexRe_t* x) { + expr_t* m_arg = self().duplicate_expr(x->m_arg); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_ComplexRe_t(al, x->base.base.loc, m_arg, m_type, m_value); + } + + + ASR::asr_t* duplicate_ComplexIm(ComplexIm_t* x) { + expr_t* m_arg = self().duplicate_expr(x->m_arg); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_ComplexIm_t(al, x->base.base.loc, m_arg, m_type, m_value); + } + + + ASR::asr_t* duplicate_DictItem(DictItem_t* x) { + expr_t* m_a = self().duplicate_expr(x->m_a); + expr_t* m_key = self().duplicate_expr(x->m_key); + expr_t* m_default = self().duplicate_expr(x->m_default); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_DictItem_t(al, x->base.base.loc, m_a, m_key, m_default, m_type, m_value); + } + + + ASR::asr_t* duplicate_CLoc(CLoc_t* x) { + expr_t* m_arg = self().duplicate_expr(x->m_arg); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_CLoc_t(al, x->base.base.loc, m_arg, m_type, m_value); + } + + + ASR::asr_t* duplicate_PointerToCPtr(PointerToCPtr_t* x) { + expr_t* m_arg = self().duplicate_expr(x->m_arg); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_PointerToCPtr_t(al, x->base.base.loc, m_arg, m_type, m_value); + } + + + ASR::asr_t* duplicate_GetPointer(GetPointer_t* x) { + expr_t* m_arg = self().duplicate_expr(x->m_arg); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_GetPointer_t(al, x->base.base.loc, m_arg, m_type, m_value); + } + + + ASR::asr_t* duplicate_ListItem(ListItem_t* x) { + expr_t* m_a = self().duplicate_expr(x->m_a); + expr_t* m_pos = self().duplicate_expr(x->m_pos); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_ListItem_t(al, x->base.base.loc, m_a, m_pos, m_type, m_value); + } + + + ASR::asr_t* duplicate_TupleItem(TupleItem_t* x) { + expr_t* m_a = self().duplicate_expr(x->m_a); + expr_t* m_pos = self().duplicate_expr(x->m_pos); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_TupleItem_t(al, x->base.base.loc, m_a, m_pos, m_type, m_value); + } + + + ASR::asr_t* duplicate_ListSection(ListSection_t* x) { + expr_t* m_a = self().duplicate_expr(x->m_a); + ASR::array_index_t m_section; + m_section.loc = x->m_section.loc; + m_section.m_left = duplicate_expr(x->m_section.m_left); + m_section.m_right = duplicate_expr(x->m_section.m_right); + m_section.m_step = duplicate_expr(x->m_section.m_step); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_ListSection_t(al, x->base.base.loc, m_a, m_section, m_type, m_value); + } + + + ASR::asr_t* duplicate_ListRepeat(ListRepeat_t* x) { + expr_t* m_left = self().duplicate_expr(x->m_left); + expr_t* m_right = self().duplicate_expr(x->m_right); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_ListRepeat_t(al, x->base.base.loc, m_left, m_right, m_type, m_value); + } + + + ASR::asr_t* duplicate_DictPop(DictPop_t* x) { + expr_t* m_a = self().duplicate_expr(x->m_a); + expr_t* m_key = self().duplicate_expr(x->m_key); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_DictPop_t(al, x->base.base.loc, m_a, m_key, m_type, m_value); + } + + + ASR::asr_t* duplicate_SetPop(SetPop_t* x) { + expr_t* m_a = self().duplicate_expr(x->m_a); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_SetPop_t(al, x->base.base.loc, m_a, m_type, m_value); + } + + + ASR::asr_t* duplicate_SetContains(SetContains_t* x) { + expr_t* m_left = self().duplicate_expr(x->m_left); + expr_t* m_right = self().duplicate_expr(x->m_right); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_SetContains_t(al, x->base.base.loc, m_left, m_right, m_type, m_value); + } + + + ASR::asr_t* duplicate_DictContains(DictContains_t* x) { + expr_t* m_left = self().duplicate_expr(x->m_left); + expr_t* m_right = self().duplicate_expr(x->m_right); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_DictContains_t(al, x->base.base.loc, m_left, m_right, m_type, m_value); + } + + + ASR::asr_t* duplicate_IntegerBitLen(IntegerBitLen_t* x) { + expr_t* m_a = self().duplicate_expr(x->m_a); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_IntegerBitLen_t(al, x->base.base.loc, m_a, m_type, m_value); + } + + + ASR::asr_t* duplicate_Ichar(Ichar_t* x) { + expr_t* m_arg = self().duplicate_expr(x->m_arg); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_Ichar_t(al, x->base.base.loc, m_arg, m_type, m_value); + } + + + ASR::asr_t* duplicate_Iachar(Iachar_t* x) { + expr_t* m_arg = self().duplicate_expr(x->m_arg); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_Iachar_t(al, x->base.base.loc, m_arg, m_type, m_value); + } + + + ASR::asr_t* duplicate_SizeOfType(SizeOfType_t* x) { + ttype_t* m_arg = self().duplicate_ttype(x->m_arg); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_SizeOfType_t(al, x->base.base.loc, m_arg, m_type, m_value); + } + + + ASR::asr_t* duplicate_PointerNullConstant(PointerNullConstant_t* x) { + ttype_t* m_type = self().duplicate_ttype(x->m_type); + return make_PointerNullConstant_t(al, x->base.base.loc, m_type); + } + + + ASR::asr_t* duplicate_PointerAssociated(PointerAssociated_t* x) { + expr_t* m_ptr = self().duplicate_expr(x->m_ptr); + expr_t* m_tgt = self().duplicate_expr(x->m_tgt); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_PointerAssociated_t(al, x->base.base.loc, m_ptr, m_tgt, m_type, m_value); + } + + + ASR::asr_t* duplicate_RealSqrt(RealSqrt_t* x) { + expr_t* m_arg = self().duplicate_expr(x->m_arg); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_RealSqrt_t(al, x->base.base.loc, m_arg, m_type, m_value); + } + + + ASR::asr_t* duplicate_ArrayIsContiguous(ArrayIsContiguous_t* x) { + expr_t* m_array = self().duplicate_expr(x->m_array); + ttype_t* m_type = self().duplicate_ttype(x->m_type); + expr_t* m_value = self().duplicate_expr(x->m_value); + return make_ArrayIsContiguous_t(al, x->base.base.loc, m_array, m_type, m_value); + } + + + ASR::asr_t* duplicate_Integer(Integer_t* x) { + return make_Integer_t(al, x->base.base.loc, x->m_kind); + } + + + ASR::asr_t* duplicate_UnsignedInteger(UnsignedInteger_t* x) { + return make_UnsignedInteger_t(al, x->base.base.loc, x->m_kind); + } + + + ASR::asr_t* duplicate_Real(Real_t* x) { + return make_Real_t(al, x->base.base.loc, x->m_kind); + } + + + ASR::asr_t* duplicate_Complex(Complex_t* x) { + return make_Complex_t(al, x->base.base.loc, x->m_kind); + } + + + ASR::asr_t* duplicate_String(String_t* x) { + expr_t* m_len_expr = self().duplicate_expr(x->m_len_expr); + return make_String_t(al, x->base.base.loc, x->m_kind, x->m_len, m_len_expr, x->m_physical_type); + } + + + ASR::asr_t* duplicate_Logical(Logical_t* x) { + return make_Logical_t(al, x->base.base.loc, x->m_kind); + } + + + ASR::asr_t* duplicate_Set(Set_t* x) { + ttype_t* m_type = self().duplicate_ttype(x->m_type); + return make_Set_t(al, x->base.base.loc, m_type); + } + + + ASR::asr_t* duplicate_List(List_t* x) { + ttype_t* m_type = self().duplicate_ttype(x->m_type); + return make_List_t(al, x->base.base.loc, m_type); + } + + + ASR::asr_t* duplicate_Tuple(Tuple_t* x) { + Vec m_type; + m_type.reserve(al, x->n_type); + for (size_t i = 0; i < x->n_type; i++) { + m_type.push_back(al, self().duplicate_ttype(x->m_type[i])); + } + return make_Tuple_t(al, x->base.base.loc, m_type.p, x->n_type); + } + + + ASR::asr_t* duplicate_StructType(StructType_t* x) { + Vec m_data_member_types; + m_data_member_types.reserve(al, x->n_data_member_types); + for (size_t i = 0; i < x->n_data_member_types; i++) { + m_data_member_types.push_back(al, self().duplicate_ttype(x->m_data_member_types[i])); + } + Vec m_member_function_types; + m_member_function_types.reserve(al, x->n_member_function_types); + for (size_t i = 0; i < x->n_member_function_types; i++) { + m_member_function_types.push_back(al, self().duplicate_ttype(x->m_member_function_types[i])); + } + symbol_t* m_derived_type = x->m_derived_type; + return make_StructType_t(al, x->base.base.loc, m_data_member_types.p, x->n_data_member_types, m_member_function_types.p, x->n_member_function_types, x->m_is_cstruct, m_derived_type); + } + + + ASR::asr_t* duplicate_EnumType(EnumType_t* x) { + symbol_t* m_enum_type = x->m_enum_type; + return make_EnumType_t(al, x->base.base.loc, m_enum_type); + } + + + ASR::asr_t* duplicate_UnionType(UnionType_t* x) { + symbol_t* m_union_type = x->m_union_type; + return make_UnionType_t(al, x->base.base.loc, m_union_type); + } + + + ASR::asr_t* duplicate_ClassType(ClassType_t* x) { + symbol_t* m_class_type = x->m_class_type; + return make_ClassType_t(al, x->base.base.loc, m_class_type); + } + + + ASR::asr_t* duplicate_Dict(Dict_t* x) { + ttype_t* m_key_type = self().duplicate_ttype(x->m_key_type); + ttype_t* m_value_type = self().duplicate_ttype(x->m_value_type); + return make_Dict_t(al, x->base.base.loc, m_key_type, m_value_type); + } + + + ASR::asr_t* duplicate_Pointer(Pointer_t* x) { + ttype_t* m_type = self().duplicate_ttype(x->m_type); + return make_Pointer_t(al, x->base.base.loc, m_type); + } + + + ASR::asr_t* duplicate_Allocatable(Allocatable_t* x) { + ttype_t* m_type = self().duplicate_ttype(x->m_type); + return make_Allocatable_t(al, x->base.base.loc, m_type); + } + + + ASR::asr_t* duplicate_CPtr(CPtr_t* x) { + return make_CPtr_t(al, x->base.base.loc); + } + + + ASR::asr_t* duplicate_SymbolicExpression(SymbolicExpression_t* x) { + return make_SymbolicExpression_t(al, x->base.base.loc); + } + + + ASR::asr_t* duplicate_TypeParameter(TypeParameter_t* x) { + return make_TypeParameter_t(al, x->base.base.loc, x->m_param); + } + + + ASR::asr_t* duplicate_Array(Array_t* x) { + ttype_t* m_type = self().duplicate_ttype(x->m_type); + Vec m_dims; + m_dims.reserve(al, x->n_dims); + for (size_t i = 0; i < x->n_dims; i++) { + ASR::dimension_t dim_copy; + dim_copy.loc = x->m_dims[i].loc; + dim_copy.m_start = self().duplicate_expr(x->m_dims[i].m_start); + dim_copy.m_length = self().duplicate_expr(x->m_dims[i].m_length); + m_dims.push_back(al, dim_copy); + } + return make_Array_t(al, x->base.base.loc, m_type, m_dims.p, x->n_dims, x->m_physical_type); + } + + + ASR::asr_t* duplicate_FunctionType(FunctionType_t* x) { + Vec m_arg_types; + m_arg_types.reserve(al, x->n_arg_types); + for (size_t i = 0; i < x->n_arg_types; i++) { + m_arg_types.push_back(al, self().duplicate_ttype(x->m_arg_types[i])); + } + ttype_t* m_return_var_type = self().duplicate_ttype(x->m_return_var_type); + Vec m_restrictions; + m_restrictions.reserve(al, x->n_restrictions); + for (size_t i = 0; i < x->n_restrictions; i++) { + m_restrictions.push_back(al, x->m_restrictions[i]); + } + return make_FunctionType_t(al, x->base.base.loc, m_arg_types.p, x->n_arg_types, m_return_var_type, x->m_abi, x->m_deftype, x->m_bindc_name, x->m_elemental, x->m_pure, x->m_module, x->m_inline, x->m_static, m_restrictions.p, x->n_restrictions, x->m_is_restriction); + } + + + ASR::asr_t* duplicate_CaseStmt(CaseStmt_t* x) { + Vec m_test; + m_test.reserve(al, x->n_test); + for (size_t i = 0; i < x->n_test; i++) { + m_test.push_back(al, self().duplicate_expr(x->m_test[i])); + } + Vec m_body; + m_body.reserve(al, x->n_body); + for (size_t i = 0; i < x->n_body; i++) { + m_body.push_back(al, self().duplicate_stmt(x->m_body[i])); + } + return make_CaseStmt_t(al, x->base.base.loc, m_test.p, x->n_test, m_body.p, x->n_body, x->m_fall_through); + } + + + ASR::asr_t* duplicate_CaseStmt_Range(CaseStmt_Range_t* x) { + expr_t* m_start = self().duplicate_expr(x->m_start); + expr_t* m_end = self().duplicate_expr(x->m_end); + Vec m_body; + m_body.reserve(al, x->n_body); + for (size_t i = 0; i < x->n_body; i++) { + m_body.push_back(al, self().duplicate_stmt(x->m_body[i])); + } + return make_CaseStmt_Range_t(al, x->base.base.loc, m_start, m_end, m_body.p, x->n_body); + } + + ASR::stmt_t* duplicate_stmt(ASR::stmt_t* x) { + if( !x ) { + return nullptr; + } + + switch(x->type) { + case ASR::stmtType::Allocate: { + return down_cast(self().duplicate_Allocate(down_cast(x))); + } + case ASR::stmtType::ReAlloc: { + return down_cast(self().duplicate_ReAlloc(down_cast(x))); + } + case ASR::stmtType::Assign: { + return down_cast(self().duplicate_Assign(down_cast(x))); + } + case ASR::stmtType::Assignment: { + return down_cast(self().duplicate_Assignment(down_cast(x))); + } + case ASR::stmtType::Associate: { + return down_cast(self().duplicate_Associate(down_cast(x))); + } + case ASR::stmtType::Cycle: { + return down_cast(self().duplicate_Cycle(down_cast(x))); + } + case ASR::stmtType::ExplicitDeallocate: { + return down_cast(self().duplicate_ExplicitDeallocate(down_cast(x))); + } + case ASR::stmtType::ImplicitDeallocate: { + return down_cast(self().duplicate_ImplicitDeallocate(down_cast(x))); + } + case ASR::stmtType::DoConcurrentLoop: { + return down_cast(self().duplicate_DoConcurrentLoop(down_cast(x))); + } + case ASR::stmtType::DoLoop: { + return down_cast(self().duplicate_DoLoop(down_cast(x))); + } + case ASR::stmtType::ErrorStop: { + return down_cast(self().duplicate_ErrorStop(down_cast(x))); + } + case ASR::stmtType::Exit: { + return down_cast(self().duplicate_Exit(down_cast(x))); + } + case ASR::stmtType::ForAllSingle: { + return down_cast(self().duplicate_ForAllSingle(down_cast(x))); + } + case ASR::stmtType::ForEach: { + return down_cast(self().duplicate_ForEach(down_cast(x))); + } + case ASR::stmtType::GoTo: { + return down_cast(self().duplicate_GoTo(down_cast(x))); + } + case ASR::stmtType::GoToTarget: { + return down_cast(self().duplicate_GoToTarget(down_cast(x))); + } + case ASR::stmtType::If: { + return down_cast(self().duplicate_If(down_cast(x))); + } + case ASR::stmtType::IfArithmetic: { + return down_cast(self().duplicate_IfArithmetic(down_cast(x))); + } + case ASR::stmtType::Print: { + return down_cast(self().duplicate_Print(down_cast(x))); + } + case ASR::stmtType::FileOpen: { + return down_cast(self().duplicate_FileOpen(down_cast(x))); + } + case ASR::stmtType::FileClose: { + return down_cast(self().duplicate_FileClose(down_cast(x))); + } + case ASR::stmtType::FileRead: { + return down_cast(self().duplicate_FileRead(down_cast(x))); + } + case ASR::stmtType::FileBackspace: { + return down_cast(self().duplicate_FileBackspace(down_cast(x))); + } + case ASR::stmtType::FileRewind: { + return down_cast(self().duplicate_FileRewind(down_cast(x))); + } + case ASR::stmtType::FileInquire: { + return down_cast(self().duplicate_FileInquire(down_cast(x))); + } + case ASR::stmtType::FileWrite: { + return down_cast(self().duplicate_FileWrite(down_cast(x))); + } + case ASR::stmtType::Return: { + return down_cast(self().duplicate_Return(down_cast(x))); + } + case ASR::stmtType::Select: { + return down_cast(self().duplicate_Select(down_cast(x))); + } + case ASR::stmtType::Stop: { + return down_cast(self().duplicate_Stop(down_cast(x))); + } + case ASR::stmtType::Assert: { + return down_cast(self().duplicate_Assert(down_cast(x))); + } + case ASR::stmtType::SubroutineCall: { + if( !allow_procedure_calls ) { + success = false; + return nullptr; + } + return down_cast(self().duplicate_SubroutineCall(down_cast(x))); + } + case ASR::stmtType::IntrinsicImpureSubroutine: { + return down_cast(self().duplicate_IntrinsicImpureSubroutine(down_cast(x))); + } + case ASR::stmtType::Where: { + return down_cast(self().duplicate_Where(down_cast(x))); + } + case ASR::stmtType::WhileLoop: { + return down_cast(self().duplicate_WhileLoop(down_cast(x))); + } + case ASR::stmtType::Nullify: { + return down_cast(self().duplicate_Nullify(down_cast(x))); + } + case ASR::stmtType::Flush: { + return down_cast(self().duplicate_Flush(down_cast(x))); + } + case ASR::stmtType::ListAppend: { + return down_cast(self().duplicate_ListAppend(down_cast(x))); + } + case ASR::stmtType::AssociateBlockCall: { + return down_cast(self().duplicate_AssociateBlockCall(down_cast(x))); + } + case ASR::stmtType::SelectType: { + return down_cast(self().duplicate_SelectType(down_cast(x))); + } + case ASR::stmtType::CPtrToPointer: { + return down_cast(self().duplicate_CPtrToPointer(down_cast(x))); + } + case ASR::stmtType::BlockCall: { + return down_cast(self().duplicate_BlockCall(down_cast(x))); + } + case ASR::stmtType::SetInsert: { + return down_cast(self().duplicate_SetInsert(down_cast(x))); + } + case ASR::stmtType::SetRemove: { + return down_cast(self().duplicate_SetRemove(down_cast(x))); + } + case ASR::stmtType::SetDiscard: { + return down_cast(self().duplicate_SetDiscard(down_cast(x))); + } + case ASR::stmtType::ListInsert: { + return down_cast(self().duplicate_ListInsert(down_cast(x))); + } + case ASR::stmtType::ListRemove: { + return down_cast(self().duplicate_ListRemove(down_cast(x))); + } + case ASR::stmtType::ListClear: { + return down_cast(self().duplicate_ListClear(down_cast(x))); + } + case ASR::stmtType::DictInsert: { + return down_cast(self().duplicate_DictInsert(down_cast(x))); + } + case ASR::stmtType::DictClear: { + return down_cast(self().duplicate_DictClear(down_cast(x))); + } + case ASR::stmtType::SetClear: { + return down_cast(self().duplicate_SetClear(down_cast(x))); + } + case ASR::stmtType::Expr: { + return down_cast(self().duplicate_Expr(down_cast(x))); + } + default: { + LCOMPILERS_ASSERT_MSG(false, "Duplication of " + std::to_string(x->type) + " statement is not supported yet."); + } + } + + return nullptr; + } + + ASR::expr_t* duplicate_expr(ASR::expr_t* x) { + if( !x ) { + return nullptr; + } + + switch(x->type) { + case ASR::exprType::IfExp: { + return down_cast(self().duplicate_IfExp(down_cast(x))); + } + case ASR::exprType::ComplexConstructor: { + return down_cast(self().duplicate_ComplexConstructor(down_cast(x))); + } + case ASR::exprType::NamedExpr: { + return down_cast(self().duplicate_NamedExpr(down_cast(x))); + } + case ASR::exprType::FunctionCall: { + if( !allow_procedure_calls ) { + success = false; + return nullptr; + } + return down_cast(self().duplicate_FunctionCall(down_cast(x))); + } + case ASR::exprType::IntrinsicElementalFunction: { + return down_cast(self().duplicate_IntrinsicElementalFunction(down_cast(x))); + } + case ASR::exprType::IntrinsicArrayFunction: { + return down_cast(self().duplicate_IntrinsicArrayFunction(down_cast(x))); + } + case ASR::exprType::IntrinsicImpureFunction: { + return down_cast(self().duplicate_IntrinsicImpureFunction(down_cast(x))); + } + case ASR::exprType::TypeInquiry: { + return down_cast(self().duplicate_TypeInquiry(down_cast(x))); + } + case ASR::exprType::StructConstructor: { + return down_cast(self().duplicate_StructConstructor(down_cast(x))); + } + case ASR::exprType::StructConstant: { + return down_cast(self().duplicate_StructConstant(down_cast(x))); + } + case ASR::exprType::EnumConstructor: { + return down_cast(self().duplicate_EnumConstructor(down_cast(x))); + } + case ASR::exprType::UnionConstructor: { + return down_cast(self().duplicate_UnionConstructor(down_cast(x))); + } + case ASR::exprType::ImpliedDoLoop: { + return down_cast(self().duplicate_ImpliedDoLoop(down_cast(x))); + } + case ASR::exprType::IntegerConstant: { + return down_cast(self().duplicate_IntegerConstant(down_cast(x))); + } + case ASR::exprType::IntegerBitNot: { + return down_cast(self().duplicate_IntegerBitNot(down_cast(x))); + } + case ASR::exprType::IntegerUnaryMinus: { + return down_cast(self().duplicate_IntegerUnaryMinus(down_cast(x))); + } + case ASR::exprType::IntegerCompare: { + return down_cast(self().duplicate_IntegerCompare(down_cast(x))); + } + case ASR::exprType::IntegerBinOp: { + return down_cast(self().duplicate_IntegerBinOp(down_cast(x))); + } + case ASR::exprType::UnsignedIntegerConstant: { + return down_cast(self().duplicate_UnsignedIntegerConstant(down_cast(x))); + } + case ASR::exprType::UnsignedIntegerUnaryMinus: { + return down_cast(self().duplicate_UnsignedIntegerUnaryMinus(down_cast(x))); + } + case ASR::exprType::UnsignedIntegerBitNot: { + return down_cast(self().duplicate_UnsignedIntegerBitNot(down_cast(x))); + } + case ASR::exprType::UnsignedIntegerCompare: { + return down_cast(self().duplicate_UnsignedIntegerCompare(down_cast(x))); + } + case ASR::exprType::UnsignedIntegerBinOp: { + return down_cast(self().duplicate_UnsignedIntegerBinOp(down_cast(x))); + } + case ASR::exprType::RealConstant: { + return down_cast(self().duplicate_RealConstant(down_cast(x))); + } + case ASR::exprType::RealUnaryMinus: { + return down_cast(self().duplicate_RealUnaryMinus(down_cast(x))); + } + case ASR::exprType::RealCompare: { + return down_cast(self().duplicate_RealCompare(down_cast(x))); + } + case ASR::exprType::RealBinOp: { + return down_cast(self().duplicate_RealBinOp(down_cast(x))); + } + case ASR::exprType::RealCopySign: { + return down_cast(self().duplicate_RealCopySign(down_cast(x))); + } + case ASR::exprType::ComplexConstant: { + return down_cast(self().duplicate_ComplexConstant(down_cast(x))); + } + case ASR::exprType::ComplexUnaryMinus: { + return down_cast(self().duplicate_ComplexUnaryMinus(down_cast(x))); + } + case ASR::exprType::ComplexCompare: { + return down_cast(self().duplicate_ComplexCompare(down_cast(x))); + } + case ASR::exprType::ComplexBinOp: { + return down_cast(self().duplicate_ComplexBinOp(down_cast(x))); + } + case ASR::exprType::LogicalConstant: { + return down_cast(self().duplicate_LogicalConstant(down_cast(x))); + } + case ASR::exprType::LogicalNot: { + return down_cast(self().duplicate_LogicalNot(down_cast(x))); + } + case ASR::exprType::LogicalCompare: { + return down_cast(self().duplicate_LogicalCompare(down_cast(x))); + } + case ASR::exprType::LogicalBinOp: { + return down_cast(self().duplicate_LogicalBinOp(down_cast(x))); + } + case ASR::exprType::ListConstant: { + return down_cast(self().duplicate_ListConstant(down_cast(x))); + } + case ASR::exprType::ListLen: { + return down_cast(self().duplicate_ListLen(down_cast(x))); + } + case ASR::exprType::ListConcat: { + return down_cast(self().duplicate_ListConcat(down_cast(x))); + } + case ASR::exprType::ListCompare: { + return down_cast(self().duplicate_ListCompare(down_cast(x))); + } + case ASR::exprType::ListCount: { + return down_cast(self().duplicate_ListCount(down_cast(x))); + } + case ASR::exprType::ListContains: { + return down_cast(self().duplicate_ListContains(down_cast(x))); + } + case ASR::exprType::SetConstant: { + return down_cast(self().duplicate_SetConstant(down_cast(x))); + } + case ASR::exprType::SetLen: { + return down_cast(self().duplicate_SetLen(down_cast(x))); + } + case ASR::exprType::TupleConstant: { + return down_cast(self().duplicate_TupleConstant(down_cast(x))); + } + case ASR::exprType::TupleLen: { + return down_cast(self().duplicate_TupleLen(down_cast(x))); + } + case ASR::exprType::TupleCompare: { + return down_cast(self().duplicate_TupleCompare(down_cast(x))); + } + case ASR::exprType::TupleConcat: { + return down_cast(self().duplicate_TupleConcat(down_cast(x))); + } + case ASR::exprType::TupleContains: { + return down_cast(self().duplicate_TupleContains(down_cast(x))); + } + case ASR::exprType::StringConstant: { + return down_cast(self().duplicate_StringConstant(down_cast(x))); + } + case ASR::exprType::StringConcat: { + return down_cast(self().duplicate_StringConcat(down_cast(x))); + } + case ASR::exprType::StringRepeat: { + return down_cast(self().duplicate_StringRepeat(down_cast(x))); + } + case ASR::exprType::StringLen: { + return down_cast(self().duplicate_StringLen(down_cast(x))); + } + case ASR::exprType::StringItem: { + return down_cast(self().duplicate_StringItem(down_cast(x))); + } + case ASR::exprType::StringSection: { + return down_cast(self().duplicate_StringSection(down_cast(x))); + } + case ASR::exprType::StringCompare: { + return down_cast(self().duplicate_StringCompare(down_cast(x))); + } + case ASR::exprType::StringContains: { + return down_cast(self().duplicate_StringContains(down_cast(x))); + } + case ASR::exprType::StringOrd: { + return down_cast(self().duplicate_StringOrd(down_cast(x))); + } + case ASR::exprType::StringChr: { + return down_cast(self().duplicate_StringChr(down_cast(x))); + } + case ASR::exprType::StringFormat: { + return down_cast(self().duplicate_StringFormat(down_cast(x))); + } + case ASR::exprType::StringPhysicalCast: { + return down_cast(self().duplicate_StringPhysicalCast(down_cast(x))); + } + case ASR::exprType::CPtrCompare: { + return down_cast(self().duplicate_CPtrCompare(down_cast(x))); + } + case ASR::exprType::SymbolicCompare: { + return down_cast(self().duplicate_SymbolicCompare(down_cast(x))); + } + case ASR::exprType::DictConstant: { + return down_cast(self().duplicate_DictConstant(down_cast(x))); + } + case ASR::exprType::DictLen: { + return down_cast(self().duplicate_DictLen(down_cast(x))); + } + case ASR::exprType::Var: { + return down_cast(self().duplicate_Var(down_cast(x))); + } + case ASR::exprType::FunctionParam: { + return down_cast(self().duplicate_FunctionParam(down_cast(x))); + } + case ASR::exprType::ArrayConstructor: { + return down_cast(self().duplicate_ArrayConstructor(down_cast(x))); + } + case ASR::exprType::ArrayConstant: { + return down_cast(self().duplicate_ArrayConstant(down_cast(x))); + } + case ASR::exprType::ArrayItem: { + return down_cast(self().duplicate_ArrayItem(down_cast(x))); + } + case ASR::exprType::ArraySection: { + return down_cast(self().duplicate_ArraySection(down_cast(x))); + } + case ASR::exprType::ArraySize: { + return down_cast(self().duplicate_ArraySize(down_cast(x))); + } + case ASR::exprType::ArrayBound: { + return down_cast(self().duplicate_ArrayBound(down_cast(x))); + } + case ASR::exprType::ArrayTranspose: { + return down_cast(self().duplicate_ArrayTranspose(down_cast(x))); + } + case ASR::exprType::ArrayPack: { + return down_cast(self().duplicate_ArrayPack(down_cast(x))); + } + case ASR::exprType::ArrayReshape: { + if( !allow_reshape ) { + success = false; + return nullptr; + } + return down_cast(self().duplicate_ArrayReshape(down_cast(x))); + } + case ASR::exprType::ArrayAll: { + return down_cast(self().duplicate_ArrayAll(down_cast(x))); + } + case ASR::exprType::ArrayBroadcast: { + return down_cast(self().duplicate_ArrayBroadcast(down_cast(x))); + } + case ASR::exprType::BitCast: { + return down_cast(self().duplicate_BitCast(down_cast(x))); + } + case ASR::exprType::StructInstanceMember: { + return down_cast(self().duplicate_StructInstanceMember(down_cast(x))); + } + case ASR::exprType::StructStaticMember: { + return down_cast(self().duplicate_StructStaticMember(down_cast(x))); + } + case ASR::exprType::EnumStaticMember: { + return down_cast(self().duplicate_EnumStaticMember(down_cast(x))); + } + case ASR::exprType::UnionInstanceMember: { + return down_cast(self().duplicate_UnionInstanceMember(down_cast(x))); + } + case ASR::exprType::EnumName: { + return down_cast(self().duplicate_EnumName(down_cast(x))); + } + case ASR::exprType::EnumValue: { + return down_cast(self().duplicate_EnumValue(down_cast(x))); + } + case ASR::exprType::OverloadedCompare: { + return down_cast(self().duplicate_OverloadedCompare(down_cast(x))); + } + case ASR::exprType::OverloadedBinOp: { + return down_cast(self().duplicate_OverloadedBinOp(down_cast(x))); + } + case ASR::exprType::OverloadedUnaryMinus: { + return down_cast(self().duplicate_OverloadedUnaryMinus(down_cast(x))); + } + case ASR::exprType::OverloadedStringConcat: { + return down_cast(self().duplicate_OverloadedStringConcat(down_cast(x))); + } + case ASR::exprType::Cast: { + return down_cast(self().duplicate_Cast(down_cast(x))); + } + case ASR::exprType::ArrayPhysicalCast: { + return down_cast(self().duplicate_ArrayPhysicalCast(down_cast(x))); + } + case ASR::exprType::ComplexRe: { + return down_cast(self().duplicate_ComplexRe(down_cast(x))); + } + case ASR::exprType::ComplexIm: { + return down_cast(self().duplicate_ComplexIm(down_cast(x))); + } + case ASR::exprType::DictItem: { + return down_cast(self().duplicate_DictItem(down_cast(x))); + } + case ASR::exprType::CLoc: { + return down_cast(self().duplicate_CLoc(down_cast(x))); + } + case ASR::exprType::PointerToCPtr: { + return down_cast(self().duplicate_PointerToCPtr(down_cast(x))); + } + case ASR::exprType::GetPointer: { + return down_cast(self().duplicate_GetPointer(down_cast(x))); + } + case ASR::exprType::ListItem: { + return down_cast(self().duplicate_ListItem(down_cast(x))); + } + case ASR::exprType::TupleItem: { + return down_cast(self().duplicate_TupleItem(down_cast(x))); + } + case ASR::exprType::ListSection: { + return down_cast(self().duplicate_ListSection(down_cast(x))); + } + case ASR::exprType::ListRepeat: { + return down_cast(self().duplicate_ListRepeat(down_cast(x))); + } + case ASR::exprType::DictPop: { + return down_cast(self().duplicate_DictPop(down_cast(x))); + } + case ASR::exprType::SetPop: { + return down_cast(self().duplicate_SetPop(down_cast(x))); + } + case ASR::exprType::SetContains: { + return down_cast(self().duplicate_SetContains(down_cast(x))); + } + case ASR::exprType::DictContains: { + return down_cast(self().duplicate_DictContains(down_cast(x))); + } + case ASR::exprType::IntegerBitLen: { + return down_cast(self().duplicate_IntegerBitLen(down_cast(x))); + } + case ASR::exprType::Ichar: { + return down_cast(self().duplicate_Ichar(down_cast(x))); + } + case ASR::exprType::Iachar: { + return down_cast(self().duplicate_Iachar(down_cast(x))); + } + case ASR::exprType::SizeOfType: { + return down_cast(self().duplicate_SizeOfType(down_cast(x))); + } + case ASR::exprType::PointerNullConstant: { + return down_cast(self().duplicate_PointerNullConstant(down_cast(x))); + } + case ASR::exprType::PointerAssociated: { + return down_cast(self().duplicate_PointerAssociated(down_cast(x))); + } + case ASR::exprType::RealSqrt: { + return down_cast(self().duplicate_RealSqrt(down_cast(x))); + } + case ASR::exprType::ArrayIsContiguous: { + return down_cast(self().duplicate_ArrayIsContiguous(down_cast(x))); + } + default: { + LCOMPILERS_ASSERT_MSG(false, "Duplication of " + std::to_string(x->type) + " expression is not supported yet."); + } + } + + return nullptr; + } + + ASR::ttype_t* duplicate_ttype(ASR::ttype_t* x) { + if( !x ) { + return nullptr; + } + + switch(x->type) { + case ASR::ttypeType::Integer: { + return down_cast(self().duplicate_Integer(down_cast(x))); + } + case ASR::ttypeType::UnsignedInteger: { + return down_cast(self().duplicate_UnsignedInteger(down_cast(x))); + } + case ASR::ttypeType::Real: { + return down_cast(self().duplicate_Real(down_cast(x))); + } + case ASR::ttypeType::Complex: { + return down_cast(self().duplicate_Complex(down_cast(x))); + } + case ASR::ttypeType::String: { + return down_cast(self().duplicate_String(down_cast(x))); + } + case ASR::ttypeType::Logical: { + return down_cast(self().duplicate_Logical(down_cast(x))); + } + case ASR::ttypeType::Set: { + return down_cast(self().duplicate_Set(down_cast(x))); + } + case ASR::ttypeType::List: { + return down_cast(self().duplicate_List(down_cast(x))); + } + case ASR::ttypeType::Tuple: { + return down_cast(self().duplicate_Tuple(down_cast(x))); + } + case ASR::ttypeType::StructType: { + return down_cast(self().duplicate_StructType(down_cast(x))); + } + case ASR::ttypeType::EnumType: { + return down_cast(self().duplicate_EnumType(down_cast(x))); + } + case ASR::ttypeType::UnionType: { + return down_cast(self().duplicate_UnionType(down_cast(x))); + } + case ASR::ttypeType::ClassType: { + return down_cast(self().duplicate_ClassType(down_cast(x))); + } + case ASR::ttypeType::Dict: { + return down_cast(self().duplicate_Dict(down_cast(x))); + } + case ASR::ttypeType::Pointer: { + return down_cast(self().duplicate_Pointer(down_cast(x))); + } + case ASR::ttypeType::Allocatable: { + return down_cast(self().duplicate_Allocatable(down_cast(x))); + } + case ASR::ttypeType::CPtr: { + return down_cast(self().duplicate_CPtr(down_cast(x))); + } + case ASR::ttypeType::SymbolicExpression: { + return down_cast(self().duplicate_SymbolicExpression(down_cast(x))); + } + case ASR::ttypeType::TypeParameter: { + return down_cast(self().duplicate_TypeParameter(down_cast(x))); + } + case ASR::ttypeType::Array: { + return down_cast(self().duplicate_Array(down_cast(x))); + } + case ASR::ttypeType::FunctionType: { + return down_cast(self().duplicate_FunctionType(down_cast(x))); + } + default: { + LCOMPILERS_ASSERT_MSG(false, "Duplication of " + std::to_string(x->type) + " type is not supported yet."); + } + } + + return nullptr; + } + + ASR::case_stmt_t* duplicate_case_stmt(ASR::case_stmt_t* x) { + if( !x ) { + return nullptr; + } + + switch(x->type) { + case ASR::case_stmtType::CaseStmt: { + return down_cast(self().duplicate_CaseStmt(down_cast(x))); + } + case ASR::case_stmtType::CaseStmt_Range: { + return down_cast(self().duplicate_CaseStmt_Range(down_cast(x))); + } + default: { + LCOMPILERS_ASSERT_MSG(false, "Duplication of " + std::to_string(x->type) + " case statement is not supported yet."); + } + } + + return nullptr; + } + +}; + + +} diff --git a/src/libasr/asr_expr_type_visitor.h b/src/libasr/asr_expr_type_visitor.h new file mode 100644 index 0000000000..a4cb733fc5 --- /dev/null +++ b/src/libasr/asr_expr_type_visitor.h @@ -0,0 +1,159 @@ +#pragma once + +// Generated by grammar/asdl_cpp.py + +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace LCompilers::ASR { +/******************************************************************************/ +// Expression Type (`expr_type`) visitor +static inline ASR::ttype_t* expr_type0(const ASR::expr_t *f) +{ + LCOMPILERS_ASSERT(f != nullptr); + switch (f->type) { + case ASR::exprType::IfExp: { return ((ASR::IfExp_t*)f)->m_type; } + case ASR::exprType::ComplexConstructor: { return ((ASR::ComplexConstructor_t*)f)->m_type; } + case ASR::exprType::NamedExpr: { return ((ASR::NamedExpr_t*)f)->m_type; } + case ASR::exprType::FunctionCall: { return ((ASR::FunctionCall_t*)f)->m_type; } + case ASR::exprType::IntrinsicElementalFunction: { return ((ASR::IntrinsicElementalFunction_t*)f)->m_type; } + case ASR::exprType::IntrinsicArrayFunction: { return ((ASR::IntrinsicArrayFunction_t*)f)->m_type; } + case ASR::exprType::IntrinsicImpureFunction: { return ((ASR::IntrinsicImpureFunction_t*)f)->m_type; } + case ASR::exprType::TypeInquiry: { return ((ASR::TypeInquiry_t*)f)->m_type; } + case ASR::exprType::StructConstructor: { return ((ASR::StructConstructor_t*)f)->m_type; } + case ASR::exprType::StructConstant: { return ((ASR::StructConstant_t*)f)->m_type; } + case ASR::exprType::EnumConstructor: { return ((ASR::EnumConstructor_t*)f)->m_type; } + case ASR::exprType::UnionConstructor: { return ((ASR::UnionConstructor_t*)f)->m_type; } + case ASR::exprType::ImpliedDoLoop: { return ((ASR::ImpliedDoLoop_t*)f)->m_type; } + case ASR::exprType::IntegerConstant: { return ((ASR::IntegerConstant_t*)f)->m_type; } + case ASR::exprType::IntegerBitNot: { return ((ASR::IntegerBitNot_t*)f)->m_type; } + case ASR::exprType::IntegerUnaryMinus: { return ((ASR::IntegerUnaryMinus_t*)f)->m_type; } + case ASR::exprType::IntegerCompare: { return ((ASR::IntegerCompare_t*)f)->m_type; } + case ASR::exprType::IntegerBinOp: { return ((ASR::IntegerBinOp_t*)f)->m_type; } + case ASR::exprType::UnsignedIntegerConstant: { return ((ASR::UnsignedIntegerConstant_t*)f)->m_type; } + case ASR::exprType::UnsignedIntegerUnaryMinus: { return ((ASR::UnsignedIntegerUnaryMinus_t*)f)->m_type; } + case ASR::exprType::UnsignedIntegerBitNot: { return ((ASR::UnsignedIntegerBitNot_t*)f)->m_type; } + case ASR::exprType::UnsignedIntegerCompare: { return ((ASR::UnsignedIntegerCompare_t*)f)->m_type; } + case ASR::exprType::UnsignedIntegerBinOp: { return ((ASR::UnsignedIntegerBinOp_t*)f)->m_type; } + case ASR::exprType::RealConstant: { return ((ASR::RealConstant_t*)f)->m_type; } + case ASR::exprType::RealUnaryMinus: { return ((ASR::RealUnaryMinus_t*)f)->m_type; } + case ASR::exprType::RealCompare: { return ((ASR::RealCompare_t*)f)->m_type; } + case ASR::exprType::RealBinOp: { return ((ASR::RealBinOp_t*)f)->m_type; } + case ASR::exprType::RealCopySign: { return ((ASR::RealCopySign_t*)f)->m_type; } + case ASR::exprType::ComplexConstant: { return ((ASR::ComplexConstant_t*)f)->m_type; } + case ASR::exprType::ComplexUnaryMinus: { return ((ASR::ComplexUnaryMinus_t*)f)->m_type; } + case ASR::exprType::ComplexCompare: { return ((ASR::ComplexCompare_t*)f)->m_type; } + case ASR::exprType::ComplexBinOp: { return ((ASR::ComplexBinOp_t*)f)->m_type; } + case ASR::exprType::LogicalConstant: { return ((ASR::LogicalConstant_t*)f)->m_type; } + case ASR::exprType::LogicalNot: { return ((ASR::LogicalNot_t*)f)->m_type; } + case ASR::exprType::LogicalCompare: { return ((ASR::LogicalCompare_t*)f)->m_type; } + case ASR::exprType::LogicalBinOp: { return ((ASR::LogicalBinOp_t*)f)->m_type; } + case ASR::exprType::ListConstant: { return ((ASR::ListConstant_t*)f)->m_type; } + case ASR::exprType::ListLen: { return ((ASR::ListLen_t*)f)->m_type; } + case ASR::exprType::ListConcat: { return ((ASR::ListConcat_t*)f)->m_type; } + case ASR::exprType::ListCompare: { return ((ASR::ListCompare_t*)f)->m_type; } + case ASR::exprType::ListCount: { return ((ASR::ListCount_t*)f)->m_type; } + case ASR::exprType::ListContains: { return ((ASR::ListContains_t*)f)->m_type; } + case ASR::exprType::SetConstant: { return ((ASR::SetConstant_t*)f)->m_type; } + case ASR::exprType::SetLen: { return ((ASR::SetLen_t*)f)->m_type; } + case ASR::exprType::TupleConstant: { return ((ASR::TupleConstant_t*)f)->m_type; } + case ASR::exprType::TupleLen: { return ((ASR::TupleLen_t*)f)->m_type; } + case ASR::exprType::TupleCompare: { return ((ASR::TupleCompare_t*)f)->m_type; } + case ASR::exprType::TupleConcat: { return ((ASR::TupleConcat_t*)f)->m_type; } + case ASR::exprType::TupleContains: { return ((ASR::TupleContains_t*)f)->m_type; } + case ASR::exprType::StringConstant: { return ((ASR::StringConstant_t*)f)->m_type; } + case ASR::exprType::StringConcat: { return ((ASR::StringConcat_t*)f)->m_type; } + case ASR::exprType::StringRepeat: { return ((ASR::StringRepeat_t*)f)->m_type; } + case ASR::exprType::StringLen: { return ((ASR::StringLen_t*)f)->m_type; } + case ASR::exprType::StringItem: { return ((ASR::StringItem_t*)f)->m_type; } + case ASR::exprType::StringSection: { return ((ASR::StringSection_t*)f)->m_type; } + case ASR::exprType::StringCompare: { return ((ASR::StringCompare_t*)f)->m_type; } + case ASR::exprType::StringContains: { return ((ASR::StringContains_t*)f)->m_type; } + case ASR::exprType::StringOrd: { return ((ASR::StringOrd_t*)f)->m_type; } + case ASR::exprType::StringChr: { return ((ASR::StringChr_t*)f)->m_type; } + case ASR::exprType::StringFormat: { return ((ASR::StringFormat_t*)f)->m_type; } + case ASR::exprType::StringPhysicalCast: { return ((ASR::StringPhysicalCast_t*)f)->m_type; } + case ASR::exprType::CPtrCompare: { return ((ASR::CPtrCompare_t*)f)->m_type; } + case ASR::exprType::SymbolicCompare: { return ((ASR::SymbolicCompare_t*)f)->m_type; } + case ASR::exprType::DictConstant: { return ((ASR::DictConstant_t*)f)->m_type; } + case ASR::exprType::DictLen: { return ((ASR::DictLen_t*)f)->m_type; } + case ASR::exprType::Var: { + ASR::symbol_t *s = ((ASR::Var_t*)f)->m_v; + if (s->type == ASR::symbolType::ExternalSymbol) { + ASR::ExternalSymbol_t *e = ASR::down_cast(s); + LCOMPILERS_ASSERT(e->m_external); + LCOMPILERS_ASSERT(!ASR::is_a(*e->m_external)); + s = e->m_external; + } + if (s->type == ASR::symbolType::Function) { + return ASR::down_cast(s)->m_function_signature; + } else if( s->type == ASR::symbolType::Variable ) { + return ASR::down_cast(s)->m_type; + } else { + // ICE: only Function and Variable have types, this symbol + // does not have a type + LCOMPILERS_ASSERT_MSG(false, std::to_string(s->type)); + } + return nullptr; + } + case ASR::exprType::FunctionParam: { return ((ASR::FunctionParam_t*)f)->m_type; } + case ASR::exprType::ArrayConstructor: { return ((ASR::ArrayConstructor_t*)f)->m_type; } + case ASR::exprType::ArrayConstant: { return ((ASR::ArrayConstant_t*)f)->m_type; } + case ASR::exprType::ArrayItem: { return ((ASR::ArrayItem_t*)f)->m_type; } + case ASR::exprType::ArraySection: { return ((ASR::ArraySection_t*)f)->m_type; } + case ASR::exprType::ArraySize: { return ((ASR::ArraySize_t*)f)->m_type; } + case ASR::exprType::ArrayBound: { return ((ASR::ArrayBound_t*)f)->m_type; } + case ASR::exprType::ArrayTranspose: { return ((ASR::ArrayTranspose_t*)f)->m_type; } + case ASR::exprType::ArrayPack: { return ((ASR::ArrayPack_t*)f)->m_type; } + case ASR::exprType::ArrayReshape: { return ((ASR::ArrayReshape_t*)f)->m_type; } + case ASR::exprType::ArrayAll: { return ((ASR::ArrayAll_t*)f)->m_type; } + case ASR::exprType::ArrayBroadcast: { return ((ASR::ArrayBroadcast_t*)f)->m_type; } + case ASR::exprType::BitCast: { return ((ASR::BitCast_t*)f)->m_type; } + case ASR::exprType::StructInstanceMember: { return ((ASR::StructInstanceMember_t*)f)->m_type; } + case ASR::exprType::StructStaticMember: { return ((ASR::StructStaticMember_t*)f)->m_type; } + case ASR::exprType::EnumStaticMember: { return ((ASR::EnumStaticMember_t*)f)->m_type; } + case ASR::exprType::UnionInstanceMember: { return ((ASR::UnionInstanceMember_t*)f)->m_type; } + case ASR::exprType::EnumName: { return ((ASR::EnumName_t*)f)->m_type; } + case ASR::exprType::EnumValue: { return ((ASR::EnumValue_t*)f)->m_type; } + case ASR::exprType::OverloadedCompare: { return ((ASR::OverloadedCompare_t*)f)->m_type; } + case ASR::exprType::OverloadedBinOp: { return expr_type0(((ASR::OverloadedBinOp_t*)f)->m_overloaded); } + case ASR::exprType::OverloadedUnaryMinus: { return ((ASR::OverloadedUnaryMinus_t*)f)->m_type; } + case ASR::exprType::OverloadedStringConcat: { return ((ASR::OverloadedStringConcat_t*)f)->m_type; } + case ASR::exprType::Cast: { return ((ASR::Cast_t*)f)->m_type; } + case ASR::exprType::ArrayPhysicalCast: { return ((ASR::ArrayPhysicalCast_t*)f)->m_type; } + case ASR::exprType::ComplexRe: { return ((ASR::ComplexRe_t*)f)->m_type; } + case ASR::exprType::ComplexIm: { return ((ASR::ComplexIm_t*)f)->m_type; } + case ASR::exprType::DictItem: { return ((ASR::DictItem_t*)f)->m_type; } + case ASR::exprType::CLoc: { return ((ASR::CLoc_t*)f)->m_type; } + case ASR::exprType::PointerToCPtr: { return ((ASR::PointerToCPtr_t*)f)->m_type; } + case ASR::exprType::GetPointer: { return ((ASR::GetPointer_t*)f)->m_type; } + case ASR::exprType::ListItem: { return ((ASR::ListItem_t*)f)->m_type; } + case ASR::exprType::TupleItem: { return ((ASR::TupleItem_t*)f)->m_type; } + case ASR::exprType::ListSection: { return ((ASR::ListSection_t*)f)->m_type; } + case ASR::exprType::ListRepeat: { return ((ASR::ListRepeat_t*)f)->m_type; } + case ASR::exprType::DictPop: { return ((ASR::DictPop_t*)f)->m_type; } + case ASR::exprType::SetPop: { return ((ASR::SetPop_t*)f)->m_type; } + case ASR::exprType::SetContains: { return ((ASR::SetContains_t*)f)->m_type; } + case ASR::exprType::DictContains: { return ((ASR::DictContains_t*)f)->m_type; } + case ASR::exprType::IntegerBitLen: { return ((ASR::IntegerBitLen_t*)f)->m_type; } + case ASR::exprType::Ichar: { return ((ASR::Ichar_t*)f)->m_type; } + case ASR::exprType::Iachar: { return ((ASR::Iachar_t*)f)->m_type; } + case ASR::exprType::SizeOfType: { return ((ASR::SizeOfType_t*)f)->m_type; } + case ASR::exprType::PointerNullConstant: { return ((ASR::PointerNullConstant_t*)f)->m_type; } + case ASR::exprType::PointerAssociated: { return ((ASR::PointerAssociated_t*)f)->m_type; } + case ASR::exprType::RealSqrt: { return ((ASR::RealSqrt_t*)f)->m_type; } + case ASR::exprType::ArrayIsContiguous: { return ((ASR::ArrayIsContiguous_t*)f)->m_type; } + default : throw LCompilersException("Not implemented"); + } +} + + + +} diff --git a/src/libasr/asr_expr_value_visitor.h b/src/libasr/asr_expr_value_visitor.h new file mode 100644 index 0000000000..448bc6c7db --- /dev/null +++ b/src/libasr/asr_expr_value_visitor.h @@ -0,0 +1,154 @@ +#pragma once + +// Generated by grammar/asdl_cpp.py + +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace LCompilers::ASR { +/******************************************************************************/ +// Expression Value (`expr_value`) visitor +static inline ASR::expr_t* expr_value0(ASR::expr_t *f) +{ + LCOMPILERS_ASSERT(f != nullptr); + switch (f->type) { + case ASR::exprType::IfExp: { return ((ASR::IfExp_t*)f)->m_value; } + case ASR::exprType::ComplexConstructor: { return ((ASR::ComplexConstructor_t*)f)->m_value; } + case ASR::exprType::NamedExpr: { return ((ASR::NamedExpr_t*)f)->m_value; } + case ASR::exprType::FunctionCall: { return ((ASR::FunctionCall_t*)f)->m_value; } + case ASR::exprType::IntrinsicElementalFunction: { return ((ASR::IntrinsicElementalFunction_t*)f)->m_value; } + case ASR::exprType::IntrinsicArrayFunction: { return ((ASR::IntrinsicArrayFunction_t*)f)->m_value; } + case ASR::exprType::IntrinsicImpureFunction: { return ((ASR::IntrinsicImpureFunction_t*)f)->m_value; } + case ASR::exprType::TypeInquiry: { return ((ASR::TypeInquiry_t*)f)->m_value; } + case ASR::exprType::StructConstructor: { return ((ASR::StructConstructor_t*)f)->m_value; } + case ASR::exprType::StructConstant: { return f; } + case ASR::exprType::EnumConstructor: { return ((ASR::EnumConstructor_t*)f)->m_value; } + case ASR::exprType::UnionConstructor: { return ((ASR::UnionConstructor_t*)f)->m_value; } + case ASR::exprType::ImpliedDoLoop: { return ((ASR::ImpliedDoLoop_t*)f)->m_value; } + case ASR::exprType::IntegerConstant: { return f; } + case ASR::exprType::IntegerBitNot: { return ((ASR::IntegerBitNot_t*)f)->m_value; } + case ASR::exprType::IntegerUnaryMinus: { return ((ASR::IntegerUnaryMinus_t*)f)->m_value; } + case ASR::exprType::IntegerCompare: { return ((ASR::IntegerCompare_t*)f)->m_value; } + case ASR::exprType::IntegerBinOp: { return ((ASR::IntegerBinOp_t*)f)->m_value; } + case ASR::exprType::UnsignedIntegerConstant: { return f; } + case ASR::exprType::UnsignedIntegerUnaryMinus: { return ((ASR::UnsignedIntegerUnaryMinus_t*)f)->m_value; } + case ASR::exprType::UnsignedIntegerBitNot: { return ((ASR::UnsignedIntegerBitNot_t*)f)->m_value; } + case ASR::exprType::UnsignedIntegerCompare: { return ((ASR::UnsignedIntegerCompare_t*)f)->m_value; } + case ASR::exprType::UnsignedIntegerBinOp: { return ((ASR::UnsignedIntegerBinOp_t*)f)->m_value; } + case ASR::exprType::RealConstant: { return f; } + case ASR::exprType::RealUnaryMinus: { return ((ASR::RealUnaryMinus_t*)f)->m_value; } + case ASR::exprType::RealCompare: { return ((ASR::RealCompare_t*)f)->m_value; } + case ASR::exprType::RealBinOp: { return ((ASR::RealBinOp_t*)f)->m_value; } + case ASR::exprType::RealCopySign: { return ((ASR::RealCopySign_t*)f)->m_value; } + case ASR::exprType::ComplexConstant: { return f; } + case ASR::exprType::ComplexUnaryMinus: { return ((ASR::ComplexUnaryMinus_t*)f)->m_value; } + case ASR::exprType::ComplexCompare: { return ((ASR::ComplexCompare_t*)f)->m_value; } + case ASR::exprType::ComplexBinOp: { return ((ASR::ComplexBinOp_t*)f)->m_value; } + case ASR::exprType::LogicalConstant: { return f; } + case ASR::exprType::LogicalNot: { return ((ASR::LogicalNot_t*)f)->m_value; } + case ASR::exprType::LogicalCompare: { return ((ASR::LogicalCompare_t*)f)->m_value; } + case ASR::exprType::LogicalBinOp: { return ((ASR::LogicalBinOp_t*)f)->m_value; } + case ASR::exprType::ListConstant: { return f; } + case ASR::exprType::ListLen: { return ((ASR::ListLen_t*)f)->m_value; } + case ASR::exprType::ListConcat: { return ((ASR::ListConcat_t*)f)->m_value; } + case ASR::exprType::ListCompare: { return ((ASR::ListCompare_t*)f)->m_value; } + case ASR::exprType::ListCount: { return ((ASR::ListCount_t*)f)->m_value; } + case ASR::exprType::ListContains: { return ((ASR::ListContains_t*)f)->m_value; } + case ASR::exprType::SetConstant: { return f; } + case ASR::exprType::SetLen: { return ((ASR::SetLen_t*)f)->m_value; } + case ASR::exprType::TupleConstant: { return f; } + case ASR::exprType::TupleLen: { return ((ASR::TupleLen_t*)f)->m_value; } + case ASR::exprType::TupleCompare: { return ((ASR::TupleCompare_t*)f)->m_value; } + case ASR::exprType::TupleConcat: { return ((ASR::TupleConcat_t*)f)->m_value; } + case ASR::exprType::TupleContains: { return ((ASR::TupleContains_t*)f)->m_value; } + case ASR::exprType::StringConstant: { return f; } + case ASR::exprType::StringConcat: { return ((ASR::StringConcat_t*)f)->m_value; } + case ASR::exprType::StringRepeat: { return ((ASR::StringRepeat_t*)f)->m_value; } + case ASR::exprType::StringLen: { return ((ASR::StringLen_t*)f)->m_value; } + case ASR::exprType::StringItem: { return ((ASR::StringItem_t*)f)->m_value; } + case ASR::exprType::StringSection: { return ((ASR::StringSection_t*)f)->m_value; } + case ASR::exprType::StringCompare: { return ((ASR::StringCompare_t*)f)->m_value; } + case ASR::exprType::StringContains: { return ((ASR::StringContains_t*)f)->m_value; } + case ASR::exprType::StringOrd: { return ((ASR::StringOrd_t*)f)->m_value; } + case ASR::exprType::StringChr: { return ((ASR::StringChr_t*)f)->m_value; } + case ASR::exprType::StringFormat: { return ((ASR::StringFormat_t*)f)->m_value; } + case ASR::exprType::StringPhysicalCast: { return ((ASR::StringPhysicalCast_t*)f)->m_value; } + case ASR::exprType::CPtrCompare: { return ((ASR::CPtrCompare_t*)f)->m_value; } + case ASR::exprType::SymbolicCompare: { return ((ASR::SymbolicCompare_t*)f)->m_value; } + case ASR::exprType::DictConstant: { return f; } + case ASR::exprType::DictLen: { return ((ASR::DictLen_t*)f)->m_value; } + case ASR::exprType::Var: { + ASR::symbol_t *s = ((ASR::Var_t*)f)->m_v; + if (s->type == ASR::symbolType::ExternalSymbol) { + ASR::ExternalSymbol_t *e = ASR::down_cast(s); + LCOMPILERS_ASSERT(!ASR::is_a(*e->m_external)); + s = e->m_external; + } + if( ASR::is_a(*s) || + ASR::down_cast(s)->m_storage != + ASR::storage_typeType::Parameter ) { + return nullptr; + } + return ASR::down_cast(s)->m_value; + } + case ASR::exprType::FunctionParam: { return ((ASR::FunctionParam_t*)f)->m_value; } + case ASR::exprType::ArrayConstructor: { return ((ASR::ArrayConstructor_t*)f)->m_value; } + case ASR::exprType::ArrayConstant: { return f; } + case ASR::exprType::ArrayItem: { return ((ASR::ArrayItem_t*)f)->m_value; } + case ASR::exprType::ArraySection: { return ((ASR::ArraySection_t*)f)->m_value; } + case ASR::exprType::ArraySize: { return ((ASR::ArraySize_t*)f)->m_value; } + case ASR::exprType::ArrayBound: { return ((ASR::ArrayBound_t*)f)->m_value; } + case ASR::exprType::ArrayTranspose: { return ((ASR::ArrayTranspose_t*)f)->m_value; } + case ASR::exprType::ArrayPack: { return ((ASR::ArrayPack_t*)f)->m_value; } + case ASR::exprType::ArrayReshape: { return ((ASR::ArrayReshape_t*)f)->m_value; } + case ASR::exprType::ArrayAll: { return ((ASR::ArrayAll_t*)f)->m_value; } + case ASR::exprType::ArrayBroadcast: { return ((ASR::ArrayBroadcast_t*)f)->m_value; } + case ASR::exprType::BitCast: { return ((ASR::BitCast_t*)f)->m_value; } + case ASR::exprType::StructInstanceMember: { return ((ASR::StructInstanceMember_t*)f)->m_value; } + case ASR::exprType::StructStaticMember: { return ((ASR::StructStaticMember_t*)f)->m_value; } + case ASR::exprType::EnumStaticMember: { return ((ASR::EnumStaticMember_t*)f)->m_value; } + case ASR::exprType::UnionInstanceMember: { return ((ASR::UnionInstanceMember_t*)f)->m_value; } + case ASR::exprType::EnumName: { return ((ASR::EnumName_t*)f)->m_value; } + case ASR::exprType::EnumValue: { return ((ASR::EnumValue_t*)f)->m_value; } + case ASR::exprType::OverloadedCompare: { return ((ASR::OverloadedCompare_t*)f)->m_value; } + case ASR::exprType::OverloadedBinOp: { return ((ASR::OverloadedBinOp_t*)f)->m_value; } + case ASR::exprType::OverloadedUnaryMinus: { return ((ASR::OverloadedUnaryMinus_t*)f)->m_value; } + case ASR::exprType::OverloadedStringConcat: { return ((ASR::OverloadedStringConcat_t*)f)->m_value; } + case ASR::exprType::Cast: { return ((ASR::Cast_t*)f)->m_value; } + case ASR::exprType::ArrayPhysicalCast: { return ((ASR::ArrayPhysicalCast_t*)f)->m_value; } + case ASR::exprType::ComplexRe: { return ((ASR::ComplexRe_t*)f)->m_value; } + case ASR::exprType::ComplexIm: { return ((ASR::ComplexIm_t*)f)->m_value; } + case ASR::exprType::DictItem: { return ((ASR::DictItem_t*)f)->m_value; } + case ASR::exprType::CLoc: { return ((ASR::CLoc_t*)f)->m_value; } + case ASR::exprType::PointerToCPtr: { return ((ASR::PointerToCPtr_t*)f)->m_value; } + case ASR::exprType::GetPointer: { return ((ASR::GetPointer_t*)f)->m_value; } + case ASR::exprType::ListItem: { return ((ASR::ListItem_t*)f)->m_value; } + case ASR::exprType::TupleItem: { return ((ASR::TupleItem_t*)f)->m_value; } + case ASR::exprType::ListSection: { return ((ASR::ListSection_t*)f)->m_value; } + case ASR::exprType::ListRepeat: { return ((ASR::ListRepeat_t*)f)->m_value; } + case ASR::exprType::DictPop: { return ((ASR::DictPop_t*)f)->m_value; } + case ASR::exprType::SetPop: { return ((ASR::SetPop_t*)f)->m_value; } + case ASR::exprType::SetContains: { return ((ASR::SetContains_t*)f)->m_value; } + case ASR::exprType::DictContains: { return ((ASR::DictContains_t*)f)->m_value; } + case ASR::exprType::IntegerBitLen: { return ((ASR::IntegerBitLen_t*)f)->m_value; } + case ASR::exprType::Ichar: { return ((ASR::Ichar_t*)f)->m_value; } + case ASR::exprType::Iachar: { return ((ASR::Iachar_t*)f)->m_value; } + case ASR::exprType::SizeOfType: { return ((ASR::SizeOfType_t*)f)->m_value; } + case ASR::exprType::PointerNullConstant: { return f; } + case ASR::exprType::PointerAssociated: { return ((ASR::PointerAssociated_t*)f)->m_value; } + case ASR::exprType::RealSqrt: { return ((ASR::RealSqrt_t*)f)->m_value; } + case ASR::exprType::ArrayIsContiguous: { return ((ASR::ArrayIsContiguous_t*)f)->m_value; } + default : throw LCompilersException("Not implemented"); + } +} + + + +} diff --git a/src/libasr/asr_json_visitor.h b/src/libasr/asr_json_visitor.h new file mode 100644 index 0000000000..fa90146809 --- /dev/null +++ b/src/libasr/asr_json_visitor.h @@ -0,0 +1,7794 @@ +#pragma once + +// Generated by grammar/asdl_cpp.py + +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace LCompilers::ASR { +/******************************************************************************/ +// Json Visitor base class + +template +class JsonBaseVisitor : public BaseVisitor +{ +private: + StructType& self() { return static_cast(*this); } +public: + std::string s, indtd = ""; + bool no_loc = false; + int indent_level = 0, indent_spaces = 4; + LocationManager &lm; +public: + JsonBaseVisitor(LocationManager &lmref) : lm(lmref) { + s.reserve(100000); + } + void inc_indent() { + indent_level++; + indtd = std::string(indent_level*indent_spaces, ' '); + } + void dec_indent() { + indent_level--; + LCOMPILERS_ASSERT(indent_level >= 0); + indtd = std::string(indent_level*indent_spaces, ' '); + } + void append_location(std::string &s, uint32_t first, uint32_t last) { + if (no_loc) return; + s.append(",\n" + indtd); + s.append("\"loc\": {"); + inc_indent(); + s.append("\n" + indtd); + s.append("\"first\": " + std::to_string(first)); + s.append(",\n" + indtd); + s.append("\"last\": " + std::to_string(last)); + + uint32_t first_line = 0, first_col = 0; + std::string first_filename; + uint32_t last_line = 0, last_col = 0; + std::string last_filename; + + lm.pos_to_linecol(first, first_line, first_col, first_filename); + lm.pos_to_linecol(last, last_line, last_col, last_filename); + + s.append(",\n" + indtd); + s.append("\"first_filename\": \"" + first_filename + "\""); + s.append(",\n" + indtd); + s.append("\"first_line\": " + std::to_string(first_line)); + s.append(",\n" + indtd); + s.append("\"first_column\": " + std::to_string(first_col)); + s.append(",\n" + indtd); + s.append("\"last_filename\": \"" + last_filename + "\""); + s.append(",\n" + indtd); + s.append("\"last_line\": " + std::to_string(last_line)); + s.append(",\n" + indtd); + s.append("\"last_column\": " + std::to_string(last_col)); + + dec_indent(); + s.append("\n" + indtd); + s.append("}"); + } + void visit_TranslationUnit(const TranslationUnit_t &x) { + s.append("{"); + inc_indent(); s.append("\n" + indtd); + s.append("\"node\": \"TranslationUnit\""); + s.append(",\n" + indtd); + s.append("\"fields\": {"); + inc_indent(); s.append("\n" + indtd); + s.append("\"symtab\": "); + s.append("{"); + inc_indent(); s.append("\n" + indtd); + s.append("\"node\": \"SymbolTable" + x.m_symtab->get_counter() +"\""); + s.append(",\n" + indtd); + s.append("\"fields\": {"); + if (x.m_symtab->get_scope().size() > 0) { + inc_indent(); s.append("\n" + indtd); + size_t i = 0; + for (auto &a : x.m_symtab->get_scope()) { + s.append("\"" + a.first + "\": "); + this->visit_symbol(*a.second); + if (i < x.m_symtab->get_scope().size()-1) { + s.append(",\n" + indtd); + } + i++; + } + dec_indent(); s.append("\n" + indtd); + } + s.append("}"); + dec_indent(); s.append("\n" + indtd); + s.append("}"); + s.append(",\n" + indtd); + s.append("\"items\": "); + s.append("["); + if (x.n_items > 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; iget_counter() +"\""); + s.append(",\n" + indtd); + s.append("\"fields\": {"); + if (x.m_symtab->get_scope().size() > 0) { + inc_indent(); s.append("\n" + indtd); + size_t i = 0; + for (auto &a : x.m_symtab->get_scope()) { + s.append("\"" + a.first + "\": "); + this->visit_symbol(*a.second); + if (i < x.m_symtab->get_scope().size()-1) { + s.append(",\n" + indtd); + } + i++; + } + dec_indent(); s.append("\n" + indtd); + } + s.append("}"); + dec_indent(); s.append("\n" + indtd); + s.append("}"); + s.append(",\n" + indtd); + s.append("\"name\": "); + s.append("\"" + std::string(x.m_name) + "\""); + s.append(",\n" + indtd); + s.append("\"dependencies\": "); + s.append("["); + if (x.n_dependencies > 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; iget_counter() +"\""); + s.append(",\n" + indtd); + s.append("\"fields\": {"); + if (x.m_symtab->get_scope().size() > 0) { + inc_indent(); s.append("\n" + indtd); + size_t i = 0; + for (auto &a : x.m_symtab->get_scope()) { + s.append("\"" + a.first + "\": "); + this->visit_symbol(*a.second); + if (i < x.m_symtab->get_scope().size()-1) { + s.append(",\n" + indtd); + } + i++; + } + dec_indent(); s.append("\n" + indtd); + } + s.append("}"); + dec_indent(); s.append("\n" + indtd); + s.append("}"); + s.append(",\n" + indtd); + s.append("\"name\": "); + s.append("\"" + std::string(x.m_name) + "\""); + s.append(",\n" + indtd); + s.append("\"dependencies\": "); + s.append("["); + if (x.n_dependencies > 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; iget_counter() +"\""); + s.append(",\n" + indtd); + s.append("\"fields\": {"); + if (x.m_symtab->get_scope().size() > 0) { + inc_indent(); s.append("\n" + indtd); + size_t i = 0; + for (auto &a : x.m_symtab->get_scope()) { + s.append("\"" + a.first + "\": "); + this->visit_symbol(*a.second); + if (i < x.m_symtab->get_scope().size()-1) { + s.append(",\n" + indtd); + } + i++; + } + dec_indent(); s.append("\n" + indtd); + } + s.append("}"); + dec_indent(); s.append("\n" + indtd); + s.append("}"); + s.append(",\n" + indtd); + s.append("\"name\": "); + s.append("\"" + std::string(x.m_name) + "\""); + s.append(",\n" + indtd); + s.append("\"function_signature\": "); + self().visit_ttype(*x.m_function_signature); + s.append(",\n" + indtd); + s.append("\"dependencies\": "); + s.append("["); + if (x.n_dependencies > 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; iget_counter()); + s.append(",\n" + indtd); + s.append("\"name\": "); + s.append("\"" + std::string(x.m_name) + "\""); + s.append(",\n" + indtd); + s.append("\"procs\": "); + s.append("["); + if (x.n_procs > 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; iget_counter()); + s.append(",\n" + indtd); + s.append("\"name\": "); + s.append("\"" + std::string(x.m_name) + "\""); + s.append(",\n" + indtd); + s.append("\"procs\": "); + s.append("["); + if (x.n_procs > 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; iget_counter()); + s.append(",\n" + indtd); + s.append("\"name\": "); + s.append("\"" + std::string(x.m_name) + "\""); + s.append(",\n" + indtd); + s.append("\"external\": "); + self().visit_symbol(*x.m_external); + s.append(",\n" + indtd); + s.append("\"module_name\": "); + s.append("\"" + std::string(x.m_module_name) + "\""); + s.append(",\n" + indtd); + s.append("\"scope_names\": "); + s.append("["); + if (x.n_scope_names > 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; iget_counter() +"\""); + s.append(",\n" + indtd); + s.append("\"fields\": {"); + if (x.m_symtab->get_scope().size() > 0) { + inc_indent(); s.append("\n" + indtd); + size_t i = 0; + for (auto &a : x.m_symtab->get_scope()) { + s.append("\"" + a.first + "\": "); + this->visit_symbol(*a.second); + if (i < x.m_symtab->get_scope().size()-1) { + s.append(",\n" + indtd); + } + i++; + } + dec_indent(); s.append("\n" + indtd); + } + s.append("}"); + dec_indent(); s.append("\n" + indtd); + s.append("}"); + s.append(",\n" + indtd); + s.append("\"name\": "); + s.append("\"" + std::string(x.m_name) + "\""); + s.append(",\n" + indtd); + s.append("\"dependencies\": "); + s.append("["); + if (x.n_dependencies > 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; iget_counter() +"\""); + s.append(",\n" + indtd); + s.append("\"fields\": {"); + if (x.m_symtab->get_scope().size() > 0) { + inc_indent(); s.append("\n" + indtd); + size_t i = 0; + for (auto &a : x.m_symtab->get_scope()) { + s.append("\"" + a.first + "\": "); + this->visit_symbol(*a.second); + if (i < x.m_symtab->get_scope().size()-1) { + s.append(",\n" + indtd); + } + i++; + } + dec_indent(); s.append("\n" + indtd); + } + s.append("}"); + dec_indent(); s.append("\n" + indtd); + s.append("}"); + s.append(",\n" + indtd); + s.append("\"name\": "); + s.append("\"" + std::string(x.m_name) + "\""); + s.append(",\n" + indtd); + s.append("\"dependencies\": "); + s.append("["); + if (x.n_dependencies > 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; iget_counter() +"\""); + s.append(",\n" + indtd); + s.append("\"fields\": {"); + if (x.m_symtab->get_scope().size() > 0) { + inc_indent(); s.append("\n" + indtd); + size_t i = 0; + for (auto &a : x.m_symtab->get_scope()) { + s.append("\"" + a.first + "\": "); + this->visit_symbol(*a.second); + if (i < x.m_symtab->get_scope().size()-1) { + s.append(",\n" + indtd); + } + i++; + } + dec_indent(); s.append("\n" + indtd); + } + s.append("}"); + dec_indent(); s.append("\n" + indtd); + s.append("}"); + s.append(",\n" + indtd); + s.append("\"name\": "); + s.append("\"" + std::string(x.m_name) + "\""); + s.append(",\n" + indtd); + s.append("\"dependencies\": "); + s.append("["); + if (x.n_dependencies > 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; iget_counter()); + s.append(",\n" + indtd); + s.append("\"name\": "); + s.append("\"" + std::string(x.m_name) + "\""); + s.append(",\n" + indtd); + s.append("\"dependencies\": "); + s.append("["); + if (x.n_dependencies > 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; iget_counter() +"\""); + s.append(",\n" + indtd); + s.append("\"fields\": {"); + if (x.m_symtab->get_scope().size() > 0) { + inc_indent(); s.append("\n" + indtd); + size_t i = 0; + for (auto &a : x.m_symtab->get_scope()) { + s.append("\"" + a.first + "\": "); + this->visit_symbol(*a.second); + if (i < x.m_symtab->get_scope().size()-1) { + s.append(",\n" + indtd); + } + i++; + } + dec_indent(); s.append("\n" + indtd); + } + s.append("}"); + dec_indent(); s.append("\n" + indtd); + s.append("}"); + s.append(",\n" + indtd); + s.append("\"name\": "); + s.append("\"" + std::string(x.m_name) + "\""); + s.append(",\n" + indtd); + s.append("\"abi\": "); + visit_abiType(x.m_abi); + s.append(",\n" + indtd); + s.append("\"access\": "); + visit_accessType(x.m_access); + dec_indent(); s.append("\n" + indtd); + s.append("}"); + append_location(s, x.base.base.loc.first, x.base.base.loc.last); + dec_indent(); s.append("\n" + indtd); + s.append("}"); + if ((bool&)x) { } // Suppress unused warning + } + void visit_ClassProcedure(const ClassProcedure_t &x) { + s.append("{"); + inc_indent(); s.append("\n" + indtd); + s.append("\"node\": \"ClassProcedure\""); + s.append(",\n" + indtd); + s.append("\"fields\": {"); + inc_indent(); s.append("\n" + indtd); + s.append("\"parent_symtab\": "); + s.append(x.m_parent_symtab->get_counter()); + s.append(",\n" + indtd); + s.append("\"name\": "); + s.append("\"" + std::string(x.m_name) + "\""); + s.append(",\n" + indtd); + s.append("\"self_argument\": "); + if (x.m_self_argument) { + s.append("\"" + std::string(x.m_self_argument) + "\""); + } else { + s.append("[]"); + } + s.append(",\n" + indtd); + s.append("\"proc_name\": "); + s.append("\"" + std::string(x.m_proc_name) + "\""); + s.append(",\n" + indtd); + s.append("\"proc\": "); + self().visit_symbol(*x.m_proc); + s.append(",\n" + indtd); + s.append("\"abi\": "); + visit_abiType(x.m_abi); + s.append(",\n" + indtd); + s.append("\"is_deferred\": "); + if (x.m_is_deferred) { + s.append("true"); + } else { + s.append("false"); + } + s.append(",\n" + indtd); + s.append("\"is_nopass\": "); + if (x.m_is_nopass) { + s.append("true"); + } else { + s.append("false"); + } + dec_indent(); s.append("\n" + indtd); + s.append("}"); + append_location(s, x.base.base.loc.first, x.base.base.loc.last); + dec_indent(); s.append("\n" + indtd); + s.append("}"); + if ((bool&)x) { } // Suppress unused warning + } + void visit_AssociateBlock(const AssociateBlock_t &x) { + s.append("{"); + inc_indent(); s.append("\n" + indtd); + s.append("\"node\": \"AssociateBlock\""); + s.append(",\n" + indtd); + s.append("\"fields\": {"); + inc_indent(); s.append("\n" + indtd); + s.append("\"symtab\": "); + s.append("{"); + inc_indent(); s.append("\n" + indtd); + s.append("\"node\": \"SymbolTable" + x.m_symtab->get_counter() +"\""); + s.append(",\n" + indtd); + s.append("\"fields\": {"); + if (x.m_symtab->get_scope().size() > 0) { + inc_indent(); s.append("\n" + indtd); + size_t i = 0; + for (auto &a : x.m_symtab->get_scope()) { + s.append("\"" + a.first + "\": "); + this->visit_symbol(*a.second); + if (i < x.m_symtab->get_scope().size()-1) { + s.append(",\n" + indtd); + } + i++; + } + dec_indent(); s.append("\n" + indtd); + } + s.append("}"); + dec_indent(); s.append("\n" + indtd); + s.append("}"); + s.append(",\n" + indtd); + s.append("\"name\": "); + s.append("\"" + std::string(x.m_name) + "\""); + s.append(",\n" + indtd); + s.append("\"body\": "); + s.append("["); + if (x.n_body > 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; iget_counter() +"\""); + s.append(",\n" + indtd); + s.append("\"fields\": {"); + if (x.m_symtab->get_scope().size() > 0) { + inc_indent(); s.append("\n" + indtd); + size_t i = 0; + for (auto &a : x.m_symtab->get_scope()) { + s.append("\"" + a.first + "\": "); + this->visit_symbol(*a.second); + if (i < x.m_symtab->get_scope().size()-1) { + s.append(",\n" + indtd); + } + i++; + } + dec_indent(); s.append("\n" + indtd); + } + s.append("}"); + dec_indent(); s.append("\n" + indtd); + s.append("}"); + s.append(",\n" + indtd); + s.append("\"name\": "); + s.append("\"" + std::string(x.m_name) + "\""); + s.append(",\n" + indtd); + s.append("\"body\": "); + s.append("["); + if (x.n_body > 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; iget_counter() +"\""); + s.append(",\n" + indtd); + s.append("\"fields\": {"); + if (x.m_symtab->get_scope().size() > 0) { + inc_indent(); s.append("\n" + indtd); + size_t i = 0; + for (auto &a : x.m_symtab->get_scope()) { + s.append("\"" + a.first + "\": "); + this->visit_symbol(*a.second); + if (i < x.m_symtab->get_scope().size()-1) { + s.append(",\n" + indtd); + } + i++; + } + dec_indent(); s.append("\n" + indtd); + } + s.append("}"); + dec_indent(); s.append("\n" + indtd); + s.append("}"); + s.append(",\n" + indtd); + s.append("\"name\": "); + s.append("\"" + std::string(x.m_name) + "\""); + s.append(",\n" + indtd); + s.append("\"args\": "); + s.append("["); + if (x.n_args > 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; iget_counter() +"\""); + s.append(",\n" + indtd); + s.append("\"fields\": {"); + if (x.m_symtab->get_scope().size() > 0) { + inc_indent(); s.append("\n" + indtd); + size_t i = 0; + for (auto &a : x.m_symtab->get_scope()) { + s.append("\"" + a.first + "\": "); + this->visit_symbol(*a.second); + if (i < x.m_symtab->get_scope().size()-1) { + s.append(",\n" + indtd); + } + i++; + } + dec_indent(); s.append("\n" + indtd); + } + s.append("}"); + dec_indent(); s.append("\n" + indtd); + s.append("}"); + s.append(",\n" + indtd); + s.append("\"name\": "); + s.append("\"" + std::string(x.m_name) + "\""); + s.append(",\n" + indtd); + s.append("\"args\": "); + s.append("["); + if (x.n_args > 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i 0) { + inc_indent(); s.append("\n" + indtd); + for (size_t i=0; i +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace LCompilers::LFortran { + class LookupNameVisitor : public ASR::DefaultLookupNameVisitor { + public: + LookupNameVisitor(uint16_t pos) { + this->pos = pos; + } + void visit_ExternalSymbol(const ASR::ExternalSymbol_t &x) { + if ((bool&)x) { } // Suppress unused warning + if (test_loc_and_set_span(x.base.base.loc)) { + const ASR::symbol_t* sym = this->symbol_get_past_external_(x.m_external); + this->handle_symbol(sym); + if ( ASR::is_a(*sym) ) { + this->handle_symbol(ASR::down_cast(sym)->m_proc); + } + } + } + void visit_FunctionCall(const ASR::FunctionCall_t &x) { + for (size_t i=0; ivisit_call_arg(x.m_args[i]); + } + this->visit_ttype(*x.m_type); + if (x.m_value) + this->visit_expr(*x.m_value); + if (x.m_dt) + this->visit_expr(*x.m_dt); + if (test_loc_and_set_span(x.base.base.loc)) { + const ASR::symbol_t* sym = this->symbol_get_past_external_(x.m_name); + this->handle_symbol(sym); + if ( ASR::is_a(*sym) ) { + this->handle_symbol(ASR::down_cast(sym)->m_proc); + } + } + } + }; + + + class OccurenceCollector: public ASR::BaseWalkVisitor { + public: + std::string symbol_name; + std::vector &symbol_lists; + LCompilers::LocationManager lm; + OccurenceCollector(std::string symbol_name, std::vector &symbol_lists, + LCompilers::LocationManager lm) : symbol_lists(symbol_lists) { + this->symbol_name = symbol_name; + this->lm = lm; + } + + void populate_document_symbol_and_push(const Location& loc, ASR::symbolType type) { + document_symbols loc_; + uint32_t first_line; + uint32_t last_line; + uint32_t first_column; + uint32_t last_column; + std::string filename; + lm.pos_to_linecol(loc.first, first_line, + first_column, filename); + lm.pos_to_linecol(loc.last, last_line, + last_column, filename); + loc_.first_column = first_column; + loc_.last_column = last_column + 1; + loc_.first_line = first_line; + loc_.last_line = last_line; + loc_.symbol_name = symbol_name; + loc_.filename = filename; + loc_.symbol_type = type; + symbol_lists.push_back(loc_); + } + + void visit_symbol(const ASR::symbol_t& x) { + ASR::symbol_t* sym = const_cast(&x); + if ( ASRUtils::symbol_name(sym) == symbol_name ) { + if ( ASR::is_a(*sym) ) { + ASR::Function_t* f = ASR::down_cast(sym); + if ( f->m_start_name ) { + this->populate_document_symbol_and_push(*(f->m_start_name), x.type); + } + if ( f->m_end_name ) { + this->populate_document_symbol_and_push(*(f->m_end_name), x.type); + } + } else if ( ASR::is_a(*sym) ) { + ASR::Program_t* p = ASR::down_cast(sym); + if ( p->m_start_name ) { + this->populate_document_symbol_and_push(*(p->m_start_name), x.type); + } + if ( p->m_end_name ) { + this->populate_document_symbol_and_push(*(p->m_end_name), x.type); + } + } else if ( ASR::is_a(*sym) ) { + ASR::Module_t* m = ASR::down_cast(sym); + if ( m->m_start_name ) { + this->populate_document_symbol_and_push(*(m->m_start_name), x.type); + } + if ( m->m_end_name ) { + this->populate_document_symbol_and_push(*(m->m_end_name), x.type); + } + } else { + this->populate_document_symbol_and_push(x.base.loc, x.type); + } + } + ASR::BaseWalkVisitor::visit_symbol(x); + } + + void visit_Var(const ASR::Var_t& x) { + if ( ASRUtils::symbol_name(x.m_v) == symbol_name ) { + if ( ASR::is_a(*x.m_v) ) { + ASR::Function_t* f = ASR::down_cast(x.m_v); + if ( f->m_start_name ) { + this->populate_document_symbol_and_push(*(f->m_start_name), x.m_v->type); + } + if ( f->m_end_name ) { + this->populate_document_symbol_and_push(*(f->m_end_name), x.m_v->type); + } + } else if ( ASR::is_a(*x.m_v) ) { + ASR::Program_t* p = ASR::down_cast(x.m_v); + if ( p->m_start_name ) { + this->populate_document_symbol_and_push(*(p->m_start_name), x.m_v->type); + } + if ( p->m_end_name ) { + this->populate_document_symbol_and_push(*(p->m_end_name), x.m_v->type); + } + } else if ( ASR::is_a(*x.m_v) ) { + ASR::Module_t* m = ASR::down_cast(x.m_v); + if ( m->m_start_name ) { + this->populate_document_symbol_and_push(*(m->m_start_name), x.m_v->type); + } + if ( m->m_end_name ) { + this->populate_document_symbol_and_push(*(m->m_end_name), x.m_v->type); + } + } else { + this->populate_document_symbol_and_push(x.base.base.loc, x.m_v->type); + } + } + ASR::BaseWalkVisitor::visit_Var(x); + } + + // We need this visitors because we want to use the + // overwritten `visit_symbol` and not `this->visit_symbol` + // in BaseWalkVisitor we have `this->visit_symbol` which + // prevents us from using the overwritten `visit_symbol` + void visit_TranslationUnit(const ASR::TranslationUnit_t &x) { + for (auto &a : x.m_symtab->get_scope()) { + visit_symbol(*a.second); + } + } + void visit_Program(const ASR::Program_t &x) { + for (auto &a : x.m_symtab->get_scope()) { + visit_symbol(*a.second); + } + for (size_t i=0; ivisit_call_arg(x.m_args[i]); + } + if ( ASRUtils::symbol_name(x.m_name) == symbol_name ) { + this->populate_document_symbol_and_push(x.base.base.loc, ASR::symbolType::Function); + } + this->visit_ttype(*x.m_type); + if (x.m_value && visit_compile_time_value) + this->visit_expr(*x.m_value); + if (x.m_dt) + this->visit_expr(*x.m_dt); + } + void visit_Module(const ASR::Module_t &x) { + for (auto &a : x.m_symtab->get_scope()) { + visit_symbol(*a.second); + } + } + void visit_Function(const ASR::Function_t &x) { + for (auto &a : x.m_symtab->get_scope()) { + visit_symbol(*a.second); + } + visit_ttype(*x.m_function_signature); + for (size_t i=0; iget_scope()) { + visit_symbol(*a.second); + } + for (size_t i=0; iget_scope()) { + visit_symbol(*a.second); + } + visit_ttype(*x.m_type); + } + void visit_Union(const ASR::Union_t &x) { + for (auto &a : x.m_symtab->get_scope()) { + this->visit_symbol(*a.second); + } + for (size_t i=0; i +#include +#include +#include +#include +#include +#include +#include + + +namespace LCompilers::ASR { +/******************************************************************************/ +// Walk Visitor base class + +template +class DefaultLookupNameVisitor : public BaseVisitor +{ +private: + StructType& self() { return static_cast(*this); } +public: + uint16_t pos; + uint32_t min_span = UINT32_MAX; + ASR::asr_t* node_to_return = nullptr; + bool test_loc_and_set_span(Location loc) { + uint32_t first = loc.first; + uint32_t last = loc.last; + if (first <= pos && pos <= last) { + uint32_t span = last - first; + if (span < min_span) { + min_span = span; + return true; + } + } + return false; + } + void handle_symbol(const symbol_t* sym) { + switch(sym->type) { + case ASR::symbolType::Program: { + node_to_return = ( ASR::asr_t* ) ((Program_t*)sym); + return; + } + case ASR::symbolType::Module: { + node_to_return = ( ASR::asr_t* ) ((Module_t*)sym); + return; + } + case ASR::symbolType::Function: { + node_to_return = ( ASR::asr_t* ) ((Function_t*)sym); + return; + } + case ASR::symbolType::GenericProcedure: { + node_to_return = ( ASR::asr_t* ) ((GenericProcedure_t*)sym); + return; + } + case ASR::symbolType::CustomOperator: { + node_to_return = ( ASR::asr_t* ) ((CustomOperator_t*)sym); + return; + } + case ASR::symbolType::ExternalSymbol: { + node_to_return = ( ASR::asr_t* ) ((ExternalSymbol_t*)sym); + return; + } + case ASR::symbolType::Struct: { + node_to_return = ( ASR::asr_t* ) ((Struct_t*)sym); + return; + } + case ASR::symbolType::Enum: { + node_to_return = ( ASR::asr_t* ) ((Enum_t*)sym); + return; + } + case ASR::symbolType::Union: { + node_to_return = ( ASR::asr_t* ) ((Union_t*)sym); + return; + } + case ASR::symbolType::Variable: { + node_to_return = ( ASR::asr_t* ) ((Variable_t*)sym); + return; + } + case ASR::symbolType::Class: { + node_to_return = ( ASR::asr_t* ) ((Class_t*)sym); + return; + } + case ASR::symbolType::ClassProcedure: { + node_to_return = ( ASR::asr_t* ) ((ClassProcedure_t*)sym); + return; + } + case ASR::symbolType::AssociateBlock: { + node_to_return = ( ASR::asr_t* ) ((AssociateBlock_t*)sym); + return; + } + case ASR::symbolType::Block: { + node_to_return = ( ASR::asr_t* ) ((Block_t*)sym); + return; + } + case ASR::symbolType::Requirement: { + node_to_return = ( ASR::asr_t* ) ((Requirement_t*)sym); + return; + } + case ASR::symbolType::Template: { + node_to_return = ( ASR::asr_t* ) ((Template_t*)sym); + return; + } + } + } + static inline const ASR::symbol_t *symbol_get_past_external_(ASR::symbol_t *f) { + if (f->type == ASR::symbolType::ExternalSymbol) { + ASR::ExternalSymbol_t *e = ASR::down_cast(f); + LCOMPILERS_ASSERT(!ASR::is_a(*e->m_external)); + return e->m_external; + } else { + return f; + } + } + void visit_TranslationUnit(const TranslationUnit_t &x) { + for (auto &a : x.m_symtab->get_scope()) { + this->visit_symbol(*a.second); + } + if (test_loc_and_set_span(x.base.base.loc)) { + node_to_return = (ASR::asr_t*) &x; + } + } + void visit_Program(const Program_t &x) { + for (auto &a : x.m_symtab->get_scope()) { + this->visit_symbol(*a.second); + } + for (size_t i=0; iget_scope()) { + this->visit_symbol(*a.second); + } + if (test_loc_and_set_span(x.base.base.loc)) { + node_to_return = (ASR::asr_t*) &x; + } + } + void visit_Function(const Function_t &x) { + for (auto &a : x.m_symtab->get_scope()) { + this->visit_symbol(*a.second); + } + self().visit_ttype(*x.m_function_signature); + for (size_t i=0; iget_scope()) { + this->visit_symbol(*a.second); + } + for (size_t i=0; iget_scope()) { + this->visit_symbol(*a.second); + } + self().visit_ttype(*x.m_type); + if (test_loc_and_set_span(x.base.base.loc)) { + self().handle_symbol(self().symbol_get_past_external_(x.m_parent)); + } + } + void visit_Union(const Union_t &x) { + for (auto &a : x.m_symtab->get_scope()) { + this->visit_symbol(*a.second); + } + for (size_t i=0; iget_scope()) { + this->visit_symbol(*a.second); + } + if (test_loc_and_set_span(x.base.base.loc)) { + node_to_return = (ASR::asr_t*) &x; + } + } + void visit_ClassProcedure(const ClassProcedure_t &x) { + if ((bool&)x) { } // Suppress unused warning + if (test_loc_and_set_span(x.base.base.loc)) { + self().handle_symbol(self().symbol_get_past_external_(x.m_proc)); + } + } + void visit_AssociateBlock(const AssociateBlock_t &x) { + for (auto &a : x.m_symtab->get_scope()) { + this->visit_symbol(*a.second); + } + for (size_t i=0; iget_scope()) { + this->visit_symbol(*a.second); + } + for (size_t i=0; iget_scope()) { + this->visit_symbol(*a.second); + } + for (size_t i=0; iget_scope()) { + this->visit_symbol(*a.second); + } + for (size_t i=0; i +#include +#include +#include +#include +#include +#include +#include + + +namespace LCompilers::ASR { +/******************************************************************************/ +// Walk Visitor base class + +template +class ASRPassBaseWalkVisitor : public BaseVisitor +{ +private: + StructType& self() { return static_cast(*this); } +public: + SymbolTable* current_scope=nullptr; + void transform_stmts(ASR::stmt_t **&m_body, size_t &n_body) { + for (size_t i = 0; i < n_body; i++) { + self().visit_stmt(*m_body[i]); + } + } + void visit_TranslationUnit(const TranslationUnit_t &x) { + SymbolTable* current_scope_copy = current_scope; + current_scope = x.m_symtab; + for (auto &a : x.m_symtab->get_scope()) { + this->visit_symbol(*a.second); + } + current_scope = current_scope_copy; + } + void visit_Program(const Program_t &x) { + Program_t& xx = const_cast(x); + SymbolTable* current_scope_copy = current_scope; + current_scope = x.m_symtab; + for (auto &a : x.m_symtab->get_scope()) { + this->visit_symbol(*a.second); + } + self().transform_stmts(xx.m_body, xx.n_body); + current_scope = current_scope_copy; + } + void visit_Module(const Module_t &x) { + SymbolTable* current_scope_copy = current_scope; + current_scope = x.m_symtab; + for (auto &a : x.m_symtab->get_scope()) { + this->visit_symbol(*a.second); + } + current_scope = current_scope_copy; + } + void visit_Function(const Function_t &x) { + Function_t& xx = const_cast(x); + SymbolTable* current_scope_copy = current_scope; + current_scope = x.m_symtab; + for (auto &a : x.m_symtab->get_scope()) { + this->visit_symbol(*a.second); + } + self().visit_ttype(*x.m_function_signature); + for (size_t i=0; iget_scope()) { + this->visit_symbol(*a.second); + } + for (size_t i=0; iget_scope()) { + this->visit_symbol(*a.second); + } + self().visit_ttype(*x.m_type); + current_scope = current_scope_copy; + } + void visit_Union(const Union_t &x) { + SymbolTable* current_scope_copy = current_scope; + current_scope = x.m_symtab; + for (auto &a : x.m_symtab->get_scope()) { + this->visit_symbol(*a.second); + } + for (size_t i=0; iget_scope()) { + this->visit_symbol(*a.second); + } + current_scope = current_scope_copy; + } + void visit_ClassProcedure(const ClassProcedure_t &x) { + SymbolTable* current_scope_copy = current_scope; + current_scope = x.m_parent_symtab; + if ((bool&)x) { } // Suppress unused warning + current_scope = current_scope_copy; + } + void visit_AssociateBlock(const AssociateBlock_t &x) { + AssociateBlock_t& xx = const_cast(x); + SymbolTable* current_scope_copy = current_scope; + current_scope = x.m_symtab; + for (auto &a : x.m_symtab->get_scope()) { + this->visit_symbol(*a.second); + } + self().transform_stmts(xx.m_body, xx.n_body); + current_scope = current_scope_copy; + } + void visit_Block(const Block_t &x) { + Block_t& xx = const_cast(x); + SymbolTable* current_scope_copy = current_scope; + current_scope = x.m_symtab; + for (auto &a : x.m_symtab->get_scope()) { + this->visit_symbol(*a.second); + } + self().transform_stmts(xx.m_body, xx.n_body); + current_scope = current_scope_copy; + } + void visit_Requirement(const Requirement_t &x) { + SymbolTable* current_scope_copy = current_scope; + current_scope = x.m_symtab; + for (auto &a : x.m_symtab->get_scope()) { + this->visit_symbol(*a.second); + } + for (size_t i=0; iget_scope()) { + this->visit_symbol(*a.second); + } + for (size_t i=0; i(x); + for (size_t i=0; i(x); + self().visit_do_loop_head(x.m_head); + self().transform_stmts(xx.m_body, xx.n_body); + self().transform_stmts(xx.m_orelse, xx.n_orelse); + } + void visit_ErrorStop(const ErrorStop_t &x) { + if (x.m_code) + self().visit_expr(*x.m_code); + } + void visit_Exit(const Exit_t &x) { + if ((bool&)x) { } // Suppress unused warning + } + void visit_ForAllSingle(const ForAllSingle_t &x) { + self().visit_do_loop_head(x.m_head); + self().visit_stmt(*x.m_assign_stmt); + } + void visit_ForEach(const ForEach_t &x) { + ForEach_t& xx = const_cast(x); + self().visit_expr(*x.m_var); + self().visit_expr(*x.m_container); + self().transform_stmts(xx.m_body, xx.n_body); + } + void visit_GoTo(const GoTo_t &x) { + if ((bool&)x) { } // Suppress unused warning + } + void visit_GoToTarget(const GoToTarget_t &x) { + if ((bool&)x) { } // Suppress unused warning + } + void visit_If(const If_t &x) { + If_t& xx = const_cast(x); + self().visit_expr(*x.m_test); + self().transform_stmts(xx.m_body, xx.n_body); + self().transform_stmts(xx.m_orelse, xx.n_orelse); + } + void visit_IfArithmetic(const IfArithmetic_t &x) { + self().visit_expr(*x.m_test); + } + void visit_Print(const Print_t &x) { + self().visit_expr(*x.m_text); + } + void visit_FileOpen(const FileOpen_t &x) { + if (x.m_newunit) + self().visit_expr(*x.m_newunit); + if (x.m_filename) + self().visit_expr(*x.m_filename); + if (x.m_status) + self().visit_expr(*x.m_status); + if (x.m_form) + self().visit_expr(*x.m_form); + } + void visit_FileClose(const FileClose_t &x) { + if (x.m_unit) + self().visit_expr(*x.m_unit); + if (x.m_iostat) + self().visit_expr(*x.m_iostat); + if (x.m_iomsg) + self().visit_expr(*x.m_iomsg); + if (x.m_err) + self().visit_expr(*x.m_err); + if (x.m_status) + self().visit_expr(*x.m_status); + } + void visit_FileRead(const FileRead_t &x) { + if (x.m_unit) + self().visit_expr(*x.m_unit); + if (x.m_fmt) + self().visit_expr(*x.m_fmt); + if (x.m_iomsg) + self().visit_expr(*x.m_iomsg); + if (x.m_iostat) + self().visit_expr(*x.m_iostat); + if (x.m_size) + self().visit_expr(*x.m_size); + if (x.m_id) + self().visit_expr(*x.m_id); + for (size_t i=0; i(x); + self().visit_expr(*x.m_test); + for (size_t i=0; i(x); + self().visit_expr(*x.m_test); + self().transform_stmts(xx.m_body, xx.n_body); + self().transform_stmts(xx.m_orelse, xx.n_orelse); + } + void visit_WhileLoop(const WhileLoop_t &x) { + WhileLoop_t& xx = const_cast(x); + self().visit_expr(*x.m_test); + self().transform_stmts(xx.m_body, xx.n_body); + self().transform_stmts(xx.m_orelse, xx.n_orelse); + } + void visit_Nullify(const Nullify_t &x) { + for (size_t i=0; i(x); + self().visit_expr(*x.m_selector); + for (size_t i=0; i(x); + for (size_t i=0; i(x); + if (x.m_start) + self().visit_expr(*x.m_start); + if (x.m_end) + self().visit_expr(*x.m_end); + self().transform_stmts(xx.m_body, xx.n_body); + } + void visit_TypeStmtName(const TypeStmtName_t &x) { + TypeStmtName_t& xx = const_cast(x); + self().transform_stmts(xx.m_body, xx.n_body); + if ((bool&)x) { } // Suppress unused warning + } + void visit_ClassStmt(const ClassStmt_t &x) { + ClassStmt_t& xx = const_cast(x); + self().transform_stmts(xx.m_body, xx.n_body); + if ((bool&)x) { } // Suppress unused warning + } + void visit_TypeStmtType(const TypeStmtType_t &x) { + TypeStmtType_t& xx = const_cast(x); + self().visit_ttype(*x.m_type); + self().transform_stmts(xx.m_body, xx.n_body); + } + void visit_Require(const Require_t &x) { + if ((bool&)x) { } // Suppress unused warning + } +}; + + +} diff --git a/src/libasr/asr_pickle_visitor.h b/src/libasr/asr_pickle_visitor.h new file mode 100644 index 0000000000..02710d3bfa --- /dev/null +++ b/src/libasr/asr_pickle_visitor.h @@ -0,0 +1,9509 @@ +#pragma once + +// Generated by grammar/asdl_cpp.py + +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace LCompilers::ASR { +/******************************************************************************/ +// Pickle Visitor base class + +template +class PickleBaseVisitor : public BaseVisitor +{ +private: + StructType& self() { return static_cast(*this); } +public: + std::string s, indented = ""; + bool use_colors; + bool indent; + int indent_level = 0, indent_spaces = 4; +public: + PickleBaseVisitor() : use_colors(false), indent(false) { s.reserve(100000); } + void inc_indent() { + indent_level++; + indented = std::string(indent_level*indent_spaces, ' '); + } + void dec_indent() { + indent_level--; + LCOMPILERS_ASSERT(indent_level >= 0); + indented = std::string(indent_level*indent_spaces, ' '); + } + void visit_TranslationUnit(const TranslationUnit_t &x) { + s.append("("); + if (use_colors) { + s.append(color(style::bold)); + s.append(color(fg::magenta)); + } + s.append("TranslationUnit"); + if (use_colors) { + s.append(color(fg::reset)); + s.append(color(style::reset)); + } + if(indent) { + inc_indent(); + s.append("\n" + indented); + } else { + s.append(" "); + } + s.append("("); + if (use_colors) { + s.append(color(fg::yellow)); + } + s.append("SymbolTable"); + if (use_colors) { + s.append(color(fg::reset)); + } + if(indent) { + inc_indent(); + s.append("\n" + indented); + } else { + s.append(" "); + } + s.append(x.m_symtab->get_counter()); + if(indent) s.append("\n" + indented); + else s.append(" "); + s.append("{"); + if(indent) { + inc_indent(); + s.append("\n" + indented); + } + { + size_t i = 0; + for (auto &a : x.m_symtab->get_scope()) { + s.append(a.first + ":"); + if(indent) { + inc_indent(); + s.append("\n" + indented); + } else { + s.append(" "); + } + this->visit_symbol(*a.second); + if(indent) dec_indent(); + if (i < x.m_symtab->get_scope().size()-1) { + s.append(","); + if(indent) s.append("\n" + indented); + else s.append(" "); + } + i++; + } + } + if(indent) { + dec_indent(); + s.append("\n" + indented); + } + s.append("})"); + if(indent) dec_indent(); + if(indent) s.append("\n" + indented); + else s.append(" "); + s.append("["); + for (size_t i=0; iget_counter()); + if(indent) s.append("\n" + indented); + else s.append(" "); + s.append("{"); + if(indent) { + inc_indent(); + s.append("\n" + indented); + } + { + size_t i = 0; + for (auto &a : x.m_symtab->get_scope()) { + s.append(a.first + ":"); + if(indent) { + inc_indent(); + s.append("\n" + indented); + } else { + s.append(" "); + } + this->visit_symbol(*a.second); + if(indent) dec_indent(); + if (i < x.m_symtab->get_scope().size()-1) { + s.append(","); + if(indent) s.append("\n" + indented); + else s.append(" "); + } + i++; + } + } + if(indent) { + dec_indent(); + s.append("\n" + indented); + } + s.append("})"); + if(indent) dec_indent(); + if(indent) s.append("\n" + indented); + else s.append(" "); + s.append(x.m_name); + if(indent) s.append("\n" + indented); + else s.append(" "); + s.append("["); + for (size_t i=0; iget_counter()); + if(indent) s.append("\n" + indented); + else s.append(" "); + s.append("{"); + if(indent) { + inc_indent(); + s.append("\n" + indented); + } + { + size_t i = 0; + for (auto &a : x.m_symtab->get_scope()) { + s.append(a.first + ":"); + if(indent) { + inc_indent(); + s.append("\n" + indented); + } else { + s.append(" "); + } + this->visit_symbol(*a.second); + if(indent) dec_indent(); + if (i < x.m_symtab->get_scope().size()-1) { + s.append(","); + if(indent) s.append("\n" + indented); + else s.append(" "); + } + i++; + } + } + if(indent) { + dec_indent(); + s.append("\n" + indented); + } + s.append("})"); + if(indent) dec_indent(); + if(indent) s.append("\n" + indented); + else s.append(" "); + s.append(x.m_name); + if(indent) s.append("\n" + indented); + else s.append(" "); + s.append("["); + for (size_t i=0; iget_counter()); + if(indent) s.append("\n" + indented); + else s.append(" "); + s.append("{"); + if(indent) { + inc_indent(); + s.append("\n" + indented); + } + { + size_t i = 0; + for (auto &a : x.m_symtab->get_scope()) { + s.append(a.first + ":"); + if(indent) { + inc_indent(); + s.append("\n" + indented); + } else { + s.append(" "); + } + this->visit_symbol(*a.second); + if(indent) dec_indent(); + if (i < x.m_symtab->get_scope().size()-1) { + s.append(","); + if(indent) s.append("\n" + indented); + else s.append(" "); + } + i++; + } + } + if(indent) { + dec_indent(); + s.append("\n" + indented); + } + s.append("})"); + if(indent) dec_indent(); + if(indent) s.append("\n" + indented); + else s.append(" "); + s.append(x.m_name); + if(indent) s.append("\n" + indented); + else s.append(" "); + self().visit_ttype(*x.m_function_signature); + if(indent) s.append("\n" + indented); + else s.append(" "); + s.append("["); + for (size_t i=0; iget_counter()); + if(indent) s.append("\n" + indented); + else s.append(" "); + s.append(x.m_name); + if(indent) s.append("\n" + indented); + else s.append(" "); + s.append("["); + for (size_t i=0; iget_counter()); + if(indent) s.append("\n" + indented); + else s.append(" "); + s.append(x.m_name); + if(indent) s.append("\n" + indented); + else s.append(" "); + s.append("["); + for (size_t i=0; iget_counter()); + if(indent) s.append("\n" + indented); + else s.append(" "); + s.append(x.m_name); + if(indent) s.append("\n" + indented); + else s.append(" "); + self().visit_symbol(*x.m_external); + if(indent) s.append("\n" + indented); + else s.append(" "); + s.append(x.m_module_name); + if(indent) s.append("\n" + indented); + else s.append(" "); + s.append("["); + for (size_t i=0; iget_counter()); + if(indent) s.append("\n" + indented); + else s.append(" "); + s.append("{"); + if(indent) { + inc_indent(); + s.append("\n" + indented); + } + { + size_t i = 0; + for (auto &a : x.m_symtab->get_scope()) { + s.append(a.first + ":"); + if(indent) { + inc_indent(); + s.append("\n" + indented); + } else { + s.append(" "); + } + this->visit_symbol(*a.second); + if(indent) dec_indent(); + if (i < x.m_symtab->get_scope().size()-1) { + s.append(","); + if(indent) s.append("\n" + indented); + else s.append(" "); + } + i++; + } + } + if(indent) { + dec_indent(); + s.append("\n" + indented); + } + s.append("})"); + if(indent) dec_indent(); + if(indent) s.append("\n" + indented); + else s.append(" "); + s.append(x.m_name); + if(indent) s.append("\n" + indented); + else s.append(" "); + s.append("["); + for (size_t i=0; iget_counter()); + if(indent) s.append("\n" + indented); + else s.append(" "); + s.append("{"); + if(indent) { + inc_indent(); + s.append("\n" + indented); + } + { + size_t i = 0; + for (auto &a : x.m_symtab->get_scope()) { + s.append(a.first + ":"); + if(indent) { + inc_indent(); + s.append("\n" + indented); + } else { + s.append(" "); + } + this->visit_symbol(*a.second); + if(indent) dec_indent(); + if (i < x.m_symtab->get_scope().size()-1) { + s.append(","); + if(indent) s.append("\n" + indented); + else s.append(" "); + } + i++; + } + } + if(indent) { + dec_indent(); + s.append("\n" + indented); + } + s.append("})"); + if(indent) dec_indent(); + if(indent) s.append("\n" + indented); + else s.append(" "); + s.append(x.m_name); + if(indent) s.append("\n" + indented); + else s.append(" "); + s.append("["); + for (size_t i=0; iget_counter()); + if(indent) s.append("\n" + indented); + else s.append(" "); + s.append("{"); + if(indent) { + inc_indent(); + s.append("\n" + indented); + } + { + size_t i = 0; + for (auto &a : x.m_symtab->get_scope()) { + s.append(a.first + ":"); + if(indent) { + inc_indent(); + s.append("\n" + indented); + } else { + s.append(" "); + } + this->visit_symbol(*a.second); + if(indent) dec_indent(); + if (i < x.m_symtab->get_scope().size()-1) { + s.append(","); + if(indent) s.append("\n" + indented); + else s.append(" "); + } + i++; + } + } + if(indent) { + dec_indent(); + s.append("\n" + indented); + } + s.append("})"); + if(indent) dec_indent(); + if(indent) s.append("\n" + indented); + else s.append(" "); + s.append(x.m_name); + if(indent) s.append("\n" + indented); + else s.append(" "); + s.append("["); + for (size_t i=0; iget_counter()); + if(indent) s.append("\n" + indented); + else s.append(" "); + s.append(x.m_name); + if(indent) s.append("\n" + indented); + else s.append(" "); + s.append("["); + for (size_t i=0; iget_counter()); + if(indent) s.append("\n" + indented); + else s.append(" "); + s.append("{"); + if(indent) { + inc_indent(); + s.append("\n" + indented); + } + { + size_t i = 0; + for (auto &a : x.m_symtab->get_scope()) { + s.append(a.first + ":"); + if(indent) { + inc_indent(); + s.append("\n" + indented); + } else { + s.append(" "); + } + this->visit_symbol(*a.second); + if(indent) dec_indent(); + if (i < x.m_symtab->get_scope().size()-1) { + s.append(","); + if(indent) s.append("\n" + indented); + else s.append(" "); + } + i++; + } + } + if(indent) { + dec_indent(); + s.append("\n" + indented); + } + s.append("})"); + if(indent) dec_indent(); + if(indent) s.append("\n" + indented); + else s.append(" "); + s.append(x.m_name); + if(indent) s.append("\n" + indented); + else s.append(" "); + visit_abiType(x.m_abi); + if(indent) s.append("\n" + indented); + else s.append(" "); + visit_accessType(x.m_access); + if(indent) { + dec_indent(); + s.append("\n" + indented); + } + s.append(")"); + if ((bool&)x) { } // Suppress unused warning + } + void visit_ClassProcedure(const ClassProcedure_t &x) { + s.append("("); + if (use_colors) { + s.append(color(style::bold)); + s.append(color(fg::magenta)); + } + s.append("ClassProcedure"); + if (use_colors) { + s.append(color(fg::reset)); + s.append(color(style::reset)); + } + if(indent) { + inc_indent(); + s.append("\n" + indented); + } else { + s.append(" "); + } + s.append(x.m_parent_symtab->get_counter()); + if(indent) s.append("\n" + indented); + else s.append(" "); + s.append(x.m_name); + if(indent) s.append("\n" + indented); + else s.append(" "); + if (x.m_self_argument) { + s.append(x.m_self_argument); + } else { + s.append("()"); + } + if(indent) s.append("\n" + indented); + else s.append(" "); + s.append(x.m_proc_name); + if(indent) s.append("\n" + indented); + else s.append(" "); + self().visit_symbol(*x.m_proc); + if(indent) s.append("\n" + indented); + else s.append(" "); + visit_abiType(x.m_abi); + if(indent) s.append("\n" + indented); + else s.append(" "); + if (x.m_is_deferred) { + s.append(".true."); + } else { + s.append(".false."); + } + if(indent) s.append("\n" + indented); + else s.append(" "); + if (x.m_is_nopass) { + s.append(".true."); + } else { + s.append(".false."); + } + if(indent) { + dec_indent(); + s.append("\n" + indented); + } + s.append(")"); + } + void visit_AssociateBlock(const AssociateBlock_t &x) { + s.append("("); + if (use_colors) { + s.append(color(style::bold)); + s.append(color(fg::magenta)); + } + s.append("AssociateBlock"); + if (use_colors) { + s.append(color(fg::reset)); + s.append(color(style::reset)); + } + if(indent) { + inc_indent(); + s.append("\n" + indented); + } else { + s.append(" "); + } + s.append("("); + if (use_colors) { + s.append(color(fg::yellow)); + } + s.append("SymbolTable"); + if (use_colors) { + s.append(color(fg::reset)); + } + if(indent) { + inc_indent(); + s.append("\n" + indented); + } else { + s.append(" "); + } + s.append(x.m_symtab->get_counter()); + if(indent) s.append("\n" + indented); + else s.append(" "); + s.append("{"); + if(indent) { + inc_indent(); + s.append("\n" + indented); + } + { + size_t i = 0; + for (auto &a : x.m_symtab->get_scope()) { + s.append(a.first + ":"); + if(indent) { + inc_indent(); + s.append("\n" + indented); + } else { + s.append(" "); + } + this->visit_symbol(*a.second); + if(indent) dec_indent(); + if (i < x.m_symtab->get_scope().size()-1) { + s.append(","); + if(indent) s.append("\n" + indented); + else s.append(" "); + } + i++; + } + } + if(indent) { + dec_indent(); + s.append("\n" + indented); + } + s.append("})"); + if(indent) dec_indent(); + if(indent) s.append("\n" + indented); + else s.append(" "); + s.append(x.m_name); + if(indent) s.append("\n" + indented); + else s.append(" "); + s.append("["); + for (size_t i=0; iget_counter()); + if(indent) s.append("\n" + indented); + else s.append(" "); + s.append("{"); + if(indent) { + inc_indent(); + s.append("\n" + indented); + } + { + size_t i = 0; + for (auto &a : x.m_symtab->get_scope()) { + s.append(a.first + ":"); + if(indent) { + inc_indent(); + s.append("\n" + indented); + } else { + s.append(" "); + } + this->visit_symbol(*a.second); + if(indent) dec_indent(); + if (i < x.m_symtab->get_scope().size()-1) { + s.append(","); + if(indent) s.append("\n" + indented); + else s.append(" "); + } + i++; + } + } + if(indent) { + dec_indent(); + s.append("\n" + indented); + } + s.append("})"); + if(indent) dec_indent(); + if(indent) s.append("\n" + indented); + else s.append(" "); + s.append(x.m_name); + if(indent) s.append("\n" + indented); + else s.append(" "); + s.append("["); + for (size_t i=0; iget_counter()); + if(indent) s.append("\n" + indented); + else s.append(" "); + s.append("{"); + if(indent) { + inc_indent(); + s.append("\n" + indented); + } + { + size_t i = 0; + for (auto &a : x.m_symtab->get_scope()) { + s.append(a.first + ":"); + if(indent) { + inc_indent(); + s.append("\n" + indented); + } else { + s.append(" "); + } + this->visit_symbol(*a.second); + if(indent) dec_indent(); + if (i < x.m_symtab->get_scope().size()-1) { + s.append(","); + if(indent) s.append("\n" + indented); + else s.append(" "); + } + i++; + } + } + if(indent) { + dec_indent(); + s.append("\n" + indented); + } + s.append("})"); + if(indent) dec_indent(); + if(indent) s.append("\n" + indented); + else s.append(" "); + s.append(x.m_name); + if(indent) s.append("\n" + indented); + else s.append(" "); + s.append("["); + for (size_t i=0; iget_counter()); + if(indent) s.append("\n" + indented); + else s.append(" "); + s.append("{"); + if(indent) { + inc_indent(); + s.append("\n" + indented); + } + { + size_t i = 0; + for (auto &a : x.m_symtab->get_scope()) { + s.append(a.first + ":"); + if(indent) { + inc_indent(); + s.append("\n" + indented); + } else { + s.append(" "); + } + this->visit_symbol(*a.second); + if(indent) dec_indent(); + if (i < x.m_symtab->get_scope().size()-1) { + s.append(","); + if(indent) s.append("\n" + indented); + else s.append(" "); + } + i++; + } + } + if(indent) { + dec_indent(); + s.append("\n" + indented); + } + s.append("})"); + if(indent) dec_indent(); + if(indent) s.append("\n" + indented); + else s.append(" "); + s.append(x.m_name); + if(indent) s.append("\n" + indented); + else s.append(" "); + s.append("["); + for (size_t i=0; i std::string lcompilers_unique_ID; +std::string lcompilers_commandline_options; namespace LCompilers { @@ -41,12 +42,12 @@ void SymbolTable::mark_all_variables_external(Allocator &al) { ASR::Function_t *v = ASR::down_cast(a.second); ASR::FunctionType_t* v_func_type = ASR::down_cast(v->m_function_signature); if (v_func_type->m_abi != ASR::abiType::Interactive) { - v_func_type->m_abi = ASR::abiType::Interactive; v->m_body = nullptr; v->n_body = 0; PassUtils::UpdateDependenciesVisitor ud(al); ud.visit_Function(*v); } + v_func_type->m_abi = ASR::abiType::Interactive; break; } case (ASR::symbolType::Module) : { diff --git a/src/libasr/asr_scopes.h b/src/libasr/asr_scopes.h index 972982d5a3..67c3e6c455 100644 --- a/src/libasr/asr_scopes.h +++ b/src/libasr/asr_scopes.h @@ -5,6 +5,7 @@ #include #include +extern std::string lcompilers_commandline_options; namespace LCompilers { @@ -49,6 +50,14 @@ struct SymbolTable { return scope[name]; } + SymbolTable* get_global_scope() { + SymbolTable* global_scope = this; + while (global_scope->parent) { + global_scope = global_scope->parent; + } + return global_scope; + } + const std::map& get_scope() const { return scope; } diff --git a/src/libasr/asr_serialization_visitor.h b/src/libasr/asr_serialization_visitor.h new file mode 100644 index 0000000000..6d9f898684 --- /dev/null +++ b/src/libasr/asr_serialization_visitor.h @@ -0,0 +1,3568 @@ +#pragma once + +// Generated by grammar/asdl_cpp.py + +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace LCompilers::ASR { +/******************************************************************************/ +// Serialization Visitor base class + +template +class SerializationBaseVisitor : public BaseVisitor +{ +private: + StructType& self() { return static_cast(*this); } +public: + void visit_TranslationUnit(const TranslationUnit_t &x) { + self().write_int8(x.base.type); + self().write_int64(x.base.base.loc.first); + self().write_int64(x.base.base.loc.last); + self().write_int64(x.m_symtab->counter); + self().write_int64(x.m_symtab->get_scope().size()); + for (auto &a : x.m_symtab->get_scope()) { + if (ASR::is_a(*a.second)) { + continue; + } + self().write_string(a.first); + this->visit_symbol(*a.second); + } + for (auto &a : x.m_symtab->get_scope()) { + if (ASR::is_a(*a.second)) { + self().write_string(a.first); + this->visit_symbol(*a.second); + } + } + self().write_int64(x.n_items); + for (size_t i=0; itype); + self().visit_asr(*x.m_items[i]); + } + if ((bool&)x) { } // Suppress unused warning + } + void visit_Program(const Program_t &x) { + self().write_int8(x.base.type); + self().write_int64(x.base.base.loc.first); + self().write_int64(x.base.base.loc.last); + self().write_int64(x.m_symtab->counter); + self().write_int64(x.m_symtab->get_scope().size()); + for (auto &a : x.m_symtab->get_scope()) { + if (ASR::is_a(*a.second)) { + continue; + } + self().write_string(a.first); + this->visit_symbol(*a.second); + } + for (auto &a : x.m_symtab->get_scope()) { + if (ASR::is_a(*a.second)) { + self().write_string(a.first); + this->visit_symbol(*a.second); + } + } + self().write_string(x.m_name); + self().write_int64(x.n_dependencies); + for (size_t i=0; icounter); + self().write_int64(x.m_symtab->get_scope().size()); + for (auto &a : x.m_symtab->get_scope()) { + if (ASR::is_a(*a.second)) { + continue; + } + self().write_string(a.first); + this->visit_symbol(*a.second); + } + for (auto &a : x.m_symtab->get_scope()) { + if (ASR::is_a(*a.second)) { + self().write_string(a.first); + this->visit_symbol(*a.second); + } + } + self().write_string(x.m_name); + self().write_int64(x.n_dependencies); + for (size_t i=0; icounter); + self().write_int64(x.m_symtab->get_scope().size()); + for (auto &a : x.m_symtab->get_scope()) { + if (ASR::is_a(*a.second)) { + continue; + } + self().write_string(a.first); + this->visit_symbol(*a.second); + } + for (auto &a : x.m_symtab->get_scope()) { + if (ASR::is_a(*a.second)) { + self().write_string(a.first); + this->visit_symbol(*a.second); + } + } + self().write_string(x.m_name); + self().visit_ttype(*x.m_function_signature); + self().write_int64(x.n_dependencies); + for (size_t i=0; icounter); + self().write_string(x.m_name); + self().write_int64(x.n_procs); + for (size_t i=0; icounter); + self().write_string(x.m_name); + self().write_int64(x.n_procs); + for (size_t i=0; icounter); + self().write_string(x.m_name); + // We skip the symbol for ExternalSymbol + self().write_string(x.m_module_name); + self().write_int64(x.n_scope_names); + for (size_t i=0; icounter); + self().write_int64(x.m_symtab->get_scope().size()); + for (auto &a : x.m_symtab->get_scope()) { + if (ASR::is_a(*a.second)) { + continue; + } + self().write_string(a.first); + this->visit_symbol(*a.second); + } + for (auto &a : x.m_symtab->get_scope()) { + if (ASR::is_a(*a.second)) { + self().write_string(a.first); + this->visit_symbol(*a.second); + } + } + self().write_string(x.m_name); + self().write_int64(x.n_dependencies); + for (size_t i=0; icounter); + self().write_int64(x.m_symtab->get_scope().size()); + for (auto &a : x.m_symtab->get_scope()) { + if (ASR::is_a(*a.second)) { + continue; + } + self().write_string(a.first); + this->visit_symbol(*a.second); + } + for (auto &a : x.m_symtab->get_scope()) { + if (ASR::is_a(*a.second)) { + self().write_string(a.first); + this->visit_symbol(*a.second); + } + } + self().write_string(x.m_name); + self().write_int64(x.n_dependencies); + for (size_t i=0; icounter); + self().write_int64(x.m_symtab->get_scope().size()); + for (auto &a : x.m_symtab->get_scope()) { + if (ASR::is_a(*a.second)) { + continue; + } + self().write_string(a.first); + this->visit_symbol(*a.second); + } + for (auto &a : x.m_symtab->get_scope()) { + if (ASR::is_a(*a.second)) { + self().write_string(a.first); + this->visit_symbol(*a.second); + } + } + self().write_string(x.m_name); + self().write_int64(x.n_dependencies); + for (size_t i=0; icounter); + self().write_string(x.m_name); + self().write_int64(x.n_dependencies); + for (size_t i=0; icounter); + self().write_int64(x.m_symtab->get_scope().size()); + for (auto &a : x.m_symtab->get_scope()) { + if (ASR::is_a(*a.second)) { + continue; + } + self().write_string(a.first); + this->visit_symbol(*a.second); + } + for (auto &a : x.m_symtab->get_scope()) { + if (ASR::is_a(*a.second)) { + self().write_string(a.first); + this->visit_symbol(*a.second); + } + } + self().write_string(x.m_name); + visit_abiType(x.m_abi); + visit_accessType(x.m_access); + if ((bool&)x) { } // Suppress unused warning + } + void visit_ClassProcedure(const ClassProcedure_t &x) { + self().write_int8(x.base.type); + self().write_int64(x.base.base.loc.first); + self().write_int64(x.base.base.loc.last); + self().write_int64(x.m_parent_symtab->counter); + self().write_string(x.m_name); + if (x.m_self_argument) { + self().write_bool(true); + self().write_string(x.m_self_argument); + } else { + self().write_bool(false); + } + self().write_string(x.m_proc_name); + self().write_symbol(*x.m_proc); + visit_abiType(x.m_abi); + if (x.m_is_deferred) { + self().write_bool(true); + } else { + self().write_bool(false); + } + if (x.m_is_nopass) { + self().write_bool(true); + } else { + self().write_bool(false); + } + } + void visit_AssociateBlock(const AssociateBlock_t &x) { + self().write_int8(x.base.type); + self().write_int64(x.base.base.loc.first); + self().write_int64(x.base.base.loc.last); + self().write_int64(x.m_symtab->counter); + self().write_int64(x.m_symtab->get_scope().size()); + for (auto &a : x.m_symtab->get_scope()) { + if (ASR::is_a(*a.second)) { + continue; + } + self().write_string(a.first); + this->visit_symbol(*a.second); + } + for (auto &a : x.m_symtab->get_scope()) { + if (ASR::is_a(*a.second)) { + self().write_string(a.first); + this->visit_symbol(*a.second); + } + } + self().write_string(x.m_name); + self().write_int64(x.n_body); + for (size_t i=0; icounter); + self().write_int64(x.m_symtab->get_scope().size()); + for (auto &a : x.m_symtab->get_scope()) { + if (ASR::is_a(*a.second)) { + continue; + } + self().write_string(a.first); + this->visit_symbol(*a.second); + } + for (auto &a : x.m_symtab->get_scope()) { + if (ASR::is_a(*a.second)) { + self().write_string(a.first); + this->visit_symbol(*a.second); + } + } + self().write_string(x.m_name); + self().write_int64(x.n_body); + for (size_t i=0; icounter); + self().write_int64(x.m_symtab->get_scope().size()); + for (auto &a : x.m_symtab->get_scope()) { + if (ASR::is_a(*a.second)) { + continue; + } + self().write_string(a.first); + this->visit_symbol(*a.second); + } + for (auto &a : x.m_symtab->get_scope()) { + if (ASR::is_a(*a.second)) { + self().write_string(a.first); + this->visit_symbol(*a.second); + } + } + self().write_string(x.m_name); + self().write_int64(x.n_args); + for (size_t i=0; icounter); + self().write_int64(x.m_symtab->get_scope().size()); + for (auto &a : x.m_symtab->get_scope()) { + if (ASR::is_a(*a.second)) { + continue; + } + self().write_string(a.first); + this->visit_symbol(*a.second); + } + for (auto &a : x.m_symtab->get_scope()) { + if (ASR::is_a(*a.second)) { + self().write_string(a.first); + this->visit_symbol(*a.second); + } + } + self().write_string(x.m_name); + self().write_int64(x.n_args); + for (size_t i=0; i +#include +#include +#include +#include +#include +#include +#include + + +namespace LCompilers::ASR { +/******************************************************************************/ +// Statement Replacer Base class + +template +class BaseStmtReplacer { +public: + StructType& self() { return static_cast(*this); } + + ASR::stmt_t** current_stmt; + ASR::stmt_t** current_stmt_copy; + bool has_replacement_happened; + + BaseStmtReplacer() : current_stmt(nullptr), has_replacement_happened(false) {} + + + void replace_Allocate(Allocate_t* x) { + if (x) { } + } + + + void replace_ReAlloc(ReAlloc_t* x) { + if (x) { } + } + + + void replace_Assign(Assign_t* x) { + if (x) { } + } + + + void replace_Assignment(Assignment_t* x) { + if (x) { } + } + + + void replace_Associate(Associate_t* x) { + if (x) { } + } + + + void replace_Cycle(Cycle_t* x) { + if (x) { } + } + + + void replace_ExplicitDeallocate(ExplicitDeallocate_t* x) { + if (x) { } + } + + + void replace_ImplicitDeallocate(ImplicitDeallocate_t* x) { + if (x) { } + } + + + void replace_DoConcurrentLoop(DoConcurrentLoop_t* x) { + for (size_t i = 0; i < x->n_body; i++) { + current_stmt_copy = current_stmt; + current_stmt = &(x->m_body[i]); + self().replace_stmt(x->m_body[i]); + current_stmt = current_stmt_copy; + } + } + + + void replace_DoLoop(DoLoop_t* x) { + for (size_t i = 0; i < x->n_body; i++) { + current_stmt_copy = current_stmt; + current_stmt = &(x->m_body[i]); + self().replace_stmt(x->m_body[i]); + current_stmt = current_stmt_copy; + } + for (size_t i = 0; i < x->n_orelse; i++) { + current_stmt_copy = current_stmt; + current_stmt = &(x->m_orelse[i]); + self().replace_stmt(x->m_orelse[i]); + current_stmt = current_stmt_copy; + } + } + + + void replace_ErrorStop(ErrorStop_t* x) { + if (x) { } + } + + + void replace_Exit(Exit_t* x) { + if (x) { } + } + + + void replace_ForAllSingle(ForAllSingle_t* x) { + if (x) { } + } + + + void replace_ForEach(ForEach_t* x) { + for (size_t i = 0; i < x->n_body; i++) { + current_stmt_copy = current_stmt; + current_stmt = &(x->m_body[i]); + self().replace_stmt(x->m_body[i]); + current_stmt = current_stmt_copy; + } + } + + + void replace_GoTo(GoTo_t* x) { + if (x) { } + } + + + void replace_GoToTarget(GoToTarget_t* x) { + if (x) { } + } + + + void replace_If(If_t* x) { + for (size_t i = 0; i < x->n_body; i++) { + current_stmt_copy = current_stmt; + current_stmt = &(x->m_body[i]); + self().replace_stmt(x->m_body[i]); + current_stmt = current_stmt_copy; + } + for (size_t i = 0; i < x->n_orelse; i++) { + current_stmt_copy = current_stmt; + current_stmt = &(x->m_orelse[i]); + self().replace_stmt(x->m_orelse[i]); + current_stmt = current_stmt_copy; + } + } + + + void replace_IfArithmetic(IfArithmetic_t* x) { + if (x) { } + } + + + void replace_Print(Print_t* x) { + if (x) { } + } + + + void replace_FileOpen(FileOpen_t* x) { + if (x) { } + } + + + void replace_FileClose(FileClose_t* x) { + if (x) { } + } + + + void replace_FileRead(FileRead_t* x) { + if (x) { } + } + + + void replace_FileBackspace(FileBackspace_t* x) { + if (x) { } + } + + + void replace_FileRewind(FileRewind_t* x) { + if (x) { } + } + + + void replace_FileInquire(FileInquire_t* x) { + if (x) { } + } + + + void replace_FileWrite(FileWrite_t* x) { + if (x) { } + } + + + void replace_Return(Return_t* x) { + if (x) { } + } + + + void replace_Select(Select_t* x) { + for (size_t i = 0; i < x->n_default; i++) { + current_stmt_copy = current_stmt; + current_stmt = &(x->m_default[i]); + self().replace_stmt(x->m_default[i]); + current_stmt = current_stmt_copy; + } + } + + + void replace_Stop(Stop_t* x) { + if (x) { } + } + + + void replace_Assert(Assert_t* x) { + if (x) { } + } + + + void replace_SubroutineCall(SubroutineCall_t* x) { + if (x) { } + } + + + void replace_IntrinsicImpureSubroutine(IntrinsicImpureSubroutine_t* x) { + if (x) { } + } + + + void replace_Where(Where_t* x) { + for (size_t i = 0; i < x->n_body; i++) { + current_stmt_copy = current_stmt; + current_stmt = &(x->m_body[i]); + self().replace_stmt(x->m_body[i]); + current_stmt = current_stmt_copy; + } + for (size_t i = 0; i < x->n_orelse; i++) { + current_stmt_copy = current_stmt; + current_stmt = &(x->m_orelse[i]); + self().replace_stmt(x->m_orelse[i]); + current_stmt = current_stmt_copy; + } + } + + + void replace_WhileLoop(WhileLoop_t* x) { + for (size_t i = 0; i < x->n_body; i++) { + current_stmt_copy = current_stmt; + current_stmt = &(x->m_body[i]); + self().replace_stmt(x->m_body[i]); + current_stmt = current_stmt_copy; + } + for (size_t i = 0; i < x->n_orelse; i++) { + current_stmt_copy = current_stmt; + current_stmt = &(x->m_orelse[i]); + self().replace_stmt(x->m_orelse[i]); + current_stmt = current_stmt_copy; + } + } + + + void replace_Nullify(Nullify_t* x) { + if (x) { } + } + + + void replace_Flush(Flush_t* x) { + if (x) { } + } + + + void replace_ListAppend(ListAppend_t* x) { + if (x) { } + } + + + void replace_AssociateBlockCall(AssociateBlockCall_t* x) { + if (x) { } + } + + + void replace_SelectType(SelectType_t* x) { + for (size_t i = 0; i < x->n_default; i++) { + current_stmt_copy = current_stmt; + current_stmt = &(x->m_default[i]); + self().replace_stmt(x->m_default[i]); + current_stmt = current_stmt_copy; + } + } + + + void replace_CPtrToPointer(CPtrToPointer_t* x) { + if (x) { } + } + + + void replace_BlockCall(BlockCall_t* x) { + if (x) { } + } + + + void replace_SetInsert(SetInsert_t* x) { + if (x) { } + } + + + void replace_SetRemove(SetRemove_t* x) { + if (x) { } + } + + + void replace_SetDiscard(SetDiscard_t* x) { + if (x) { } + } + + + void replace_ListInsert(ListInsert_t* x) { + if (x) { } + } + + + void replace_ListRemove(ListRemove_t* x) { + if (x) { } + } + + + void replace_ListClear(ListClear_t* x) { + if (x) { } + } + + + void replace_DictInsert(DictInsert_t* x) { + if (x) { } + } + + + void replace_DictClear(DictClear_t* x) { + if (x) { } + } + + + void replace_SetClear(SetClear_t* x) { + if (x) { } + } + + + void replace_Expr(Expr_t* x) { + if (x) { } + } + + void replace_stmt(ASR::stmt_t* x) { + if( !x ) { + return ; + } + + switch(x->type) { + case ASR::stmtType::Allocate: { + self().replace_Allocate(down_cast(x)); + break; + } + case ASR::stmtType::ReAlloc: { + self().replace_ReAlloc(down_cast(x)); + break; + } + case ASR::stmtType::Assign: { + self().replace_Assign(down_cast(x)); + break; + } + case ASR::stmtType::Assignment: { + self().replace_Assignment(down_cast(x)); + break; + } + case ASR::stmtType::Associate: { + self().replace_Associate(down_cast(x)); + break; + } + case ASR::stmtType::Cycle: { + self().replace_Cycle(down_cast(x)); + break; + } + case ASR::stmtType::ExplicitDeallocate: { + self().replace_ExplicitDeallocate(down_cast(x)); + break; + } + case ASR::stmtType::ImplicitDeallocate: { + self().replace_ImplicitDeallocate(down_cast(x)); + break; + } + case ASR::stmtType::DoConcurrentLoop: { + self().replace_DoConcurrentLoop(down_cast(x)); + break; + } + case ASR::stmtType::DoLoop: { + self().replace_DoLoop(down_cast(x)); + break; + } + case ASR::stmtType::ErrorStop: { + self().replace_ErrorStop(down_cast(x)); + break; + } + case ASR::stmtType::Exit: { + self().replace_Exit(down_cast(x)); + break; + } + case ASR::stmtType::ForAllSingle: { + self().replace_ForAllSingle(down_cast(x)); + break; + } + case ASR::stmtType::ForEach: { + self().replace_ForEach(down_cast(x)); + break; + } + case ASR::stmtType::GoTo: { + self().replace_GoTo(down_cast(x)); + break; + } + case ASR::stmtType::GoToTarget: { + self().replace_GoToTarget(down_cast(x)); + break; + } + case ASR::stmtType::If: { + self().replace_If(down_cast(x)); + break; + } + case ASR::stmtType::IfArithmetic: { + self().replace_IfArithmetic(down_cast(x)); + break; + } + case ASR::stmtType::Print: { + self().replace_Print(down_cast(x)); + break; + } + case ASR::stmtType::FileOpen: { + self().replace_FileOpen(down_cast(x)); + break; + } + case ASR::stmtType::FileClose: { + self().replace_FileClose(down_cast(x)); + break; + } + case ASR::stmtType::FileRead: { + self().replace_FileRead(down_cast(x)); + break; + } + case ASR::stmtType::FileBackspace: { + self().replace_FileBackspace(down_cast(x)); + break; + } + case ASR::stmtType::FileRewind: { + self().replace_FileRewind(down_cast(x)); + break; + } + case ASR::stmtType::FileInquire: { + self().replace_FileInquire(down_cast(x)); + break; + } + case ASR::stmtType::FileWrite: { + self().replace_FileWrite(down_cast(x)); + break; + } + case ASR::stmtType::Return: { + self().replace_Return(down_cast(x)); + break; + } + case ASR::stmtType::Select: { + self().replace_Select(down_cast(x)); + break; + } + case ASR::stmtType::Stop: { + self().replace_Stop(down_cast(x)); + break; + } + case ASR::stmtType::Assert: { + self().replace_Assert(down_cast(x)); + break; + } + case ASR::stmtType::SubroutineCall: { + self().replace_SubroutineCall(down_cast(x)); + break; + } + case ASR::stmtType::IntrinsicImpureSubroutine: { + self().replace_IntrinsicImpureSubroutine(down_cast(x)); + break; + } + case ASR::stmtType::Where: { + self().replace_Where(down_cast(x)); + break; + } + case ASR::stmtType::WhileLoop: { + self().replace_WhileLoop(down_cast(x)); + break; + } + case ASR::stmtType::Nullify: { + self().replace_Nullify(down_cast(x)); + break; + } + case ASR::stmtType::Flush: { + self().replace_Flush(down_cast(x)); + break; + } + case ASR::stmtType::ListAppend: { + self().replace_ListAppend(down_cast(x)); + break; + } + case ASR::stmtType::AssociateBlockCall: { + self().replace_AssociateBlockCall(down_cast(x)); + break; + } + case ASR::stmtType::SelectType: { + self().replace_SelectType(down_cast(x)); + break; + } + case ASR::stmtType::CPtrToPointer: { + self().replace_CPtrToPointer(down_cast(x)); + break; + } + case ASR::stmtType::BlockCall: { + self().replace_BlockCall(down_cast(x)); + break; + } + case ASR::stmtType::SetInsert: { + self().replace_SetInsert(down_cast(x)); + break; + } + case ASR::stmtType::SetRemove: { + self().replace_SetRemove(down_cast(x)); + break; + } + case ASR::stmtType::SetDiscard: { + self().replace_SetDiscard(down_cast(x)); + break; + } + case ASR::stmtType::ListInsert: { + self().replace_ListInsert(down_cast(x)); + break; + } + case ASR::stmtType::ListRemove: { + self().replace_ListRemove(down_cast(x)); + break; + } + case ASR::stmtType::ListClear: { + self().replace_ListClear(down_cast(x)); + break; + } + case ASR::stmtType::DictInsert: { + self().replace_DictInsert(down_cast(x)); + break; + } + case ASR::stmtType::DictClear: { + self().replace_DictClear(down_cast(x)); + break; + } + case ASR::stmtType::SetClear: { + self().replace_SetClear(down_cast(x)); + break; + } + case ASR::stmtType::Expr: { + self().replace_Expr(down_cast(x)); + break; + } + default: { + LCOMPILERS_ASSERT_MSG(false, "Replacement of " + std::to_string(x->type) + " statement is not supported yet."); + } + } + + } + +}; + + +} diff --git a/src/libasr/asr_tree_visitor.h b/src/libasr/asr_tree_visitor.h new file mode 100644 index 0000000000..e256b3cb1c --- /dev/null +++ b/src/libasr/asr_tree_visitor.h @@ -0,0 +1,9905 @@ +#pragma once + +// Generated by grammar/asdl_cpp.py + +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace LCompilers::ASR { +/******************************************************************************/ +// Tree Visitor base class + +template +class TreeBaseVisitor : public BaseVisitor +{ +private: + StructType& self() { return static_cast(*this); } +public: + std::string s, indtd; + bool use_colors; + bool start_line = true; + bool last, attached; + int indent_level = 0, indent_spaces = 2, lvl = 0; +public: + TreeBaseVisitor() : use_colors(false), last(true), attached(false) { s.reserve(100000); } + void inc_indent() { + indent_level++; + indtd += " "; + } + void inc_lindent() { + indent_level++; + indtd += "| "; + } + void dec_indent() { + indent_level--; + LCOMPILERS_ASSERT(indent_level >= 0); + indtd = indtd.substr(0, indent_level*indent_spaces); + } + void visit_TranslationUnit(const TranslationUnit_t &x) { + if(!attached) { + if(start_line) { + start_line = false; + s.append(indtd); + } else { + s.append("\n"+indtd); + } + last ? s.append("└-") : s.append("|-"); + } + last ? inc_indent() : inc_lindent(); + attached = true; + last = false; + if (use_colors) { + s.append(color(style::bold)); + s.append(color(fg::magenta)); + } + s.append("TranslationUnit"); + if (use_colors) { + s.append(color(fg::reset)); + s.append(color(style::reset)); + } + s.append("\n" + indtd + "|-"); + inc_lindent(); + if (use_colors) { + s.append(color(fg::yellow)); + } + s.append("SymbolTable"); + if (use_colors) { + s.append(color(fg::reset)); + } + s.append("\n" + indtd + "|-counter="); + s.append(x.m_symtab->get_counter()); + size_t i = 0; + s.append("\n" + indtd + "└-scope=↧"); + for (auto &a : x.m_symtab->get_scope()) { + i++; + inc_indent(); + last = i == x.m_symtab->get_scope().size(); + s.append("\n" + indtd + (last ? "└-" : "|-") + a.first + ": "); + this->visit_symbol(*a.second); + dec_indent(); + } + dec_indent(); + s.append("\n" + indtd + "└-" + "items=↧"); + attached = false; + for (size_t i=0; iget_scope()) { + i++; + inc_indent(); + last = i == x.m_symtab->get_scope().size(); + s.append("\n" + indtd + (last ? "└-" : "|-") + a.first + ": "); + this->visit_symbol(*a.second); + dec_indent(); + } + dec_indent(); + s.append("\n" + indtd + "|-" + "name="); + s.append(x.m_name); + s.append("\n" + indtd + "|-" + "dependencies="); + for (size_t i=0; iget_scope()) { + i++; + inc_indent(); + last = i == x.m_symtab->get_scope().size(); + s.append("\n" + indtd + (last ? "└-" : "|-") + a.first + ": "); + this->visit_symbol(*a.second); + dec_indent(); + } + dec_indent(); + s.append("\n" + indtd + "|-" + "name="); + s.append(x.m_name); + s.append("\n" + indtd + "|-" + "dependencies="); + for (size_t i=0; iget_scope()) { + i++; + inc_indent(); + last = i == x.m_symtab->get_scope().size(); + s.append("\n" + indtd + (last ? "└-" : "|-") + a.first + ": "); + this->visit_symbol(*a.second); + dec_indent(); + } + dec_indent(); + s.append("\n" + indtd + "|-" + "name="); + s.append(x.m_name); + s.append("\n" + indtd + "|-" + "function_signature="); + attached = true; + self().visit_ttype(*x.m_function_signature); + s.append("\n" + indtd + "|-" + "dependencies="); + for (size_t i=0; iget_scope()) { + i++; + inc_indent(); + last = i == x.m_symtab->get_scope().size(); + s.append("\n" + indtd + (last ? "└-" : "|-") + a.first + ": "); + this->visit_symbol(*a.second); + dec_indent(); + } + dec_indent(); + s.append("\n" + indtd + "|-" + "name="); + s.append(x.m_name); + s.append("\n" + indtd + "|-" + "dependencies="); + for (size_t i=0; iget_scope()) { + i++; + inc_indent(); + last = i == x.m_symtab->get_scope().size(); + s.append("\n" + indtd + (last ? "└-" : "|-") + a.first + ": "); + this->visit_symbol(*a.second); + dec_indent(); + } + dec_indent(); + s.append("\n" + indtd + "|-" + "name="); + s.append(x.m_name); + s.append("\n" + indtd + "|-" + "dependencies="); + for (size_t i=0; iget_scope()) { + i++; + inc_indent(); + last = i == x.m_symtab->get_scope().size(); + s.append("\n" + indtd + (last ? "└-" : "|-") + a.first + ": "); + this->visit_symbol(*a.second); + dec_indent(); + } + dec_indent(); + s.append("\n" + indtd + "|-" + "name="); + s.append(x.m_name); + s.append("\n" + indtd + "|-" + "dependencies="); + for (size_t i=0; iget_scope()) { + i++; + inc_indent(); + last = i == x.m_symtab->get_scope().size(); + s.append("\n" + indtd + (last ? "└-" : "|-") + a.first + ": "); + this->visit_symbol(*a.second); + dec_indent(); + } + dec_indent(); + s.append("\n" + indtd + "|-" + "name="); + s.append(x.m_name); + s.append("\n" + indtd + "|-" + "abiType="); + visit_abiType(x.m_abi); + s.append("\n" + indtd + "└-" + "accessType="); + visit_accessType(x.m_access); + dec_indent(); + if ((bool&)x) { } // Suppress unused warning + } + void visit_ClassProcedure(const ClassProcedure_t &x) { + if(!attached) { + if(start_line) { + start_line = false; + s.append(indtd); + } else { + s.append("\n"+indtd); + } + last ? s.append("└-") : s.append("|-"); + } + last ? inc_indent() : inc_lindent(); + attached = true; + last = false; + if (use_colors) { + s.append(color(style::bold)); + s.append(color(fg::magenta)); + } + s.append("ClassProcedure"); + if (use_colors) { + s.append(color(fg::reset)); + s.append(color(style::reset)); + } + s.append("\n" + indtd + "|-" + "parent_symtab="); + s.append(x.m_parent_symtab->get_counter()); + s.append("\n" + indtd + "|-" + "name="); + s.append(x.m_name); + s.append("\n" + indtd + "|-" + "self_argument="); + if (x.m_self_argument) { + s.append(x.m_self_argument); + } else { + s.append("()"); + } + s.append("\n" + indtd + "|-" + "proc_name="); + s.append(x.m_proc_name); + s.append("\n" + indtd + "|-" + "proc="); + attached = true; + self().visit_symbol(*x.m_proc); + s.append("\n" + indtd + "|-" + "abiType="); + visit_abiType(x.m_abi); + s.append("\n" + indtd + "|-" + "is_deferred="); + if (x.m_is_deferred) { + s.append(".true."); + } else { + s.append(".false."); + } + s.append("\n" + indtd + "└-" + "is_nopass="); + if (x.m_is_nopass) { + s.append(".true."); + } else { + s.append(".false."); + } + dec_indent(); + } + void visit_AssociateBlock(const AssociateBlock_t &x) { + if(!attached) { + if(start_line) { + start_line = false; + s.append(indtd); + } else { + s.append("\n"+indtd); + } + last ? s.append("└-") : s.append("|-"); + } + last ? inc_indent() : inc_lindent(); + attached = true; + last = false; + if (use_colors) { + s.append(color(style::bold)); + s.append(color(fg::magenta)); + } + s.append("AssociateBlock"); + if (use_colors) { + s.append(color(fg::reset)); + s.append(color(style::reset)); + } + s.append("\n" + indtd + "|-"); + inc_lindent(); + if (use_colors) { + s.append(color(fg::yellow)); + } + s.append("SymbolTable"); + if (use_colors) { + s.append(color(fg::reset)); + } + s.append("\n" + indtd + "|-counter="); + s.append(x.m_symtab->get_counter()); + size_t i = 0; + s.append("\n" + indtd + "└-scope=↧"); + for (auto &a : x.m_symtab->get_scope()) { + i++; + inc_indent(); + last = i == x.m_symtab->get_scope().size(); + s.append("\n" + indtd + (last ? "└-" : "|-") + a.first + ": "); + this->visit_symbol(*a.second); + dec_indent(); + } + dec_indent(); + s.append("\n" + indtd + "|-" + "name="); + s.append(x.m_name); + s.append("\n" + indtd + "└-" + "body=↧"); + for (size_t i=0; iget_scope()) { + i++; + inc_indent(); + last = i == x.m_symtab->get_scope().size(); + s.append("\n" + indtd + (last ? "└-" : "|-") + a.first + ": "); + this->visit_symbol(*a.second); + dec_indent(); + } + dec_indent(); + s.append("\n" + indtd + "|-" + "name="); + s.append(x.m_name); + s.append("\n" + indtd + "└-" + "body=↧"); + for (size_t i=0; iget_scope()) { + i++; + inc_indent(); + last = i == x.m_symtab->get_scope().size(); + s.append("\n" + indtd + (last ? "└-" : "|-") + a.first + ": "); + this->visit_symbol(*a.second); + dec_indent(); + } + dec_indent(); + s.append("\n" + indtd + "|-" + "name="); + s.append(x.m_name); + s.append("\n" + indtd + "|-" + "args="); + for (size_t i=0; iget_scope()) { + i++; + inc_indent(); + last = i == x.m_symtab->get_scope().size(); + s.append("\n" + indtd + (last ? "└-" : "|-") + a.first + ": "); + this->visit_symbol(*a.second); + dec_indent(); + } + dec_indent(); + s.append("\n" + indtd + "|-" + "name="); + s.append(x.m_name); + s.append("\n" + indtd + "|-" + "args="); + for (size_t i=0; i #include #include +#include #include +#include + namespace LCompilers { namespace ASRUtils { @@ -197,7 +200,7 @@ void update_call_args(Allocator &al, SymbolTable *current_scope, bool implicit_i ASR::symbol_t* arg_sym = arg_var->m_v; ASR::symbol_t* arg_sym_underlying = ASRUtils::symbol_get_past_external(arg_sym); ASR::symbol_t* sym = fetch_sym(arg_sym_underlying); - if (sym != arg_sym) { + if (sym != arg_sym_underlying) { ASR::expr_t** current_expr_copy = current_expr; current_expr = const_cast((expr_to_replace)); this->call_replacer_(sym); @@ -250,7 +253,7 @@ void update_call_args(Allocator &al, SymbolTable *current_scope, bool implicit_i ASR::symbol_t* arg_sym = arg_var->m_v; ASR::symbol_t* arg_sym_underlying = ASRUtils::symbol_get_past_external(arg_sym); ASR::symbol_t* sym = fetch_sym(arg_sym_underlying); - if (sym != arg_sym) { + if (sym != arg_sym_underlying) { ASR::expr_t** current_expr_copy = current_expr; current_expr = const_cast(&(func->m_args[i])); this->call_replacer_(sym); @@ -293,7 +296,8 @@ ASR::Module_t* load_module(Allocator &al, SymbolTable *symtab, const Location &loc, bool intrinsic, LCompilers::PassOptions& pass_options, bool run_verify, - const std::function err) { + const std::function err, + LCompilers::LocationManager &lm) { LCOMPILERS_ASSERT(symtab); if (symtab->get_symbol(module_name) != nullptr) { ASR::symbol_t *m = symtab->get_symbol(module_name); @@ -305,14 +309,14 @@ ASR::Module_t* load_module(Allocator &al, SymbolTable *symtab, } LCOMPILERS_ASSERT(symtab->parent == nullptr); ASR::TranslationUnit_t *mod1 = find_and_load_module(al, module_name, - *symtab, intrinsic, pass_options); + *symtab, intrinsic, pass_options, lm); if (mod1 == nullptr && !intrinsic) { // Module not found as a regular module. Try intrinsic module if (module_name == "iso_c_binding" ||module_name == "iso_fortran_env" ||module_name == "ieee_arithmetic") { mod1 = find_and_load_module(al, "lfortran_intrinsic_" + module_name, - *symtab, true, pass_options); + *symtab, true, pass_options, lm); } } if (mod1 == nullptr) { @@ -349,13 +353,13 @@ ASR::Module_t* load_module(Allocator &al, SymbolTable *symtab, bool is_intrinsic = startswith(item, "lfortran_intrinsic"); ASR::TranslationUnit_t *mod1 = find_and_load_module(al, item, - *symtab, is_intrinsic, pass_options); + *symtab, is_intrinsic, pass_options, lm); if (mod1 == nullptr && !is_intrinsic) { // Module not found as a regular module. Try intrinsic module if (item == "iso_c_binding" ||item == "iso_fortran_env") { mod1 = find_and_load_module(al, "lfortran_intrinsic_" + item, - *symtab, true, pass_options); + *symtab, true, pass_options, lm); } } @@ -438,7 +442,8 @@ void set_intrinsic(ASR::TranslationUnit_t* trans_unit) { ASR::TranslationUnit_t* find_and_load_module(Allocator &al, const std::string &msym, SymbolTable &symtab, bool intrinsic, - LCompilers::PassOptions& pass_options) { + LCompilers::PassOptions& pass_options, + LCompilers::LocationManager &lm) { std::filesystem::path runtime_library_dir { pass_options.runtime_library_dir }; std::filesystem::path filename {msym + ".mod"}; std::vector mod_files_dirs; @@ -453,7 +458,7 @@ ASR::TranslationUnit_t* find_and_load_module(Allocator &al, const std::string &m std::string modfile; std::filesystem::path full_path = path / filename; if (read_file(full_path.string(), modfile)) { - ASR::TranslationUnit_t *asr = load_modfile(al, modfile, false, symtab); + ASR::TranslationUnit_t *asr = load_modfile(al, modfile, false, symtab, lm); if (intrinsic) { set_intrinsic(asr); } @@ -557,7 +562,7 @@ ASR::asr_t* getStructInstanceMember_t(Allocator& al, const Location& loc, } if( ASR::is_a(*member_variable->m_type) ) { - member_type = ASRUtils::TYPE(ASR::make_Allocatable_t(al, + member_type = ASRUtils::TYPE(ASRUtils::make_Allocatable_t_util(al, member_variable->base.base.loc, member_type)); } else if( ASR::is_a(*member_variable->m_type) ) { member_type = ASRUtils::TYPE(ASR::make_Pointer_t(al, @@ -591,9 +596,9 @@ bool use_overloaded(ASR::expr_t* left, ASR::expr_t* right, left_struct = ASR::down_cast( ASRUtils::symbol_get_past_external(ASR::down_cast( left_type)->m_derived_type)); - } else if ( ASR::is_a(*left_type) ) { + } else if ( ASR::is_a(*left_type) ) { left_struct = ASR::down_cast( - ASRUtils::symbol_get_past_external(ASR::down_cast( + ASRUtils::symbol_get_past_external(ASR::down_cast( left_type)->m_class_type)); } bool found = false; @@ -692,7 +697,8 @@ bool use_overloaded(ASR::expr_t* left, ASR::expr_t* right, asr = ASRUtils::make_FunctionCall_t_util(al, loc, a_name, sym, a_args.p, 2, return_type, - nullptr, nullptr); + nullptr, nullptr, + false); } } break; @@ -784,7 +790,8 @@ void process_overloaded_unary_minus_function(ASR::symbol_t* proc, ASR::expr_t* o asr = ASRUtils::make_FunctionCall_t_util(al, loc, a_name, proc, a_args.p, 1, return_type, - nullptr, nullptr); + nullptr, nullptr, + false); } } } @@ -921,12 +928,12 @@ void process_overloaded_assignment_function(ASR::symbol_t* proc, ASR::expr_t* ta } if( (arg0_name == pass_arg_str && target != expr_dt) ) { err(std::string(subrout->m_name) + " is not a procedure of " + - ASRUtils::type_to_str(target_type), + ASRUtils::type_to_str_fortran(target_type), loc); } if( (arg1_name == pass_arg_str && value != expr_dt) ) { err(std::string(subrout->m_name) + " is not a procedure of " + - ASRUtils::type_to_str(value_type), + ASRUtils::type_to_str_fortran(value_type), loc); } } @@ -1029,7 +1036,7 @@ void process_overloaded_read_write_function(std::string &read_write, ASR::symbol std::string pass_arg_str = std::string(pass_arg); if( (arg0_name == pass_arg_str && args[0] != expr_dt) ) { err(std::string(subrout->m_name) + " is not a procedure of " + - ASRUtils::type_to_str(arg_type), + ASRUtils::type_to_str_fortran(arg_type), loc); } } @@ -1125,9 +1132,9 @@ bool use_overloaded(ASR::expr_t* left, ASR::expr_t* right, left_struct = ASR::down_cast( ASRUtils::symbol_get_past_external(ASR::down_cast( left_type)->m_derived_type)); - } else if ( ASR::is_a(*left_type) ) { + } else if ( ASR::is_a(*left_type) ) { left_struct = ASR::down_cast( - ASRUtils::symbol_get_past_external(ASR::down_cast( + ASRUtils::symbol_get_past_external(ASR::down_cast( left_type)->m_class_type)); } bool found = false; @@ -1156,9 +1163,9 @@ bool use_overloaded(ASR::expr_t* left, ASR::expr_t* right, ASR::ttype_t* right_arg_type = ASRUtils::expr_type(func->m_args[1]); if( (left_arg_type->type == left_type->type && right_arg_type->type == right_type->type) - || (ASR::is_a(*left_arg_type) && + || (ASR::is_a(*left_arg_type) && ASR::is_a(*left_type)) - || (ASR::is_a(*right_arg_type) && + || (ASR::is_a(*right_arg_type) && ASR::is_a(*right_type))) { found = true; Vec a_args; @@ -1202,7 +1209,8 @@ bool use_overloaded(ASR::expr_t* left, ASR::expr_t* right, asr = ASRUtils::make_FunctionCall_t_util(al, loc, a_name, sym, a_args.p, 2, return_type, - nullptr, nullptr); + nullptr, nullptr, + false); } } break; @@ -1391,7 +1399,8 @@ ASR::asr_t* symbol_resolve_external_generic_procedure_without_eval( return ASRUtils::make_FunctionCall_t_util(al, loc, final_sym, v, args.p, args.size(), return_type, - nullptr, nullptr); + nullptr, nullptr, + false); } } @@ -1534,7 +1543,7 @@ ASR::asr_t* make_Binop_util(Allocator &al, const Location& loc, ASR::binopType b ASRUtils::duplicate_type(al, ttype), nullptr); } default: - throw LCompilersException("Not implemented " + std::to_string(ttype->type)); + throw LCompilersException("Not implemented " + ASRUtils::type_to_str_python(ttype)); } } @@ -1551,17 +1560,17 @@ ASR::asr_t* make_Cmpop_util(Allocator &al, const Location& loc, ASR::cmpopType c case ASR::ttypeType::Complex: { return ASR::make_ComplexCompare_t(al, loc, lexpr, cmpop, rexpr, expr_type, nullptr); } - case ASR::ttypeType::Character: { + case ASR::ttypeType::String: { return ASR::make_StringCompare_t(al, loc, lexpr, cmpop, rexpr, expr_type, nullptr); } default: - throw LCompilersException("Not implemented " + std::to_string(ttype->type)); + throw LCompilersException("Not implemented " + ASRUtils::type_to_str_python(ttype)); } } void make_ArrayBroadcast_t_util(Allocator& al, const Location& loc, ASR::expr_t*& expr1, ASR::expr_t*& expr2, ASR::dimension_t* expr1_mdims, - size_t expr1_ndims) { + size_t expr1_ndims, bool is_simd_array=false) { ASR::ttype_t* expr1_type = ASRUtils::expr_type(expr1); Vec shape_args; shape_args.reserve(al, 1); @@ -1579,7 +1588,7 @@ void make_ArrayBroadcast_t_util(Allocator& al, const Location& loc, dims.push_back(al, dim); ASR::ttype_t* dest_shape_type = ASRUtils::TYPE(ASR::make_Array_t(al, loc, ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)), dims.p, dims.size(), - is_value_character_array ? ASR::array_physical_typeType::CharacterArraySinglePointer: ASR::array_physical_typeType::FixedSizeArray)); + is_value_character_array && !is_value_constant(expr2) ? ASR::array_physical_typeType::StringArraySinglePointer: ASR::array_physical_typeType::FixedSizeArray)); ASR::expr_t* dest_shape = nullptr; ASR::expr_t* value = nullptr; @@ -1603,10 +1612,11 @@ void make_ArrayBroadcast_t_util(Allocator& al, const Location& loc, dims.push_back(al, dim); if( ASRUtils::is_value_constant(expr2) && - ASRUtils::get_fixed_size_of_array(expr1_mdims, expr1_ndims) <= 256 ) { + ASRUtils::get_fixed_size_of_array(expr1_mdims, expr1_ndims) <= 256 && + is_simd_array ) { ASR::ttype_t* value_type = ASRUtils::TYPE(ASR::make_Array_t(al, loc, ASRUtils::type_get_past_array(ASRUtils::expr_type(expr2)), dims.p, dims.size(), - is_value_character_array ? ASR::array_physical_typeType::CharacterArraySinglePointer: ASR::array_physical_typeType::FixedSizeArray)); + is_value_character_array && !ASRUtils::is_value_constant(expr2) ? ASR::array_physical_typeType::StringArraySinglePointer: ASR::array_physical_typeType::FixedSizeArray)); Vec values; values.reserve(al, ASRUtils::get_fixed_size_of_array(expr1_mdims, expr1_ndims)); for( int64_t i = 0; i < ASRUtils::get_fixed_size_of_array(expr1_mdims, expr1_ndims); i++ ) { @@ -1614,6 +1624,9 @@ void make_ArrayBroadcast_t_util(Allocator& al, const Location& loc, } value = EXPR(ASRUtils::make_ArrayConstructor_t_util(al, loc, values.p, values.size(), value_type, ASR::arraystorageType::ColMajor)); + if (ASR::is_a(*value) && ASRUtils::expr_value(value)) { + value = ASRUtils::expr_value(value); + } ret_type = value_type; } } else { @@ -1642,7 +1655,7 @@ void make_ArrayBroadcast_t_util(Allocator& al, const Location& loc, } void make_ArrayBroadcast_t_util(Allocator& al, const Location& loc, - ASR::expr_t*& expr1, ASR::expr_t*& expr2) { + ASR::expr_t*& expr1, ASR::expr_t*& expr2, bool is_simd_array) { ASR::ttype_t* expr1_type = ASRUtils::expr_type(expr1); ASR::ttype_t* expr2_type = ASRUtils::expr_type(expr2); ASR::dimension_t *expr1_mdims = nullptr, *expr2_mdims = nullptr; @@ -1657,12 +1670,12 @@ void make_ArrayBroadcast_t_util(Allocator& al, const Location& loc, if( ASR::is_a(*expr2) ) { return ; } - make_ArrayBroadcast_t_util(al, loc, expr1, expr2, expr1_mdims, expr1_ndims); + make_ArrayBroadcast_t_util(al, loc, expr1, expr2, expr1_mdims, expr1_ndims, is_simd_array); } else { if( ASR::is_a(*expr1) ) { return ; } - make_ArrayBroadcast_t_util(al, loc, expr2, expr1, expr2_mdims, expr2_ndims); + make_ArrayBroadcast_t_util(al, loc, expr2, expr1, expr2_mdims, expr2_ndims, is_simd_array); } } @@ -1703,6 +1716,434 @@ void append_error(diag::Diagnostics& diag, const std::string& msg, diag::Stage::Semantic, {diag::Label("", { loc })})); } +size_t get_constant_ArrayConstant_size(ASR::ArrayConstant_t* x) { + return ASRUtils::get_fixed_size_of_array(x->m_type); +} + +ASR::expr_t* get_ArrayConstant_size(Allocator& al, ASR::ArrayConstant_t* x) { + ASR::ttype_t* int_type = ASRUtils::TYPE(ASR::make_Integer_t(al, x->base.base.loc, 4)); + return make_ConstantWithType(make_IntegerConstant_t, + ASRUtils::get_fixed_size_of_array(x->m_type), int_type, x->base.base.loc); +} + +ASR::expr_t* get_ImpliedDoLoop_size(Allocator& al, ASR::ImpliedDoLoop_t* implied_doloop) { + const Location& loc = implied_doloop->base.base.loc; + ASRUtils::ASRBuilder builder(al, loc); + ASR::expr_t* start = implied_doloop->m_start; + ASR::expr_t* end = implied_doloop->m_end; + ASR::expr_t* d = implied_doloop->m_increment; + ASR::expr_t* implied_doloop_size = nullptr; + int kind = ASRUtils::extract_kind_from_ttype_t(ASRUtils::expr_type(end)); + start = builder.i2i_t(start, ASRUtils::expr_type(end)); + if( d == nullptr ) { + implied_doloop_size = builder.Add( + builder.Sub(end, start), + make_ConstantWithKind(make_IntegerConstant_t, make_Integer_t, 1, kind, loc)); + } else { + implied_doloop_size = builder.Add(builder.Div( + builder.Sub(end, start), d), + make_ConstantWithKind(make_IntegerConstant_t, make_Integer_t, 1, kind, loc)); + } + int const_elements = 0; + ASR::expr_t* implied_doloop_size_ = nullptr; + for( size_t i = 0; i < implied_doloop->n_values; i++ ) { + if( ASR::is_a(*implied_doloop->m_values[i]) ) { + if( implied_doloop_size_ == nullptr ) { + implied_doloop_size_ = get_ImpliedDoLoop_size(al, + ASR::down_cast(implied_doloop->m_values[i])); + } else { + implied_doloop_size_ = builder.Add(get_ImpliedDoLoop_size(al, + ASR::down_cast(implied_doloop->m_values[i])), + implied_doloop_size_); + } + } else { + const_elements += 1; + } + } + if( const_elements > 1 ) { + if( implied_doloop_size_ == nullptr ) { + implied_doloop_size_ = make_ConstantWithKind(make_IntegerConstant_t, + make_Integer_t, const_elements, kind, loc); + } else { + implied_doloop_size_ = builder.Add( + make_ConstantWithKind(make_IntegerConstant_t, + make_Integer_t, const_elements, kind, loc), + implied_doloop_size_); + } + } + if( implied_doloop_size_ ) { + implied_doloop_size = builder.Mul(implied_doloop_size_, implied_doloop_size); + } + return implied_doloop_size; +} + +ASR::expr_t* get_ArrayConstructor_size(Allocator& al, ASR::ArrayConstructor_t* x) { + ASR::ttype_t* int_type = ASRUtils::TYPE(ASR::make_Integer_t(al, x->base.base.loc, 4)); + ASR::expr_t* array_size = nullptr; + int64_t constant_size = 0; + const Location& loc = x->base.base.loc; + ASRUtils::ASRBuilder builder(al, loc); + for( size_t i = 0; i < x->n_args; i++ ) { + ASR::expr_t* element = x->m_args[i]; + if( ASR::is_a(*element) ) { + if( ASRUtils::is_value_constant(element) ) { + constant_size += get_constant_ArrayConstant_size( + ASR::down_cast(element)); + } else { + ASR::expr_t* element_array_size = get_ArrayConstant_size(al, + ASR::down_cast(element)); + if( array_size == nullptr ) { + array_size = element_array_size; + } else { + array_size = builder.Add(array_size, + element_array_size); + } + } + } else if( ASR::is_a(*element) ) { + ASR::expr_t* element_array_size = get_ArrayConstructor_size(al, + ASR::down_cast(element)); + if( array_size == nullptr ) { + array_size = element_array_size; + } else { + array_size = builder.Add(array_size, + element_array_size); + } + } else if( ASR::is_a(*element) ) { + ASR::ttype_t* element_type = ASRUtils::type_get_past_allocatable( + ASRUtils::expr_type(element)); + if( ASRUtils::is_array(element_type) ) { + if( ASRUtils::is_fixed_size_array(element_type) ) { + ASR::dimension_t* m_dims = nullptr; + size_t n_dims = ASRUtils::extract_dimensions_from_ttype(element_type, m_dims); + constant_size += ASRUtils::get_fixed_size_of_array(m_dims, n_dims); + } else { + ASR::expr_t* element_array_size = ASRUtils::get_size(element, al); + if( array_size == nullptr ) { + array_size = element_array_size; + } else { + array_size = builder.Add(array_size, + element_array_size); + } + } + } else { + constant_size += 1; + } + } else if( ASR::is_a(*element) ) { + ASR::expr_t* implied_doloop_size = get_ImpliedDoLoop_size(al, + ASR::down_cast(element)); + if( array_size ) { + array_size = builder.Add(implied_doloop_size, array_size); + } else { + array_size = implied_doloop_size; + } + } else if( ASR::is_a(*element) ) { + ASR::ArraySection_t* array_section_t = ASR::down_cast(element); + ASR::expr_t* array_section_size = nullptr; + for( size_t j = 0; j < array_section_t->n_args; j++ ) { + ASR::expr_t* start = array_section_t->m_args[j].m_left; + ASR::expr_t* end = array_section_t->m_args[j].m_right; + ASR::expr_t* d = array_section_t->m_args[j].m_step; + if( d == nullptr ) { + continue; + } + ASR::expr_t* dim_size = builder.Add(builder.Div( + builder.Sub(end, start), d), + make_ConstantWithKind(make_IntegerConstant_t, make_Integer_t, 1, 4, loc)); + if( array_section_size == nullptr ) { + array_section_size = dim_size; + } else { + array_section_size = builder.Mul(array_section_size, dim_size); + } + } + if( array_size == nullptr ) { + array_size = array_section_size; + } else { + builder.Add(array_section_size, array_size); + } + } else { + constant_size += 1; + } + } + ASR::expr_t* constant_size_asr = nullptr; + if (constant_size == 0 && array_size == nullptr) { + constant_size = ASRUtils::get_fixed_size_of_array(x->m_type); + } + if( constant_size > 0 ) { + constant_size_asr = make_ConstantWithType(make_IntegerConstant_t, + constant_size, int_type, x->base.base.loc); + if( array_size == nullptr ) { + return constant_size_asr; + } + } + if( constant_size_asr ) { + array_size = builder.Add(array_size, constant_size_asr); + } + + if( array_size == nullptr ) { + array_size = make_ConstantWithKind(make_IntegerConstant_t, + make_Integer_t, 0, 4, x->base.base.loc); + } + return array_size; +} + +ASR::asr_t* make_ArraySize_t_util( + Allocator &al, const Location &a_loc, ASR::expr_t* a_v, + ASR::expr_t* a_dim, ASR::ttype_t* a_type, ASR::expr_t* a_value, + bool for_type) { + int dim = -1; + bool is_dimension_constant = (a_dim != nullptr) && ASRUtils::extract_value( + ASRUtils::expr_value(a_dim), dim); + ASR::ttype_t* array_func_type = nullptr; + if( ASR::is_a(*a_v) ) { + a_v = ASR::down_cast(a_v)->m_arg; + } + if ( ASR::is_a(*a_v) && for_type ) { + ASR::IntrinsicArrayFunction_t* af = ASR::down_cast(a_v); + int64_t dim_index = ASRUtils::IntrinsicArrayFunctionRegistry::get_dim_index( + static_cast(af->m_arr_intrinsic_id)); + ASR::expr_t* af_dim = nullptr; + if( dim_index == 1 && (size_t) dim_index < af->n_args && af->m_args[dim_index] != nullptr ) { + af_dim = af->m_args[dim_index]; + } + if ( ASRUtils::is_array(af->m_type) ) { + array_func_type = af->m_type; + } + for ( size_t i = 0; i < af->n_args; i++ ) { + if ( ASRUtils::is_array(ASRUtils::expr_type(af->m_args[i])) ) { + a_v = af->m_args[i]; + if ( ASR::is_a(*a_v)) { + a_v = ASR::down_cast(a_v)->m_arg; + } + break; + } + } + + if( af_dim != nullptr ) { + ASRBuilder builder(al, a_loc); + ASR::ttype_t* int32_type = ASRUtils::TYPE(ASR::make_Integer_t(al, a_loc, 4)); + if( a_dim == nullptr ) { + size_t rank = ASRUtils::extract_n_dims_from_ttype(ASRUtils::expr_type(a_v)); + Vec array_sizes; array_sizes.reserve(al, rank); + for( size_t i = 1; i <= rank; i++ ) { + ASR::expr_t* i_a_dim = ASRUtils::EXPR( + ASR::make_IntegerConstant_t(al, a_loc, i, int32_type)); + ASR::expr_t* i_dim_size = ASRUtils::EXPR(make_ArraySize_t_util( + al, a_loc, a_v, i_a_dim, a_type, nullptr, for_type)); + array_sizes.push_back(al, i_dim_size); + } + + rank--; + Vec merged_sizes; merged_sizes.reserve(al, rank); + for( size_t i = 0; i < rank; i++ ) { + Vec merge_args; merge_args.reserve(al, 3); + merge_args.push_back(al, array_sizes[i]); + merge_args.push_back(al, array_sizes[i + 1]); + merge_args.push_back(al, builder.Lt(builder.i32(i+1), af_dim)); + diag::Diagnostics diag; + merged_sizes.push_back(al, ASRUtils::EXPR( + ASRUtils::Merge::create_Merge(al, a_loc, merge_args, diag))); + } + + ASR::expr_t* size = merged_sizes[0]; + for( size_t i = 1; i < rank; i++ ) { + size = builder.Mul(merged_sizes[i], size); + } + + return &(size->base); + } else { + ASR::expr_t *dim_size_lt = ASRUtils::EXPR(make_ArraySize_t_util( + al, a_loc, a_v, a_dim, a_type, nullptr, for_type)); + ASR::expr_t *dim_size_gte = ASRUtils::EXPR(make_ArraySize_t_util( + al, a_loc, a_v, builder.Add(a_dim, builder.i_t(1, ASRUtils::expr_type(a_dim))), + a_type, nullptr, for_type)); + Vec merge_args; merge_args.reserve(al, 3); + merge_args.push_back(al, dim_size_lt); merge_args.push_back(al, dim_size_gte); + merge_args.push_back(al, builder.Lt(a_dim, af_dim)); + diag::Diagnostics diag; + return ASRUtils::Merge::create_Merge(al, a_loc, merge_args, diag); + } + } + } else if( ASR::is_a(*a_v) && for_type ) { + ASR::FunctionCall_t* function_call = ASR::down_cast(a_v); + ASR::dimension_t* m_dims = nullptr; + size_t n_dims = ASRUtils::extract_dimensions_from_ttype(function_call->m_type, m_dims); + if( ASRUtils::is_fixed_size_array(function_call->m_type) ) { + if( a_dim == nullptr ) { + return ASR::make_IntegerConstant_t(al, a_loc, + ASRUtils::get_fixed_size_of_array(function_call->m_type), a_type); + } else if( is_dimension_constant ) { + return &(m_dims[dim - 1].m_length->base); + } + } else { + if( a_dim == nullptr ) { + LCOMPILERS_ASSERT(m_dims[0].m_length); + ASR::expr_t* result = m_dims[0].m_length; + for( size_t i = 1; i < n_dims; i++ ) { + LCOMPILERS_ASSERT(m_dims[i].m_length); + result = ASRUtils::EXPR(ASR::make_IntegerBinOp_t(al, a_loc, + result, ASR::binopType::Mul, m_dims[i].m_length, a_type, nullptr)); + } + return &(result->base); + } else if( is_dimension_constant ) { + LCOMPILERS_ASSERT(m_dims[dim - 1].m_length); + return &(m_dims[dim - 1].m_length->base); + } + } + } else if( ASR::is_a(*a_v) && for_type ) { + ASR::IntrinsicElementalFunction_t* elemental = ASR::down_cast(a_v); + for( size_t i = 0; i < elemental->n_args; i++ ) { + if( ASRUtils::is_array(ASRUtils::expr_type(elemental->m_args[i])) ) { + a_v = elemental->m_args[i]; + break; + } + } + } + if( ASR::is_a(*a_v) ) { + ASR::ArraySection_t* array_section_t = ASR::down_cast(a_v); + if( a_dim == nullptr ) { + ASR::asr_t* const1 = ASR::make_IntegerConstant_t(al, a_loc, 1, a_type); + ASR::asr_t* size = const1; + for( size_t i = 0; i < array_section_t->n_args; i++ ) { + ASR::expr_t* start = array_section_t->m_args[i].m_left; + ASR::expr_t* end = array_section_t->m_args[i].m_right; + ASR::expr_t* d = array_section_t->m_args[i].m_step; + if( (start == nullptr || end == nullptr || d == nullptr) && + !ASRUtils::is_array(ASRUtils::expr_type(end))){ + continue; + } + ASR::expr_t* plus1 = nullptr; + // Case: A(:, iact) where iact is an array + if( ASRUtils::is_array(ASRUtils::expr_type(end)) ) { + ASR::ttype_t* arr_type = ASRUtils::expr_type(end); + bool is_func_with_unknown_return = (ASR::is_a(*end) && + ASRUtils::is_allocatable(ASRUtils::expr_type(end))) || ASR::is_a(*end); + if( ASRUtils::is_fixed_size_array(arr_type) ) { + int64_t arr_size = ASRUtils::get_fixed_size_of_array(arr_type); + plus1 = ASRUtils::EXPR(ASR::make_IntegerConstant_t(al, a_loc, arr_size, a_type)); + } else { + plus1 = ASRUtils::EXPR(ASRUtils::make_ArraySize_t_util(al, end->base.loc, end, + nullptr, a_type, ASRUtils::expr_value(end), !is_func_with_unknown_return)); + } + } else { + start = CastingUtil::perform_casting(start, a_type, al, a_loc); + end = CastingUtil::perform_casting(end, a_type, al, a_loc); + d = CastingUtil::perform_casting(d, a_type, al, a_loc); + ASR::expr_t* endminusstart = ASRUtils::EXPR(ASR::make_IntegerBinOp_t( + al, a_loc, end, ASR::binopType::Sub, start, a_type, nullptr)); + ASR::expr_t* byd = ASRUtils::EXPR(ASR::make_IntegerBinOp_t( + al, a_loc, endminusstart, ASR::binopType::Div, d, a_type, nullptr)); + plus1 = ASRUtils::EXPR(ASR::make_IntegerBinOp_t( + al, a_loc, byd, ASR::binopType::Add, ASRUtils::EXPR(const1), a_type, nullptr)); + } + size = ASR::make_IntegerBinOp_t(al, a_loc, ASRUtils::EXPR(size), + ASR::binopType::Mul, plus1, a_type, nullptr); + } + return size; + } else if( is_dimension_constant ) { + ASR::asr_t* const1 = ASR::make_IntegerConstant_t(al, a_loc, 1, a_type); + ASR::expr_t* start = array_section_t->m_args[dim - 1].m_left; + ASR::expr_t* end = array_section_t->m_args[dim - 1].m_right; + ASR::expr_t* d = array_section_t->m_args[dim - 1].m_step; + + // Case: A(:, iact) where iact is an array and dim = 2 + if( ASRUtils::is_array(ASRUtils::expr_type(end)) ) { + bool is_func_with_unknown_return = (ASR::is_a(*end) && + ASRUtils::is_allocatable(ASRUtils::expr_type(end))) || ASR::is_a(*end); + ASR::ttype_t* arr_type = ASRUtils::expr_type(end); + if( ASRUtils::is_fixed_size_array(arr_type) ) { + int64_t arr_size = ASRUtils::get_fixed_size_of_array(arr_type); + return ASR::make_IntegerConstant_t(al, a_loc, arr_size, a_type); + } else { + return ASRUtils::make_ArraySize_t_util(al, end->base.loc, end, + nullptr, a_type, ASRUtils::expr_value(end), !is_func_with_unknown_return); + } + } + + if( start == nullptr && d == nullptr ) { + return const1; + } + start = CastingUtil::perform_casting(start, a_type, al, a_loc); + end = CastingUtil::perform_casting(end, a_type, al, a_loc); + d = CastingUtil::perform_casting(d, a_type, al, a_loc); + ASR::expr_t* endminusstart = ASRUtils::EXPR(ASR::make_IntegerBinOp_t( + al, a_loc, end, ASR::binopType::Sub, start, a_type, nullptr)); + ASR::expr_t* byd = ASRUtils::EXPR(ASR::make_IntegerBinOp_t( + al, a_loc, endminusstart, ASR::binopType::Div, d, a_type, nullptr)); + return ASR::make_IntegerBinOp_t(al, a_loc, byd, ASR::binopType::Add, + ASRUtils::EXPR(const1), a_type, nullptr); + } + } + if( ASR::is_a(*a_v) ) { + ASR::ArrayItem_t* array_item_t = ASR::down_cast(a_v); + LCOMPILERS_ASSERT(ASRUtils::is_array(array_item_t->m_type)); + if( for_type ) { + LCOMPILERS_ASSERT(!ASRUtils::is_allocatable(array_item_t->m_type) && + !ASRUtils::is_pointer(array_item_t->m_type)); + } + if( a_dim == nullptr ) { + ASR::asr_t* const1 = ASR::make_IntegerConstant_t(al, a_loc, 1, a_type); + ASR::asr_t* size = const1; + for( size_t i = 0; i < array_item_t->n_args; i++ ) { + ASR::expr_t* end = ASRUtils::EXPR(make_ArraySize_t_util(al, a_loc, + array_item_t->m_args[i].m_right, a_dim, a_type, nullptr, for_type)); + size = ASR::make_IntegerBinOp_t(al, a_loc, ASRUtils::EXPR(size), + ASR::binopType::Mul, end, a_type, nullptr); + } + return size; + } else if( is_dimension_constant ) { + return make_ArraySize_t_util(al, a_loc, + array_item_t->m_args[dim].m_right, + nullptr, a_type, nullptr, for_type); + } + } + if( is_binop_expr(a_v) && for_type ) { + if( ASR::is_a(*extract_member_from_binop(a_v, 1)) ) { + return make_ArraySize_t_util(al, a_loc, extract_member_from_binop(a_v, 1), a_dim, a_type, a_value, for_type); + } else { + return make_ArraySize_t_util(al, a_loc, extract_member_from_binop(a_v, 0), a_dim, a_type, a_value, for_type); + } + } else if( is_unaryop_expr(a_v) && for_type ) { + return make_ArraySize_t_util(al, a_loc, extract_member_from_unaryop(a_v), a_dim, a_type, a_value, for_type); + } else if( ASR::is_a(*a_v) && for_type ) { + ASR::ArrayConstructor_t* array_constructor = ASR::down_cast(a_v); + return &(get_ArrayConstructor_size(al, array_constructor)->base); + } else { + ASR::dimension_t* m_dims = nullptr; + size_t n_dims = 0; + if (array_func_type != nullptr) n_dims = ASRUtils::extract_dimensions_from_ttype(array_func_type, m_dims); + else n_dims = ASRUtils::extract_dimensions_from_ttype(ASRUtils::expr_type(a_v), m_dims); + bool is_dimension_dependent_only_on_arguments_ = is_dimension_dependent_only_on_arguments(m_dims, n_dims); + + bool compute_size = (is_dimension_dependent_only_on_arguments_ && + (is_dimension_constant || a_dim == nullptr)); + if( compute_size && for_type ) { + ASR::dimension_t* m_dims = nullptr; + if (array_func_type != nullptr) n_dims = ASRUtils::extract_dimensions_from_ttype(array_func_type, m_dims); + else n_dims = ASRUtils::extract_dimensions_from_ttype(ASRUtils::expr_type(a_v), m_dims); + if( a_dim == nullptr ) { + ASR::asr_t* size = ASR::make_IntegerConstant_t(al, a_loc, 1, a_type); + for( size_t i = 0; i < n_dims; i++ ) { + size = ASR::make_IntegerBinOp_t(al, a_loc, ASRUtils::EXPR(size), + ASR::binopType::Mul, m_dims[i].m_length, a_type, nullptr); + } + return size; + } else if( is_dimension_constant ) { + return (ASR::asr_t*) m_dims[dim - 1].m_length; + } + } + } + + + if( for_type ) { + LCOMPILERS_ASSERT_MSG( + ASR::is_a(*a_v) || + ASR::is_a(*a_v) || + ASR::is_a(*a_v), + "Found ASR::exprType::" + std::to_string(a_v->type)); + } + + return ASR::make_ArraySize_t(al, a_loc, a_v, a_dim, a_type, a_value); +} //Initialize pointer to zero so that it can be initialized in first call to get_instance ASRUtils::LabelGenerator* ASRUtils::LabelGenerator::label_generator = nullptr; @@ -1745,7 +2186,7 @@ ASR::expr_t *type_enum_to_asr_expr(Allocator &al, enum TTYPE_T t, const Location type = ASRUtils::TYPE(ASR::make_Real_t(al, l, 8)); break; case STR: - type = ASRUtils::TYPE(ASR::make_Character_t(al, l, 1, -2, nullptr)); + type = ASRUtils::TYPE(ASR::make_String_t(al, l, 1, -2, nullptr, ASR::string_physical_typeType::PointerString)); break; case PTR: type = ASRUtils::TYPE(ASR::make_CPtr_t(al, l)); @@ -1758,7 +2199,7 @@ ASR::expr_t *type_enum_to_asr_expr(Allocator &al, enum TTYPE_T t, const Location ASR::symbol_t *v = ASR::down_cast(ASR::make_Variable_t(al, l, current_scope, s.c_str(al), nullptr, 0, intent, nullptr, nullptr, ASR::storage_typeType::Default, type, nullptr, ASR::abiType::BindC, ASR::Public, - ASR::presenceType::Required, true)); + ASR::presenceType::Required, true, false)); current_scope->add_symbol(n, v); return ASRUtils::EXPR(ASR::make_Var_t(al, l, v)); } diff --git a/src/libasr/asr_utils.h b/src/libasr/asr_utils.h index 42d64c4c1c..8f74d184fa 100644 --- a/src/libasr/asr_utils.h +++ b/src/libasr/asr_utils.h @@ -3,7 +3,6 @@ #include #include -#include #include #include @@ -11,6 +10,13 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include #include @@ -61,6 +67,10 @@ ASR::asr_t* make_Binop_util(Allocator &al, const Location& loc, ASR::binopType b ASR::asr_t* make_Cmpop_util(Allocator &al, const Location& loc, ASR::cmpopType cmpop, ASR::expr_t* lexpr, ASR::expr_t* rexpr, ASR::ttype_t* ttype); +inline bool check_equal_type(ASR::ttype_t* x, ASR::ttype_t* y, bool check_for_dimensions=false); + +static inline std::string type_to_str_python(const ASR::ttype_t *t, bool for_error_message=true); + static inline double extract_real(const char *s) { // TODO: this is inefficient. We should // convert this in the tokenizer where we know most information @@ -112,6 +122,16 @@ static inline ASR::symbol_t *symbol_get_past_external(ASR::symbol_t *f) } } +static inline ASR::symbol_t* symbol_get_past_ClassProcedure(ASR::symbol_t* f){ + LCOMPILERS_ASSERT(f != nullptr); + if(ASR::is_a(*f)){ + ASR::symbol_t* func = ASR::down_cast(f)->m_proc; + LCOMPILERS_ASSERT(func != nullptr); + return func; + } + return f; +} + template Location get_vec_loc(const Vec& args) { LCOMPILERS_ASSERT(args.size() > 0); @@ -173,6 +193,20 @@ static inline ASR::ttype_t *type_get_past_allocatable(ASR::ttype_t *f) } } +static inline ASR::expr_t* get_past_array_physical_cast(ASR::expr_t* x) { + if( !ASR::is_a(*x) ) { + return x; + } + return ASR::down_cast(x)->m_arg; +} + +static inline ASR::expr_t* get_past_array_broadcast(ASR::expr_t* x) { + if( !ASR::is_a(*x) ) { + return x; + } + return ASR::down_cast(x)->m_array; +} + static inline ASR::ttype_t *type_get_past_array(ASR::ttype_t *f) { if (ASR::is_a(*f)) { @@ -184,6 +218,18 @@ static inline ASR::ttype_t *type_get_past_array(ASR::ttype_t *f) } } +static inline ASR::ttype_t* extract_type(ASR::ttype_t *f) { + return type_get_past_array( + type_get_past_allocatable( + type_get_past_pointer(f))); +} + +static inline ASR::ttype_t* type_get_past_allocatable_pointer(ASR::ttype_t* f) { + return type_get_past_allocatable( + type_get_past_pointer(f) + ); +} + static inline int extract_kind_from_ttype_t(const ASR::ttype_t* type) { if (type == nullptr) { return -1; @@ -204,8 +250,8 @@ static inline int extract_kind_from_ttype_t(const ASR::ttype_t* type) { case ASR::ttypeType::Complex: { return ASR::down_cast(type)->m_kind; } - case ASR::ttypeType::Character: { - return ASR::down_cast(type)->m_kind; + case ASR::ttypeType::String: { + return ASR::down_cast(type)->m_kind; } case ASR::ttypeType::Logical: { return ASR::down_cast(type)->m_kind; @@ -247,8 +293,8 @@ static inline void set_kind_to_ttype_t(ASR::ttype_t* type, int kind) { ASR::down_cast(type)->m_kind = kind; break; } - case ASR::ttypeType::Character: { - ASR::down_cast(type)->m_kind = kind; + case ASR::ttypeType::String: { + ASR::down_cast(type)->m_kind = kind; break; } case ASR::ttypeType::Logical: { @@ -302,8 +348,8 @@ static inline ASR::ttype_t* symbol_type(const ASR::symbol_t *f) case ASR::symbolType::Variable: { return ASR::down_cast(f)->m_type; } - case ASR::symbolType::EnumType: { - return ASR::down_cast(f)->m_type; + case ASR::symbolType::Enum: { + return ASR::down_cast(f)->m_type; } case ASR::symbolType::ExternalSymbol: { return symbol_type(ASRUtils::symbol_get_past_external(f)); @@ -320,14 +366,40 @@ static inline ASR::ttype_t* symbol_type(const ASR::symbol_t *f) return nullptr; } +static inline std::string symbol_type_name(const ASR::symbol_t &s) +{ + switch( s.type ) { + case ASR::symbolType::Program: return "Program"; + case ASR::symbolType::Module: return "Module"; + case ASR::symbolType::Function: return "Function"; + case ASR::symbolType::GenericProcedure: return "GenericProcedure"; + case ASR::symbolType::CustomOperator: return "CustomOperator"; + case ASR::symbolType::ExternalSymbol: return "ExternalSymbol"; + case ASR::symbolType::Struct: return "Struct"; + case ASR::symbolType::Enum: return "Enum"; + case ASR::symbolType::Union: return "Union"; + case ASR::symbolType::Variable: return "Variable"; + case ASR::symbolType::Class: return "Class"; + case ASR::symbolType::ClassProcedure: return "ClassProcedure"; + case ASR::symbolType::AssociateBlock: return "AssociateBlock"; + case ASR::symbolType::Block: return "Block"; + case ASR::symbolType::Requirement: return "Requirement"; + case ASR::symbolType::Template: return "Template"; + default: { + LCOMPILERS_ASSERT(false); + } + } + return ""; +} + static inline ASR::abiType symbol_abi(const ASR::symbol_t *f) { switch( f->type ) { case ASR::symbolType::Variable: { return ASR::down_cast(f)->m_abi; } - case ASR::symbolType::EnumType: { - return ASR::down_cast(f)->m_abi; + case ASR::symbolType::Enum: { + return ASR::down_cast(f)->m_abi; } case ASR::symbolType::ExternalSymbol: { return symbol_abi(ASR::down_cast(f)->m_external); @@ -361,9 +433,9 @@ static inline ASR::ttype_t* get_contained_type(ASR::ttype_t* asr_type, int overl return asr_type; } } - case ASR::ttypeType::Enum: { - ASR::Enum_t* enum_asr = ASR::down_cast(asr_type); - ASR::EnumType_t* enum_type = ASR::down_cast(enum_asr->m_enum_type); + case ASR::ttypeType::EnumType: { + ASR::EnumType_t* enum_asr = ASR::down_cast(asr_type); + ASR::Enum_t* enum_type = ASR::down_cast(enum_asr->m_enum_type); return enum_type->m_type; } case ASR::ttypeType::Pointer: { @@ -393,7 +465,7 @@ static inline ASR::array_physical_typeType extract_physical_type(ASR::ttype_t* e } default: throw LCompilersException("Cannot extract the physical type of " + - std::to_string(e->type) + " type."); + ASRUtils::type_to_str_python(e) + " type."); } } @@ -421,8 +493,8 @@ static inline ASR::abiType expr_abi(ASR::expr_t* e) { return ASRUtils::expr_abi(ASR::down_cast(e)->m_arg); } default: - throw LCompilersException("Cannot extract the ABI of " + - std::to_string(e->type) + " expression."); + throw LCompilersException(std::string("Cannot extract the ABI of ") + + "ASR::exprType::" + std::to_string(e->type) + " expression."); } } @@ -444,11 +516,11 @@ static inline char *symbol_name(const ASR::symbol_t *f) case ASR::symbolType::Struct: { return ASR::down_cast(f)->m_name; } - case ASR::symbolType::EnumType: { - return ASR::down_cast(f)->m_name; + case ASR::symbolType::Enum: { + return ASR::down_cast(f)->m_name; } - case ASR::symbolType::UnionType: { - return ASR::down_cast(f)->m_name; + case ASR::symbolType::Union: { + return ASR::down_cast(f)->m_name; } case ASR::symbolType::Variable: { return ASR::down_cast(f)->m_name; @@ -521,7 +593,7 @@ static inline void encode_dimensions(size_t n_dims, std::string& res, } } -static inline std::string type_to_str(const ASR::ttype_t *t) +static inline std::string type_to_str_fortran(const ASR::ttype_t *t) { switch (t->type) { case ASR::ttypeType::Integer: { @@ -539,8 +611,8 @@ static inline std::string type_to_str(const ASR::ttype_t *t) case ASR::ttypeType::Logical: { return "logical"; } - case ASR::ttypeType::Character: { - return "character"; + case ASR::ttypeType::String: { + return "string"; } case ASR::ttypeType::Tuple: { return "tuple"; @@ -557,26 +629,26 @@ static inline std::string type_to_str(const ASR::ttype_t *t) case ASR::ttypeType::StructType: { return ASRUtils::symbol_name(ASR::down_cast(t)->m_derived_type); } - case ASR::ttypeType::Class: { - return ASRUtils::symbol_name(ASR::down_cast(t)->m_class_type); + case ASR::ttypeType::ClassType: { + return ASRUtils::symbol_name(ASR::down_cast(t)->m_class_type); } - case ASR::ttypeType::Union: { + case ASR::ttypeType::UnionType: { return "union"; } case ASR::ttypeType::CPtr: { return "type(c_ptr)"; } case ASR::ttypeType::Pointer: { - return type_to_str(ASRUtils::type_get_past_pointer( + return type_to_str_fortran(ASRUtils::type_get_past_pointer( const_cast(t))) + " pointer"; } case ASR::ttypeType::Allocatable: { - return type_to_str(ASRUtils::type_get_past_allocatable( + return type_to_str_fortran(ASRUtils::type_get_past_allocatable( const_cast(t))) + " allocatable"; } case ASR::ttypeType::Array: { ASR::Array_t* array_t = ASR::down_cast(t); - std::string res = type_to_str(array_t->m_type); + std::string res = type_to_str_fortran(array_t->m_type); encode_dimensions(array_t->n_dims, res, false); return res; } @@ -591,23 +663,23 @@ static inline std::string type_to_str(const ASR::ttype_t *t) ASR::FunctionType_t* ftp = ASR::down_cast(t); std::string result = "("; for( size_t i = 0; i < ftp->n_arg_types; i++ ) { - result += type_to_str(ftp->m_arg_types[i]) + ", "; + result += type_to_str_fortran(ftp->m_arg_types[i]) + ", "; } result += "return_type: "; if( ftp->m_return_var_type ) { - result += type_to_str(ftp->m_return_var_type); + result += type_to_str_fortran(ftp->m_return_var_type); } else { result += "void"; } result += ")"; return result; } - default : throw LCompilersException("Not implemented " + std::to_string(t->type) + "."); + default : throw LCompilersException("Not implemented " + ASRUtils::type_to_str_python(t) + "."); } } static inline std::string type_to_str_with_type(const ASR::ttype_t *t) { - std::string type = type_to_str(t); + std::string type = type_to_str_fortran(t); std::string kind = std::to_string(extract_kind_from_ttype_t(t)); return type + "(" + kind + ")"; } @@ -649,7 +721,7 @@ static inline std::string type_to_str_with_substitution(const ASR::ttype_t *t, result += ")"; return result; } - default : return type_to_str(t); + default : return type_to_str_fortran(t); } } @@ -709,12 +781,12 @@ static inline std::pair symbol_dependencies(const ASR::symbol_t ASR::Struct_t* sym = ASR::down_cast(f); return std::make_pair(sym->m_dependencies, sym->n_dependencies); } - case ASR::symbolType::EnumType: { - ASR::EnumType_t* sym = ASR::down_cast(f); + case ASR::symbolType::Enum: { + ASR::Enum_t* sym = ASR::down_cast(f); return std::make_pair(sym->m_dependencies, sym->n_dependencies); } - case ASR::symbolType::UnionType: { - ASR::UnionType_t* sym = ASR::down_cast(f); + case ASR::symbolType::Union: { + ASR::Union_t* sym = ASR::down_cast(f); return std::make_pair(sym->m_dependencies, sym->n_dependencies); } default : throw LCompilersException("Not implemented"); @@ -750,11 +822,11 @@ static inline SymbolTable *symbol_parent_symtab(const ASR::symbol_t *f) case ASR::symbolType::Struct: { return ASR::down_cast(f)->m_symtab->parent; } - case ASR::symbolType::EnumType: { - return ASR::down_cast(f)->m_symtab->parent; + case ASR::symbolType::Enum: { + return ASR::down_cast(f)->m_symtab->parent; } - case ASR::symbolType::UnionType: { - return ASR::down_cast(f)->m_symtab->parent; + case ASR::symbolType::Union: { + return ASR::down_cast(f)->m_symtab->parent; } case ASR::symbolType::Variable: { return ASR::down_cast(f)->m_parent_symtab; @@ -804,11 +876,11 @@ static inline SymbolTable *symbol_symtab(const ASR::symbol_t *f) case ASR::symbolType::Struct: { return ASR::down_cast(f)->m_symtab; } - case ASR::symbolType::EnumType: { - return ASR::down_cast(f)->m_symtab; + case ASR::symbolType::Enum: { + return ASR::down_cast(f)->m_symtab; } - case ASR::symbolType::UnionType: { - return ASR::down_cast(f)->m_symtab; + case ASR::symbolType::Union: { + return ASR::down_cast(f)->m_symtab; } case ASR::symbolType::Variable: { return nullptr; @@ -913,6 +985,21 @@ static inline bool is_c_ptr(ASR::symbol_t* v, std::string v_name="") { return false; } +static inline bool is_c_funptr(ASR::symbol_t* v, std::string v_name="") { + if( v_name == "" ) { + v_name = ASRUtils::symbol_name(v); + } + ASR::symbol_t* v_orig = ASRUtils::symbol_get_past_external(v); + if( ASR::is_a(*v_orig) ) { + ASR::Module_t* der_type_module = ASRUtils::get_sym_module0(v_orig); + return (der_type_module && std::string(der_type_module->m_name) == + "lfortran_intrinsic_iso_c_binding" && + der_type_module->m_intrinsic && + v_name == "c_funptr"); + } + return false; +} + // Returns true if the Function is intrinsic, otherwise false template static inline bool is_intrinsic_procedure(const T *fn) { @@ -976,13 +1063,57 @@ static inline bool all_args_have_value(const Vec &args) { return true; } +/* + +This function determines if a given expression represents a variable according +to the rules of Fortran variable definitions. Here's an illustration of declaration's: + +```fortran + CHARACTER(len=5) x, y(3) + INTEGER, PARAMETER :: i + TYPE (EMPLOYEE) e + INTEGER age + END TYPE EMPLOYEE +``` + +then 'x', 'y', 'y(1)', 'y(1:2)', 'e % age' are all variables, while 'i' isn't + +TODO: this definitely needs some extensions to include others as "variable"'s +*/ +static inline bool is_variable(ASR::expr_t* a_value) { + if (a_value == nullptr) { + return false; + } + switch (a_value->type) { + case ASR::exprType::ArrayItem: { + ASR::ArrayItem_t* a_item = ASR::down_cast(a_value); + ASR::expr_t* array_expr = a_item->m_v; + ASR::Variable_t* array_var = ASRUtils::EXPR2VAR(array_expr); + // a constant array's item isn't a "variable" + return array_var->m_storage != ASR::storage_typeType::Parameter; + } + case ASR::exprType::Var: { + ASR::Variable_t* variable_t = ASRUtils::EXPR2VAR(a_value); + return variable_t->m_storage != ASR::storage_typeType::Parameter; + } + case ASR::exprType::StringItem: + case ASR::exprType::StringSection: + case ASR::exprType::ArraySection: + case ASR::exprType::StructInstanceMember: { + return true; + } + default: { + return false; + } + } +} + static inline bool is_value_constant(ASR::expr_t *a_value) { if( a_value == nullptr ) { return false; } switch ( a_value->type ) { case ASR::exprType::IntegerConstant: - case ASR::exprType::IntegerBOZ: case ASR::exprType::UnsignedIntegerConstant: case ASR::exprType::RealConstant: case ASR::exprType::ComplexConstant: @@ -990,13 +1121,15 @@ static inline bool is_value_constant(ASR::expr_t *a_value) { case ASR::exprType::ImpliedDoLoop: case ASR::exprType::PointerNullConstant: case ASR::exprType::ArrayConstant: - case ASR::exprType::StringConstant: { + case ASR::exprType::StringConstant: + case ASR::exprType::StructConstant: { return true; } case ASR::exprType::RealBinOp: case ASR::exprType::IntegerUnaryMinus: case ASR::exprType::RealUnaryMinus: case ASR::exprType::IntegerBinOp: + case ASR::exprType::ArrayConstructor: case ASR::exprType::StringLen: { return is_value_constant(expr_value(a_value)); } case ASR::exprType::ListConstant: { @@ -1021,7 +1154,20 @@ static inline bool is_value_constant(ASR::expr_t *a_value) { return false; } } + return true; + } case ASR::exprType::IntrinsicArrayFunction: { + ASR::IntrinsicArrayFunction_t* intrinsic_array_function = + ASR::down_cast(a_value); + + if (ASRUtils::is_value_constant(intrinsic_array_function->m_value)) { + return true; + } + for( size_t i = 0; i < intrinsic_array_function->n_args; i++ ) { + if( !ASRUtils::is_value_constant(intrinsic_array_function->m_args[i]) ) { + return false; + } + } return true; } case ASR::exprType::FunctionCall: { ASR::FunctionCall_t* func_call_t = ASR::down_cast(a_value); @@ -1054,6 +1200,8 @@ static inline bool is_value_constant(ASR::expr_t *a_value) { ASR::Variable_t* variable_t = ASR::down_cast( ASRUtils::symbol_get_past_external(var_t->m_v)); return variable_t->m_storage == ASR::storage_typeType::Parameter; + } else if(ASR::is_a(*ASRUtils::symbol_get_past_external(var_t->m_v))){ + return true; } else { return false; } @@ -1064,6 +1212,10 @@ static inline bool is_value_constant(ASR::expr_t *a_value) { ASR::ArrayReshape_t* array_reshape = ASR::down_cast(a_value); return is_value_constant(array_reshape->m_array) && is_value_constant(array_reshape->m_shape); + } case ASR::exprType::ArrayIsContiguous: { + ASR::ArrayIsContiguous_t* + array_is_contiguous = ASR::down_cast(a_value); + return is_value_constant(array_is_contiguous->m_array); } case ASR::exprType::ArrayPhysicalCast: { ASR::ArrayPhysicalCast_t* array_physical_t = ASR::down_cast(a_value); @@ -1310,11 +1462,6 @@ static inline bool extract_value(ASR::expr_t* value_expr, T& value) { value = (T) const_int->m_n; break; } - case ASR::exprType::IntegerBOZ: { - ASR::IntegerBOZ_t* int_boz = ASR::down_cast(value_expr); - value = (T) int_boz->m_v; - break; - } case ASR::exprType::UnsignedIntegerConstant: { ASR::UnsignedIntegerConstant_t* const_int = ASR::down_cast(value_expr); value = (T) const_int->m_n; @@ -1364,6 +1511,16 @@ static inline std::string extract_dim_value(ASR::expr_t* dim) { return std::to_string(length_dim); } +static inline std::int64_t extract_dim_value_int(ASR::expr_t* dim) { + int64_t length_dim = 0; + if( dim == nullptr || + !ASRUtils::extract_value(ASRUtils::expr_value(dim), length_dim)) { + return -1; + } + + return length_dim; +} + static inline std::string type_encode_dims(size_t n_dims, ASR::dimension_t* m_dims ) { std::string dims_str = "["; @@ -1418,7 +1575,7 @@ static inline std::string get_type_code(const ASR::ttype_t *t, bool use_undersco res = "i1"; break; } - case ASR::ttypeType::Character: { + case ASR::ttypeType::String: { return "str"; } case ASR::ttypeType::Tuple: { @@ -1490,8 +1647,8 @@ static inline std::string get_type_code(const ASR::ttype_t *t, bool use_undersco } break; } - case ASR::ttypeType::Class: { - ASR::Class_t* d = ASR::down_cast(t); + case ASR::ttypeType::ClassType: { + ASR::ClassType_t* d = ASR::down_cast(t); if( ASRUtils::symbol_get_past_external(d->m_class_type) ) { res = symbol_name(ASRUtils::symbol_get_past_external(d->m_class_type)); } else { @@ -1499,8 +1656,8 @@ static inline std::string get_type_code(const ASR::ttype_t *t, bool use_undersco } break; } - case ASR::ttypeType::Union: { - ASR::Union_t* d = ASR::down_cast(t); + case ASR::ttypeType::UnionType: { + ASR::UnionType_t* d = ASR::down_cast(t); res = symbol_name(d->m_union_type); break; } @@ -1531,7 +1688,7 @@ static inline std::string get_type_code(const ASR::ttype_t *t, bool use_undersco } default: { throw LCompilersException("Type encoding not implemented for " - + std::to_string(t->type)); + + ASRUtils::type_to_str_python(t)); } } if( is_dimensional && set_dimensional_hint ) { @@ -1549,8 +1706,7 @@ static inline std::string get_type_code(ASR::ttype_t** types, size_t n_types, return code; } -static inline std::string type_to_str_python(const ASR::ttype_t *t, - bool for_error_message=true) +static inline std::string type_to_str_python(const ASR::ttype_t *t, bool for_error_message) { switch (t->type) { case ASR::ttypeType::Array: { @@ -1605,7 +1761,7 @@ static inline std::string type_to_str_python(const ASR::ttype_t *t, case ASR::ttypeType::Logical: { return "bool"; } - case ASR::ttypeType::Character: { + case ASR::ttypeType::String: { return "str"; } case ASR::ttypeType::Tuple: { @@ -1639,12 +1795,12 @@ static inline std::string type_to_str_python(const ASR::ttype_t *t, ASR::StructType_t* d = ASR::down_cast(t); return "struct " + std::string(symbol_name(d->m_derived_type)); } - case ASR::ttypeType::Enum: { - ASR::Enum_t* d = ASR::down_cast(t); + case ASR::ttypeType::EnumType: { + ASR::EnumType_t* d = ASR::down_cast(t); return "enum " + std::string(symbol_name(d->m_enum_type)); } - case ASR::ttypeType::Union: { - ASR::Union_t* d = ASR::down_cast(t); + case ASR::ttypeType::UnionType: { + ASR::UnionType_t* d = ASR::down_cast(t); return "union " + std::string(symbol_name(d->m_union_type)); } case ASR::ttypeType::Pointer: { @@ -1682,7 +1838,7 @@ static inline std::string binop_to_str_python(const ASR::binopType t) { } static inline bool is_immutable(const ASR::ttype_t *type) { - return ((ASR::is_a(*type) || ASR::is_a(*type) + return ((ASR::is_a(*type) || ASR::is_a(*type) || ASR::is_a(*type))); } @@ -1743,6 +1899,9 @@ static inline ASR::expr_t* get_constant_zero_with_given_type(Allocator& al, ASR: case ASR::ttypeType::Integer: { return ASRUtils::EXPR(ASR::make_IntegerConstant_t(al, asr_type->base.loc, 0, asr_type)); } + case ASR::ttypeType::UnsignedInteger: { + return ASRUtils::EXPR(ASR::make_UnsignedIntegerConstant_t(al, asr_type->base.loc, 0, asr_type)); + } case ASR::ttypeType::Real: { return ASRUtils::EXPR(ASR::make_RealConstant_t(al, asr_type->base.loc, 0.0, asr_type)); } @@ -1753,7 +1912,7 @@ static inline ASR::expr_t* get_constant_zero_with_given_type(Allocator& al, ASR: return ASRUtils::EXPR(ASR::make_LogicalConstant_t(al, asr_type->base.loc, false, asr_type)); } default: { - throw LCompilersException("get_constant_zero_with_given_type: Not implemented " + std::to_string(asr_type->type)); + throw LCompilersException("get_constant_zero_with_given_type: Not implemented " + ASRUtils::type_to_str_python(asr_type)); } } return nullptr; @@ -1776,7 +1935,7 @@ static inline ASR::expr_t* get_constant_one_with_given_type(Allocator& al, ASR:: return ASRUtils::EXPR(ASR::make_LogicalConstant_t(al, asr_type->base.loc, true, asr_type)); } default: { - throw LCompilersException("get_constant_one_with_given_type: Not implemented " + std::to_string(asr_type->type)); + throw LCompilersException("get_constant_one_with_given_type: Not implemented " + ASRUtils::type_to_str_python(asr_type)); } } return nullptr; @@ -1809,7 +1968,7 @@ static inline ASR::expr_t* get_minimum_value_with_given_type(Allocator& al, ASR: return ASRUtils::EXPR(ASR::make_RealConstant_t(al, asr_type->base.loc, val, asr_type)); } default: { - throw LCompilersException("get_minimum_value_with_given_type: Not implemented " + std::to_string(asr_type->type)); + throw LCompilersException("get_minimum_value_with_given_type: Not implemented " + ASRUtils::type_to_str_python(asr_type)); } } return nullptr; @@ -1842,7 +2001,7 @@ static inline ASR::expr_t* get_maximum_value_with_given_type(Allocator& al, ASR: return ASRUtils::EXPR(ASR::make_RealConstant_t(al, asr_type->base.loc, val, asr_type)); } default: { - throw LCompilersException("get_maximum_value_with_given_type: Not implemented " + std::to_string(asr_type->type)); + throw LCompilersException("get_maximum_value_with_given_type: Not implemented " + ASRUtils::type_to_str_python(asr_type)); } } return nullptr; @@ -1868,6 +2027,23 @@ static inline bool main_program_present(const ASR::TranslationUnit_t &unit) return false; } +static inline bool global_function_present(const ASR::TranslationUnit_t &unit) +{ + bool contains_global_function = false; + + for (auto &a : unit.m_symtab->get_scope()) { + if (ASR::is_a(*a.second)) { + contains_global_function = true; + } else if (ASR::is_a(*a.second)) { + // If the ASR contains a module, then the global + // function is not the only symbol present. + return false; + } + } + + return contains_global_function; +} + // Accepts dependencies in the form A -> [B, D, ...], B -> [C, D] // Returns a list of dependencies in the order that they should be built: // [D, C, B, A] @@ -1909,11 +2085,13 @@ ASR::Module_t* load_module(Allocator &al, SymbolTable *symtab, const Location &loc, bool intrinsic, LCompilers::PassOptions& pass_options, bool run_verify, - const std::function err); + const std::function err, + LCompilers::LocationManager &lm); ASR::TranslationUnit_t* find_and_load_module(Allocator &al, const std::string &msym, SymbolTable &symtab, bool intrinsic, - LCompilers::PassOptions& pass_options); + LCompilers::PassOptions& pass_options, + LCompilers::LocationManager &lm); void set_intrinsic(ASR::TranslationUnit_t* trans_unit); @@ -2014,7 +2192,7 @@ static inline bool is_real(ASR::ttype_t &x) { } static inline bool is_character(ASR::ttype_t &x) { - return ASR::is_a( + return ASR::is_a( *type_get_past_array( type_get_past_allocatable( type_get_past_pointer(&x)))); @@ -2027,6 +2205,12 @@ static inline bool is_complex(ASR::ttype_t &x) { type_get_past_pointer(&x)))); } +template +static inline bool is_complex(ASR::ttype_t &x) { + return is_complex(x) && ASRUtils::extract_kind_from_ttype_t(&x) == kind; +} + + static inline bool is_logical(ASR::ttype_t &x) { return ASR::is_a( *type_get_past_array( @@ -2034,6 +2218,11 @@ static inline bool is_logical(ASR::ttype_t &x) { type_get_past_pointer(&x)))); } +static inline bool is_struct(ASR::ttype_t& x) { + return ASR::is_a( + *extract_type(&x)); +} + // Checking if the ttype 't' is a type parameter static inline bool is_type_parameter(ASR::ttype_t &x) { switch (x.type) { @@ -2147,12 +2336,12 @@ inline size_t extract_dimensions_from_ttype(ASR::ttype_t *x, case ASR::ttypeType::UnsignedInteger: case ASR::ttypeType::Real: case ASR::ttypeType::Complex: - case ASR::ttypeType::Character: + case ASR::ttypeType::String: case ASR::ttypeType::Logical: case ASR::ttypeType::StructType: - case ASR::ttypeType::Enum: - case ASR::ttypeType::Union: - case ASR::ttypeType::Class: + case ASR::ttypeType::EnumType: + case ASR::ttypeType::UnionType: + case ASR::ttypeType::ClassType: case ASR::ttypeType::List: case ASR::ttypeType::Tuple: case ASR::ttypeType::Dict: @@ -2165,21 +2354,11 @@ inline size_t extract_dimensions_from_ttype(ASR::ttype_t *x, break; } default: - throw LCompilersException("Not implemented " + std::to_string(x->type) + "."); + throw LCompilersException("Not implemented " + ASRUtils::type_to_str_python(x) + "."); } return n_dims; } -static inline ASR::ttype_t *extract_type(ASR::ttype_t *type) { - // return type_get_past_const( - // type_get_past_array( - // type_get_past_allocatable( - // type_get_past_pointer(type)))); - return type_get_past_array( - type_get_past_allocatable( - type_get_past_pointer(type))); -} - static inline bool is_fixed_size_array(ASR::dimension_t* m_dims, size_t n_dims) { if( n_dims == 0 ) { return false; @@ -2243,10 +2422,21 @@ static inline bool is_dimension_empty(ASR::dimension_t* dims, size_t n) { return false; } +static inline bool is_dimension_empty(ASR::ttype_t* type) { + ASR::dimension_t* dims = nullptr; + size_t n = ASRUtils::extract_dimensions_from_ttype(type, dims); + return is_dimension_empty(dims, n); +} + static inline bool is_only_upper_bound_empty(ASR::dimension_t& dim) { return (dim.m_start != nullptr && dim.m_length == nullptr); } +inline bool is_array(ASR::ttype_t *x) { + ASR::dimension_t* dims = nullptr; + return extract_dimensions_from_ttype(x, dims) > 0; +} + class ExprDependentOnlyOnArguments: public ASR::BaseWalkVisitor { public: @@ -2259,7 +2449,11 @@ class ExprDependentOnlyOnArguments: public ASR::BaseWalkVisitor(*x.m_v) ) { ASR::Variable_t* x_m_v = ASR::down_cast(x.m_v); - is_dependent_only_on_argument = is_dependent_only_on_argument && ASRUtils::is_arg_dummy(x_m_v->m_intent); + if ( ASRUtils::is_array(x_m_v->m_type) ) { + is_dependent_only_on_argument = is_dependent_only_on_argument && ASRUtils::is_arg_dummy(x_m_v->m_intent); + } else { + is_dependent_only_on_argument = is_dependent_only_on_argument && (x_m_v->m_intent == ASR::intentType::In); + } } else { is_dependent_only_on_argument = false; } @@ -2281,85 +2475,123 @@ static inline bool is_dimension_dependent_only_on_arguments(ASR::dimension_t* m_ return true; } -static inline ASR::asr_t* make_ArraySize_t_util( - Allocator &al, const Location &a_loc, ASR::expr_t* a_v, - ASR::expr_t* a_dim, ASR::ttype_t* a_type, ASR::expr_t* a_value, - bool for_type=true) { - int dim = -1; - bool is_dimension_constant = (a_dim != nullptr) && ASRUtils::extract_value( - ASRUtils::expr_value(a_dim), dim); - if( ASR::is_a(*a_v) ) { - a_v = ASR::down_cast(a_v)->m_arg; +static inline bool is_dimension_dependent_only_on_arguments(ASR::ttype_t* type) { + ASR::dimension_t* m_dims; + size_t n_dims = ASRUtils::extract_dimensions_from_ttype(type, m_dims); + return is_dimension_dependent_only_on_arguments(m_dims, n_dims); +} + +static inline bool is_binop_expr(ASR::expr_t* x) { + switch( x->type ) { + case ASR::exprType::IntegerBinOp: + case ASR::exprType::RealBinOp: + case ASR::exprType::ComplexBinOp: + case ASR::exprType::LogicalBinOp: + case ASR::exprType::UnsignedIntegerBinOp: + case ASR::exprType::IntegerCompare: + case ASR::exprType::RealCompare: + case ASR::exprType::ComplexCompare: + case ASR::exprType::LogicalCompare: + case ASR::exprType::UnsignedIntegerCompare: + case ASR::exprType::StringCompare: { + return true; + } + default: { + return false; + } } +} - if( ASR::is_a(*a_v) ) { - ASR::ArraySection_t* array_section_t = ASR::down_cast(a_v); - if( a_dim == nullptr ) { - ASR::asr_t* const1 = ASR::make_IntegerConstant_t(al, a_loc, 1, a_type); - ASR::asr_t* size = const1; - for( size_t i = 0; i < array_section_t->n_args; i++ ) { - ASR::expr_t* start = array_section_t->m_args[i].m_left; - ASR::expr_t* end = array_section_t->m_args[i].m_right; - ASR::expr_t* d = array_section_t->m_args[i].m_step; - start = CastingUtil::perform_casting(start, a_type, al, a_loc); - end = CastingUtil::perform_casting(end, a_type, al, a_loc); - d = CastingUtil::perform_casting(d, a_type, al, a_loc); - ASR::expr_t* endminusstart = ASRUtils::EXPR(ASR::make_IntegerBinOp_t( - al, a_loc, end, ASR::binopType::Sub, start, a_type, nullptr)); - ASR::expr_t* byd = ASRUtils::EXPR(ASR::make_IntegerBinOp_t( - al, a_loc, endminusstart, ASR::binopType::Div, d, a_type, nullptr)); - ASR::expr_t* plus1 = ASRUtils::EXPR(ASR::make_IntegerBinOp_t( - al, a_loc, byd, ASR::binopType::Add, ASRUtils::EXPR(const1), a_type, nullptr)); - size = ASR::make_IntegerBinOp_t(al, a_loc, ASRUtils::EXPR(size), - ASR::binopType::Mul, plus1, a_type, nullptr); - } - return size; - } else if( is_dimension_constant ) { - ASR::asr_t* const1 = ASR::make_IntegerConstant_t(al, a_loc, 1, a_type); - ASR::expr_t* start = array_section_t->m_args[dim - 1].m_left; - ASR::expr_t* end = array_section_t->m_args[dim - 1].m_right; - ASR::expr_t* d = array_section_t->m_args[dim - 1].m_step; - start = CastingUtil::perform_casting(start, a_type, al, a_loc); - end = CastingUtil::perform_casting(end, a_type, al, a_loc); - d = CastingUtil::perform_casting(d, a_type, al, a_loc); - ASR::expr_t* endminusstart = ASRUtils::EXPR(ASR::make_IntegerBinOp_t( - al, a_loc, end, ASR::binopType::Sub, start, a_type, nullptr)); - ASR::expr_t* byd = ASRUtils::EXPR(ASR::make_IntegerBinOp_t( - al, a_loc, endminusstart, ASR::binopType::Div, d, a_type, nullptr)); - return ASR::make_IntegerBinOp_t(al, a_loc, byd, ASR::binopType::Add, - ASRUtils::EXPR(const1), a_type, nullptr); +static inline bool is_unaryop_expr(ASR::expr_t* x) { + switch( x->type ) { + case ASR::exprType::IntegerUnaryMinus: + case ASR::exprType::RealUnaryMinus: + case ASR::exprType::ComplexUnaryMinus: + case ASR::exprType::LogicalNot: { + return true; } - } else { - ASR::dimension_t* m_dims = nullptr; - size_t n_dims = ASRUtils::extract_dimensions_from_ttype(ASRUtils::expr_type(a_v), m_dims); - bool is_dimension_dependent_only_on_arguments_ = is_dimension_dependent_only_on_arguments(m_dims, n_dims); - - bool compute_size = (is_dimension_dependent_only_on_arguments_ && - (is_dimension_constant || a_dim == nullptr)); - if( compute_size && for_type ) { - ASR::dimension_t* m_dims = nullptr; - size_t n_dims = ASRUtils::extract_dimensions_from_ttype(ASRUtils::expr_type(a_v), m_dims); - if( a_dim == nullptr ) { - ASR::asr_t* size = ASR::make_IntegerConstant_t(al, a_loc, 1, a_type); - for( size_t i = 0; i < n_dims; i++ ) { - size = ASR::make_IntegerBinOp_t(al, a_loc, ASRUtils::EXPR(size), - ASR::binopType::Mul, m_dims[i].m_length, a_type, nullptr); - } - return size; - } else if( is_dimension_constant ) { - return (ASR::asr_t*) m_dims[dim - 1].m_length; - } + default: { + return false; + } + } +} + +static inline ASR::expr_t* extract_member_from_unaryop(ASR::expr_t* x) { + #define UNARYOP_MEMBER_CASE(X, X_t) \ + case (ASR::exprType::X) : { \ + return ASR::down_cast(x)->m_arg; \ + } + + switch (x->type) { + UNARYOP_MEMBER_CASE(IntegerUnaryMinus, IntegerUnaryMinus_t) + UNARYOP_MEMBER_CASE(RealUnaryMinus, RealUnaryMinus_t) + UNARYOP_MEMBER_CASE(ComplexUnaryMinus, ComplexUnaryMinus_t) + UNARYOP_MEMBER_CASE(LogicalNot, LogicalNot_t) + default: { + LCOMPILERS_ASSERT(false) + } + } + + return nullptr; +} + +static inline ASR::expr_t* extract_member_from_binop(ASR::expr_t* x, int8_t member) { + #define BINOP_MEMBER_CASE(X, X_t) \ + case (ASR::exprType::X) : { \ + if( member == 0 ) { \ + return ASR::down_cast(x)->m_left; \ + } else { \ + return ASR::down_cast(x)->m_right; \ + } \ + } + + switch (x->type) { + BINOP_MEMBER_CASE(IntegerBinOp, IntegerBinOp_t) + BINOP_MEMBER_CASE(RealBinOp, RealBinOp_t) + BINOP_MEMBER_CASE(ComplexBinOp, ComplexBinOp_t) + BINOP_MEMBER_CASE(LogicalBinOp, LogicalBinOp_t) + BINOP_MEMBER_CASE(UnsignedIntegerBinOp, UnsignedIntegerBinOp_t) + BINOP_MEMBER_CASE(IntegerCompare, IntegerCompare_t) + BINOP_MEMBER_CASE(RealCompare, RealCompare_t) + BINOP_MEMBER_CASE(ComplexCompare, ComplexCompare_t) + BINOP_MEMBER_CASE(LogicalCompare, LogicalCompare_t) + BINOP_MEMBER_CASE(UnsignedIntegerCompare, UnsignedIntegerCompare_t) + BINOP_MEMBER_CASE(StringCompare, StringCompare_t) + default: { + LCOMPILERS_ASSERT(false) } } - return ASR::make_ArraySize_t(al, a_loc, a_v, a_dim, a_type, a_value); + return nullptr; +} + +size_t get_constant_ArrayConstant_size(ASR::ArrayConstant_t* x); + +ASR::expr_t* get_ArrayConstant_size(Allocator& al, ASR::ArrayConstant_t* x); + +ASR::expr_t* get_ImpliedDoLoop_size(Allocator& al, ASR::ImpliedDoLoop_t* implied_doloop); + +ASR::expr_t* get_ArrayConstructor_size(Allocator& al, ASR::ArrayConstructor_t* x); + +ASR::asr_t* make_ArraySize_t_util( + Allocator &al, const Location &a_loc, ASR::expr_t* a_v, + ASR::expr_t* a_dim, ASR::ttype_t* a_type, ASR::expr_t* a_value, + bool for_type=true); + +inline ASR::asr_t* make_Variable_t_util(Allocator &al, const Location &a_loc, + SymbolTable* a_parent_symtab, char* a_name, char** a_dependencies, size_t n_dependencies, + ASR::intentType a_intent, ASR::expr_t* a_symbolic_value, ASR::expr_t* a_value, ASR::storage_typeType a_storage, + ASR::ttype_t* a_type, ASR::symbol_t* a_type_declaration, ASR::abiType a_abi, ASR::accessType a_access, ASR::presenceType a_presence, + bool a_value_attr, bool a_target_attr = false) { + return ASR::make_Variable_t(al, a_loc, a_parent_symtab, a_name, a_dependencies, n_dependencies, a_intent, + a_symbolic_value, a_value, a_storage, a_type, a_type_declaration, a_abi, a_access, a_presence, a_value_attr, a_target_attr); } inline ASR::ttype_t* make_Array_t_util(Allocator& al, const Location& loc, ASR::ttype_t* type, ASR::dimension_t* m_dims, size_t n_dims, ASR::abiType abi=ASR::abiType::Source, bool is_argument=false, ASR::array_physical_typeType physical_type=ASR::array_physical_typeType::DescriptorArray, - bool override_physical_type=false, bool is_dimension_star=false) { + bool override_physical_type=false, bool is_dimension_star=false, bool for_type=true) { if( n_dims == 0 ) { return type; } @@ -2368,7 +2600,7 @@ inline ASR::ttype_t* make_Array_t_util(Allocator& al, const Location& loc, if( m_dims[i].m_length && ASR::is_a(*m_dims[i].m_length) ) { ASR::ArraySize_t* as = ASR::down_cast(m_dims[i].m_length); m_dims[i].m_length = ASRUtils::EXPR(ASRUtils::make_ArraySize_t_util( - al, as->base.base.loc, as->m_v, as->m_dim, as->m_type, nullptr)); + al, as->base.base.loc, as->m_v, as->m_dim, as->m_type, nullptr, for_type)); } } @@ -2418,11 +2650,11 @@ inline bool ttype_set_dimensions(ASR::ttype_t** x, case ASR::ttypeType::UnsignedInteger: case ASR::ttypeType::Real: case ASR::ttypeType::Complex: - case ASR::ttypeType::Character: + case ASR::ttypeType::String: case ASR::ttypeType::Logical: case ASR::ttypeType::StructType: - case ASR::ttypeType::Enum: - case ASR::ttypeType::Union: + case ASR::ttypeType::EnumType: + case ASR::ttypeType::UnionType: case ASR::ttypeType::TypeParameter: { *x = ASRUtils::make_Array_t_util(al, (*x)->base.loc, *x, m_dims, n_dims, abi, is_argument, ASR::array_physical_typeType::DescriptorArray, false, is_dimension_star); @@ -2434,18 +2666,17 @@ inline bool ttype_set_dimensions(ASR::ttype_t** x, return false; } -inline bool is_array(ASR::ttype_t *x) { - ASR::dimension_t* dims = nullptr; - return extract_dimensions_from_ttype(x, dims) > 0; -} - static inline bool is_aggregate_type(ASR::ttype_t* asr_type) { return ASRUtils::is_array(asr_type) || !(ASR::is_a(*asr_type) || ASR::is_a(*asr_type) || ASR::is_a(*asr_type) || ASR::is_a(*asr_type) || - ASR::is_a(*asr_type)); + ASR::is_a(*asr_type) || + ASR::is_a( + *ASRUtils::type_get_past_pointer( + ASRUtils::type_get_past_allocatable(asr_type))) || + ASR::is_a(*asr_type)); } static inline ASR::dimension_t* duplicate_dimensions(Allocator& al, ASR::dimension_t* m_dims, size_t n_dims); @@ -2475,8 +2706,7 @@ static inline ASR::asr_t* make_StructType_t_util(Allocator& al, Location loc, AS } } bool is_cstruct = member_functions.n == 0; - return ASR::make_StructType_t(al, - loc, + return ASR::make_StructType_t(al, loc, members.p, members.n, member_functions.p, @@ -2534,26 +2764,23 @@ static inline ASR::ttype_t* duplicate_type(Allocator& al, const ASR::ttype_t* t, t_ = ASRUtils::TYPE(ASR::make_Logical_t(al, t->base.loc, tnew->m_kind)); break; } - case ASR::ttypeType::Character: { - ASR::Character_t* tnew = ASR::down_cast(t); - t_ = ASRUtils::TYPE(ASR::make_Character_t(al, t->base.loc, - tnew->m_kind, tnew->m_len, tnew->m_len_expr)); + case ASR::ttypeType::String: { + ASR::String_t* tnew = ASR::down_cast(t); + t_ = ASRUtils::TYPE(ASR::make_String_t(al, t->base.loc, + tnew->m_kind, tnew->m_len, tnew->m_len_expr, tnew->m_physical_type)); break; } case ASR::ttypeType::StructType: { ASR::StructType_t* tnew = ASR::down_cast(t); t_ = ASRUtils::TYPE(ASR::make_StructType_t(al, t->base.loc, - tnew->m_data_member_types, - tnew->n_data_member_types, - tnew->m_member_function_types, - tnew->n_member_function_types, - tnew->m_is_cstruct, - tnew->m_derived_type)); + tnew->m_data_member_types, tnew->n_data_member_types, + tnew->m_member_function_types, tnew->n_member_function_types, + tnew->m_is_cstruct, tnew->m_derived_type)); break; } - case ASR::ttypeType::Class: { - ASR::Class_t* tnew = ASR::down_cast(t); - t_ = ASRUtils::TYPE(ASR::make_Class_t(al, t->base.loc, tnew->m_class_type)); + case ASR::ttypeType::ClassType: { + ASR::ClassType_t* tnew = ASR::down_cast(t); + t_ = ASRUtils::TYPE(ASR::make_ClassType_t(al, t->base.loc, tnew->m_class_type)); break; } case ASR::ttypeType::Pointer: { @@ -2562,7 +2789,7 @@ static inline ASR::ttype_t* duplicate_type(Allocator& al, const ASR::ttype_t* t, physical_type, override_physical_type); if( override_physical_type && (physical_type == ASR::array_physical_typeType::FixedSizeArray || - (physical_type == ASR::array_physical_typeType::CharacterArraySinglePointer && + (physical_type == ASR::array_physical_typeType::StringArraySinglePointer && dims != nullptr) ) ) { return dup_type; } @@ -2621,7 +2848,19 @@ static inline ASR::ttype_t* duplicate_type(Allocator& al, const ASR::ttype_t* t, case ASR::ttypeType::SymbolicExpression: { return ASRUtils::TYPE(ASR::make_SymbolicExpression_t(al, t->base.loc)); } - default : throw LCompilersException("Not implemented " + std::to_string(t->type)); + case ASR::ttypeType::Tuple: { + ASR::Tuple_t* tup = ASR::down_cast(t); + Vec types; + types.reserve(al, tup->n_type); + for( size_t i = 0; i < tup->n_type; i++ ) { + ASR::ttype_t *t = ASRUtils::duplicate_type(al, tup->m_type[i], + nullptr, physical_type, override_physical_type); + types.push_back(al, t); + } + return ASRUtils::TYPE(ASR::make_Tuple_t(al, tup->base.base.loc, + types.p, types.size())); + } + default : throw LCompilersException("Not implemented " + ASRUtils::type_to_str_python(t)); } LCOMPILERS_ASSERT(t_ != nullptr); return ASRUtils::make_Array_t_util( @@ -2650,6 +2889,47 @@ static inline void set_absent_optional_arguments_to_null( LCOMPILERS_ASSERT(args.size() + offset == (func->n_args)); } +// Check if the passed ttype node is character type node of +// physical type `DescriptorString`. +static inline bool is_descriptorString(ASR::ttype_t* t){ + return is_character(*t) && + ASR::down_cast( + extract_type(t))->m_physical_type == ASR::string_physical_typeType::DescriptorString; +} + +// Create `StringPhysicalCast` node from `PointerString` --> `DescriptorString`. +static inline ASR::expr_t* cast_string_pointer_to_descriptor(Allocator& al, ASR::expr_t* string){ + LCOMPILERS_ASSERT(is_character(*ASRUtils::expr_type(string)) && + !is_descriptorString(expr_type(string))); + ASR::ttype_t* string_type = ASRUtils::expr_type(string); + ASR::ttype_t* stringDescriptor_type = ASRUtils::duplicate_type(al, + ASRUtils::extract_type(string_type)); + ASR::down_cast(stringDescriptor_type)->m_physical_type = ASR::string_physical_typeType::DescriptorString; + ASR::ttype_t* alloctable_stringDescriptor_type = ASRUtils::TYPE( + ASR::make_Allocatable_t(al, string->base.loc, stringDescriptor_type)); + // Create pointerString to descriptorString cast node + ASR::expr_t* ptr_to_desc_string_cast = ASRUtils::EXPR( + ASR::make_StringPhysicalCast_t(al, string->base.loc , string, + ASR::string_physical_typeType::PointerString, ASR::string_physical_typeType::DescriptorString, + alloctable_stringDescriptor_type, nullptr)); + return ptr_to_desc_string_cast; +} + +// Create `StringPhysicalCast` node from `DescriptorString` --> `PointerString`. +static inline ASR::expr_t* cast_string_descriptor_to_pointer(Allocator& al, ASR::expr_t* string){ + LCOMPILERS_ASSERT(is_character(*ASRUtils::expr_type(string)) && + is_descriptorString(expr_type(string))); + // Create string node with `PointerString` physical type + ASR::ttype_t* stringPointer_type = ASRUtils::duplicate_type(al, ASRUtils::expr_type(string)); + ASR::down_cast(ASRUtils::type_get_past_allocatable(stringPointer_type))->m_physical_type = ASR::string_physical_typeType::PointerString; + // Create descriptorString to pointerString cast node + ASR::expr_t* des_to_ptr_string_cast = ASRUtils::EXPR( + ASR::make_StringPhysicalCast_t(al, string->base.loc , string, + ASR::string_physical_typeType::DescriptorString, ASR::string_physical_typeType::PointerString, + stringPointer_type, nullptr)); + return des_to_ptr_string_cast; +} + static inline ASR::ttype_t* duplicate_type_with_empty_dims(Allocator& al, ASR::ttype_t* t, ASR::array_physical_typeType physical_type=ASR::array_physical_typeType::DescriptorArray, bool override_physical_type=false) { @@ -2691,20 +2971,17 @@ static inline ASR::ttype_t* duplicate_type_without_dims(Allocator& al, const ASR ASR::Logical_t* tnew = ASR::down_cast(t); return ASRUtils::TYPE(ASR::make_Logical_t(al, loc, tnew->m_kind)); } - case ASR::ttypeType::Character: { - ASR::Character_t* tnew = ASR::down_cast(t); - return ASRUtils::TYPE(ASR::make_Character_t(al, loc, - tnew->m_kind, tnew->m_len, tnew->m_len_expr)); + case ASR::ttypeType::String: { + ASR::String_t* tnew = ASR::down_cast(t); + return ASRUtils::TYPE(ASR::make_String_t(al, loc, + tnew->m_kind, tnew->m_len, tnew->m_len_expr, ASR::string_physical_typeType::PointerString)); } case ASR::ttypeType::StructType: { ASR::StructType_t* tstruct = ASR::down_cast(t); - return ASRUtils::TYPE(ASR::make_StructType_t(al, t->base.loc, - tstruct->m_data_member_types, - tstruct->n_data_member_types, - tstruct->m_member_function_types, - tstruct->n_member_function_types, - tstruct->m_is_cstruct, - tstruct->m_derived_type)); + return ASRUtils::TYPE(ASR::make_StructType_t(al, loc, + tstruct->m_data_member_types, tstruct->n_data_member_types, + tstruct->m_member_function_types, tstruct->n_member_function_types, + tstruct->m_is_cstruct, tstruct->m_derived_type)); } case ASR::ttypeType::Pointer: { ASR::Pointer_t* ptr = ASR::down_cast(t); @@ -2722,10 +2999,15 @@ static inline ASR::ttype_t* duplicate_type_without_dims(Allocator& al, const ASR ASR::TypeParameter_t* tp = ASR::down_cast(t); return ASRUtils::TYPE(ASR::make_TypeParameter_t(al, loc, tp->m_param)); } - default : throw LCompilersException("Not implemented " + std::to_string(t->type)); + default : throw LCompilersException("Not implemented " + ASRUtils::type_to_str_python(t)); } } +static inline ASR::asr_t* make_Allocatable_t_util(Allocator& al, const Location& loc, ASR::ttype_t* type) { + return ASR::make_Allocatable_t( + al, loc, duplicate_type_with_empty_dims(al, type)); +} + inline std::string remove_trailing_white_spaces(std::string str) { int end = str.size() - 1; while (end >= 0 && str[end] == ' ') { @@ -2746,8 +3028,8 @@ inline bool is_same_type_pointer(ASR::ttype_t* source, ASR::ttype_t* dest) { dest = temp; } dest = ASRUtils::type_get_past_array(ASR::down_cast(dest)->m_type); - if( (ASR::is_a(*source) || ASR::is_a(*source)) && - (ASR::is_a(*dest) || ASR::is_a(*dest)) ) { + if( (ASR::is_a(*source) || ASR::is_a(*source)) && + (ASR::is_a(*dest) || ASR::is_a(*dest)) ) { return true; } bool res = source->type == dest->type; @@ -2780,20 +3062,18 @@ inline int extract_kind_str(char* m_n, char *&kind_str) { // this function only extract's the 'kind' and raises an error when it's of // inappropriate type (e.g. float), but doesn't ensure 'kind' is appropriate // for whose kind it is -template -inline int extract_kind(ASR::expr_t* kind_expr, const Location& loc) { +template +inline int extract_kind(ASR::expr_t* kind_expr, const Location& loc, diag::Diagnostics &diag) { switch( kind_expr->type ) { case ASR::exprType::Var: { - ASR::Var_t* kind_var = - ASR::down_cast(kind_expr); - ASR::Variable_t* kind_variable = - ASR::down_cast( + ASR::Var_t* kind_var = ASR::down_cast(kind_expr); + ASR::Variable_t* kind_variable = ASR::down_cast( symbol_get_past_external(kind_var->m_v)); bool is_parent_enum = false; if (kind_variable->m_parent_symtab->asr_owner != nullptr) { ASR::symbol_t *s = ASR::down_cast( kind_variable->m_parent_symtab->asr_owner); - is_parent_enum = ASR::is_a(*s); + is_parent_enum = ASR::is_a(*s); } if( is_parent_enum ) { return ASRUtils::extract_kind_from_ttype_t(kind_variable->m_type); @@ -2802,30 +3082,52 @@ inline int extract_kind(ASR::expr_t* kind_expr, const Location& loc) { LCOMPILERS_ASSERT( kind_variable->m_value != nullptr ); return ASR::down_cast(kind_variable->m_value)->m_n; } else { - std::string msg = "Integer variable required. " + std::string(kind_variable->m_name) + - " is not an Integer variable."; - throw SemanticError(msg, loc); + diag.add(diag::Diagnostic( + "Integer variable required. " + std::string(kind_variable->m_name) + + " is not an Integer variable.", + diag::Level::Error, diag::Stage::Semantic, { + diag::Label("", {loc})})); + throw SemanticAbort(); } } else { - std::string msg = "Parameter '" + std::string(kind_variable->m_name) + - "' is a variable, which does not reduce to a constant expression"; - throw SemanticError(msg, loc); + diag.add(diag::Diagnostic( + "Parameter '" + std::string(kind_variable->m_name) + + "' is a variable, which does not reduce to a constant expression", + diag::Level::Error, diag::Stage::Semantic, { + diag::Label("", {loc})})); + throw SemanticAbort(); } } case ASR::exprType::IntrinsicElementalFunction: { ASR::IntrinsicElementalFunction_t* kind_isf = ASR::down_cast(kind_expr); - if (kind_isf->m_intrinsic_id == 1 && kind_isf->m_value) { - // m_intrinsic_id: 1 -> kind intrinsic - LCOMPILERS_ASSERT( ASR::is_a(*kind_isf->m_value) ); - ASR::IntegerConstant_t* kind_ic = - ASR::down_cast(kind_isf->m_value); - return kind_ic->m_n; + if ( kind_isf->m_value && + ASR::is_a(*kind_isf->m_value) ) { + return ASR::down_cast(kind_isf->m_value)->m_n; } else { - throw SemanticError("Only Integer literals or expressions which " - "reduce to constant Integer are accepted as kind parameters.", - loc); + diag.add(diag::Diagnostic( + "Only Integer literals or expressions which " + "reduce to constant Integer are accepted as kind parameters", + diag::Level::Error, diag::Stage::Semantic, { + diag::Label("", {loc})})); + throw SemanticAbort(); } + break; + } + case ASR::exprType::TypeInquiry: { + ASR::TypeInquiry_t* kind_ti = + ASR::down_cast(kind_expr); + if (kind_ti->m_value) { + return ASR::down_cast(kind_ti->m_value)->m_n; + } else { + diag.add(diag::Diagnostic( + "Only Integer literals or expressions which " + "reduce to constant Integer are accepted as kind parameters", + diag::Level::Error, diag::Stage::Semantic, { + diag::Label("", {loc})})); + throw SemanticAbort(); + } + break; } // allow integer binary operator kinds (e.g. '1 + 7') case ASR::exprType::IntegerBinOp: @@ -2838,26 +3140,30 @@ inline int extract_kind(ASR::expr_t* kind_expr, const Location& loc) { // as 'a' isn't a constant. // ToDo: we should raise a better error, by "locating" just // 'a' as well, instead of the whole '1*a' - throw SemanticError("Only Integer literals or expressions which " - "reduce to constant Integer are accepted as kind parameters.", - loc); + diag.add(diag::Diagnostic( + "Only Integer literals or expressions which " + "reduce to constant Integer are accepted as kind parameters", + diag::Level::Error, diag::Stage::Semantic, { + diag::Label("", {loc})})); + throw SemanticAbort(); } return a_kind; } // make sure not to allow kind having "RealConstant" (e.g. 4.0), // and everything else default: { - throw SemanticError( + diag.add(diag::Diagnostic( "Only Integer literals or expressions which " - "reduce to constant Integer are accepted as kind parameters.", - loc - ); + "reduce to constant Integer are accepted as kind parameters", + diag::Level::Error, diag::Stage::Semantic, { + diag::Label("", {loc})})); + throw SemanticAbort(); } } } -template -inline int extract_len(ASR::expr_t* len_expr, const Location& loc) { +template +inline int extract_len(ASR::expr_t* len_expr, const Location& loc, diag::Diagnostics &diag) { int a_len = -10; switch( len_expr->type ) { case ASR::exprType::IntegerConstant: { @@ -2876,9 +3182,12 @@ inline int extract_len(ASR::expr_t* len_expr, const Location& loc) { LCOMPILERS_ASSERT( len_variable->m_value != nullptr ); a_len = ASR::down_cast(len_variable->m_value)->m_n; } else { - std::string msg = "Integer variable required. " + std::string(len_variable->m_name) + - " is not an Integer variable."; - throw SemanticError(msg, loc); + diag.add(diag::Diagnostic( + "Integer variable required. " + std::string(len_variable->m_name) + + " is not an Integer variable", + diag::Level::Error, diag::Stage::Semantic, { + diag::Label("", {loc})})); + throw SemanticAbort(); } } else { // An expression is being used for `len` that cannot be evaluated @@ -2901,8 +3210,11 @@ inline int extract_len(ASR::expr_t* len_expr, const Location& loc) { break; } default: { - throw SemanticError("Only Integers or variables implemented so far for `len` expressions, found: " + std::to_string(len_expr->type), - loc); + diag.add(diag::Diagnostic( + "Only Integers or variables implemented so far for `len` expressions, found: " + ASRUtils::type_to_str_python(ASRUtils::expr_type(len_expr)), + diag::Level::Error, diag::Stage::Semantic, { + diag::Label("", {loc})})); + throw SemanticAbort(); } } LCOMPILERS_ASSERT(a_len != -10) @@ -2978,7 +3290,7 @@ inline bool expr_equal(ASR::expr_t* x, ASR::expr_t* y) { case ASR::exprType::Var: { ASR::Var_t* var_x = ASR::down_cast(x); ASR::Var_t* var_y = ASR::down_cast(y); - return var_x->m_v == var_y->m_v; + return check_equal_type(expr_type(&var_x->base), expr_type(&var_y->base), true); } case ASR::exprType::IntegerConstant: { ASR::IntegerConstant_t* intconst_x = ASR::down_cast(x); @@ -3010,7 +3322,6 @@ inline bool dimension_expr_equal( if (!(dim_a && dim_b)) { return true; } - int dim_a_int {-1}; int dim_b_int {-1}; @@ -3026,23 +3337,17 @@ inline bool dimension_expr_equal( return true; } -inline bool dimensions_equal(ASR::dimension_t* dims_a, size_t n_dims_a, - ASR::dimension_t* dims_b, size_t n_dims_b -) { - // unequal ranks means dimensions aren't equal - if (n_dims_a != n_dims_b) { - return false; - } +inline bool dimensions_compatible(ASR::dimension_t* dims_a, size_t n_dims_a, + ASR::dimension_t* dims_b, size_t n_dims_b, + bool check_n_dims= true){ - for( size_t i = 0; i < n_dims_a; i++ ) { - ASR::dimension_t dim_a = dims_a[i]; - ASR::dimension_t dim_b = dims_b[i]; - if( !dimension_expr_equal(dim_a.m_length, dim_b.m_length) || - !dimension_expr_equal(dim_a.m_start, dim_b.m_start) ) { - return false; - } + if (check_n_dims && (n_dims_a != n_dims_b)) { + return false; } - return true; + int total_a = get_fixed_size_of_array(dims_a,n_dims_a); + int total_b = get_fixed_size_of_array(dims_b,n_dims_b); + // -1 means found dimension with no value at compile time, then return true anyway. + return (total_a == -1) || (total_b == -1) || (total_a >= total_b); } inline bool types_equal(ASR::ttype_t *a, ASR::ttype_t *b, @@ -3065,6 +3370,20 @@ inline bool types_equal(ASR::ttype_t *a, ASR::ttype_t *b, a = ASRUtils::type_get_past_array(a); b = ASRUtils::type_get_past_array(b); } + // If either argument is a polymorphic type, return true. + if (ASR::is_a(*a)) { + if (ASRUtils::symbol_name( + ASRUtils::symbol_get_past_external( + ASR::down_cast(a)->m_class_type)) == std::string("~abstract_type")) { + return true; + } + } else if (ASR::is_a(*b)) { + if (ASRUtils::symbol_name( + ASRUtils::symbol_get_past_external( + ASR::down_cast(b)->m_class_type)) == std::string("~abstract_type")) { + return true; + } + } if (a->type == b->type) { // TODO: check dims // TODO: check all types @@ -3076,7 +3395,7 @@ inline bool types_equal(ASR::ttype_t *a, ASR::ttype_t *b, return false; } - return ASRUtils::dimensions_equal( + return ASRUtils::dimensions_compatible( a2->m_dims, a2->n_dims, b2->m_dims, b2->n_dims); } @@ -3118,9 +3437,9 @@ inline bool types_equal(ASR::ttype_t *a, ASR::ttype_t *b, ASR::Logical_t *b2 = ASR::down_cast(b); return (a2->m_kind == b2->m_kind); } - case (ASR::ttypeType::Character) : { - ASR::Character_t *a2 = ASR::down_cast(a); - ASR::Character_t *b2 = ASR::down_cast(b); + case (ASR::ttypeType::String) : { + ASR::String_t *a2 = ASR::down_cast(a); + ASR::String_t *b2 = ASR::down_cast(b); return (a2->m_kind == b2->m_kind); } case (ASR::ttypeType::List) : { @@ -3139,17 +3458,17 @@ inline bool types_equal(ASR::ttype_t *a, ASR::ttype_t *b, b2->m_derived_type)); return a2_type == b2_type; } - case (ASR::ttypeType::Class) : { - ASR::Class_t *a2 = ASR::down_cast(a); - ASR::Class_t *b2 = ASR::down_cast(b); + case (ASR::ttypeType::ClassType) : { + ASR::ClassType_t *a2 = ASR::down_cast(a); + ASR::ClassType_t *b2 = ASR::down_cast(b); ASR::symbol_t* a2_typesym = ASRUtils::symbol_get_past_external(a2->m_class_type); ASR::symbol_t* b2_typesym = ASRUtils::symbol_get_past_external(b2->m_class_type); if( a2_typesym->type != b2_typesym->type ) { return false; } - if( a2_typesym->type == ASR::symbolType::ClassType ) { - ASR::ClassType_t *a2_type = ASR::down_cast(a2_typesym); - ASR::ClassType_t *b2_type = ASR::down_cast(b2_typesym); + if( a2_typesym->type == ASR::symbolType::Class ) { + ASR::Class_t *a2_type = ASR::down_cast(a2_typesym); + ASR::Class_t *b2_type = ASR::down_cast(b2_typesym); return a2_type == b2_type; } else if( a2_typesym->type == ASR::symbolType::Struct ) { ASR::Struct_t *a2_type = ASR::down_cast(a2_typesym); @@ -3158,13 +3477,13 @@ inline bool types_equal(ASR::ttype_t *a, ASR::ttype_t *b, } return false; } - case (ASR::ttypeType::Union) : { - ASR::Union_t *a2 = ASR::down_cast(a); - ASR::Union_t *b2 = ASR::down_cast(b); - ASR::UnionType_t *a2_type = ASR::down_cast( + case (ASR::ttypeType::UnionType) : { + ASR::UnionType_t *a2 = ASR::down_cast(a); + ASR::UnionType_t *b2 = ASR::down_cast(b); + ASR::Union_t *a2_type = ASR::down_cast( ASRUtils::symbol_get_past_external( a2->m_union_type)); - ASR::UnionType_t *b2_type = ASR::down_cast( + ASR::Union_t *b2_type = ASR::down_cast( ASRUtils::symbol_get_past_external( b2->m_union_type)); return a2_type == b2_type; @@ -3189,36 +3508,34 @@ inline bool types_equal(ASR::ttype_t *a, ASR::ttype_t *b, } default : return false; } - } else if( a->type == ASR::ttypeType::StructType && - b->type == ASR::ttypeType::Class ) { + } else if (a->type == ASR::ttypeType::StructType && b->type == ASR::ttypeType::ClassType) { ASR::StructType_t *a2 = ASR::down_cast(a); - ASR::Class_t *b2 = ASR::down_cast(b); + ASR::ClassType_t *b2 = ASR::down_cast(b); ASR::symbol_t* a2_typesym = ASRUtils::symbol_get_past_external(a2->m_derived_type); ASR::symbol_t* b2_typesym = ASRUtils::symbol_get_past_external(b2->m_class_type); if( a2_typesym->type != b2_typesym->type ) { return false; } - if( a2_typesym->type == ASR::symbolType::ClassType ) { - ASR::ClassType_t *a2_type = ASR::down_cast(a2_typesym); - ASR::ClassType_t *b2_type = ASR::down_cast(b2_typesym); + if( a2_typesym->type == ASR::symbolType::Class ) { + ASR::Class_t *a2_type = ASR::down_cast(a2_typesym); + ASR::Class_t *b2_type = ASR::down_cast(b2_typesym); return a2_type == b2_type; } else if( a2_typesym->type == ASR::symbolType::Struct ) { ASR::Struct_t *a2_type = ASR::down_cast(a2_typesym); ASR::Struct_t *b2_type = ASR::down_cast(b2_typesym); return is_derived_type_similar(a2_type, b2_type); } - } else if( a->type == ASR::ttypeType::Class && - b->type == ASR::ttypeType::StructType ) { - ASR::Class_t *a2 = ASR::down_cast(a); + } else if (a->type == ASR::ttypeType::ClassType && b->type == ASR::ttypeType::StructType) { + ASR::ClassType_t *a2 = ASR::down_cast(a); ASR::StructType_t *b2 = ASR::down_cast(b); ASR::symbol_t* a2_typesym = ASRUtils::symbol_get_past_external(a2->m_class_type); ASR::symbol_t* b2_typesym = ASRUtils::symbol_get_past_external(b2->m_derived_type); if( a2_typesym->type != b2_typesym->type ) { return false; } - if( a2_typesym->type == ASR::symbolType::ClassType ) { - ASR::ClassType_t *a2_type = ASR::down_cast(a2_typesym); - ASR::ClassType_t *b2_type = ASR::down_cast(b2_typesym); + if( a2_typesym->type == ASR::symbolType::Class ) { + ASR::Class_t *a2_type = ASR::down_cast(a2_typesym); + ASR::Class_t *b2_type = ASR::down_cast(b2_typesym); return a2_type == b2_type; } else if( a2_typesym->type == ASR::symbolType::Struct ) { ASR::Struct_t *a2_type = ASR::down_cast(a2_typesym); @@ -3259,7 +3576,7 @@ inline bool types_equal_with_substitution(ASR::ttype_t *a, ASR::ttype_t *b, return false; } - return ASRUtils::dimensions_equal( + return ASRUtils::dimensions_compatible( a2->m_dims, a2->n_dims, b2->m_dims, b2->n_dims); } @@ -3301,9 +3618,9 @@ inline bool types_equal_with_substitution(ASR::ttype_t *a, ASR::ttype_t *b, ASR::Logical_t *b2 = ASR::down_cast(b); return (a2->m_kind == b2->m_kind); } - case (ASR::ttypeType::Character) : { - ASR::Character_t *a2 = ASR::down_cast(a); - ASR::Character_t *b2 = ASR::down_cast(b); + case (ASR::ttypeType::String) : { + ASR::String_t *a2 = ASR::down_cast(a); + ASR::String_t *b2 = ASR::down_cast(b); return (a2->m_kind == b2->m_kind); } case (ASR::ttypeType::List) : { @@ -3322,17 +3639,17 @@ inline bool types_equal_with_substitution(ASR::ttype_t *a, ASR::ttype_t *b, b2->m_derived_type)); return a2_type == b2_type; } - case (ASR::ttypeType::Class) : { - ASR::Class_t *a2 = ASR::down_cast(a); - ASR::Class_t *b2 = ASR::down_cast(b); + case (ASR::ttypeType::ClassType) : { + ASR::ClassType_t *a2 = ASR::down_cast(a); + ASR::ClassType_t *b2 = ASR::down_cast(b); ASR::symbol_t* a2_typesym = ASRUtils::symbol_get_past_external(a2->m_class_type); ASR::symbol_t* b2_typesym = ASRUtils::symbol_get_past_external(b2->m_class_type); if( a2_typesym->type != b2_typesym->type ) { return false; } - if( a2_typesym->type == ASR::symbolType::ClassType ) { - ASR::ClassType_t *a2_type = ASR::down_cast(a2_typesym); - ASR::ClassType_t *b2_type = ASR::down_cast(b2_typesym); + if( a2_typesym->type == ASR::symbolType::Class ) { + ASR::Class_t *a2_type = ASR::down_cast(a2_typesym); + ASR::Class_t *b2_type = ASR::down_cast(b2_typesym); return a2_type == b2_type; } else if( a2_typesym->type == ASR::symbolType::Struct ) { ASR::Struct_t *a2_type = ASR::down_cast(a2_typesym); @@ -3341,13 +3658,13 @@ inline bool types_equal_with_substitution(ASR::ttype_t *a, ASR::ttype_t *b, } return false; } - case (ASR::ttypeType::Union) : { - ASR::Union_t *a2 = ASR::down_cast(a); - ASR::Union_t *b2 = ASR::down_cast(b); - ASR::UnionType_t *a2_type = ASR::down_cast( + case (ASR::ttypeType::UnionType) : { + ASR::UnionType_t *a2 = ASR::down_cast(a); + ASR::UnionType_t *b2 = ASR::down_cast(b); + ASR::Union_t *a2_type = ASR::down_cast( ASRUtils::symbol_get_past_external( a2->m_union_type)); - ASR::UnionType_t *b2_type = ASR::down_cast( + ASR::Union_t *b2_type = ASR::down_cast( ASRUtils::symbol_get_past_external( b2->m_union_type)); return a2_type == b2_type; @@ -3373,35 +3690,35 @@ inline bool types_equal_with_substitution(ASR::ttype_t *a, ASR::ttype_t *b, default : return false; } } else if( a->type == ASR::ttypeType::StructType && - b->type == ASR::ttypeType::Class ) { + b->type == ASR::ttypeType::ClassType ) { ASR::StructType_t *a2 = ASR::down_cast(a); - ASR::Class_t *b2 = ASR::down_cast(b); + ASR::ClassType_t *b2 = ASR::down_cast(b); ASR::symbol_t* a2_typesym = ASRUtils::symbol_get_past_external(a2->m_derived_type); ASR::symbol_t* b2_typesym = ASRUtils::symbol_get_past_external(b2->m_class_type); if( a2_typesym->type != b2_typesym->type ) { return false; } - if( a2_typesym->type == ASR::symbolType::ClassType ) { - ASR::ClassType_t *a2_type = ASR::down_cast(a2_typesym); - ASR::ClassType_t *b2_type = ASR::down_cast(b2_typesym); + if( a2_typesym->type == ASR::symbolType::Class ) { + ASR::Class_t *a2_type = ASR::down_cast(a2_typesym); + ASR::Class_t *b2_type = ASR::down_cast(b2_typesym); return a2_type == b2_type; } else if( a2_typesym->type == ASR::symbolType::Struct ) { ASR::Struct_t *a2_type = ASR::down_cast(a2_typesym); ASR::Struct_t *b2_type = ASR::down_cast(b2_typesym); return is_derived_type_similar(a2_type, b2_type); } - } else if( a->type == ASR::ttypeType::Class && + } else if( a->type == ASR::ttypeType::ClassType && b->type == ASR::ttypeType::StructType ) { - ASR::Class_t *a2 = ASR::down_cast(a); + ASR::ClassType_t *a2 = ASR::down_cast(a); ASR::StructType_t *b2 = ASR::down_cast(b); ASR::symbol_t* a2_typesym = ASRUtils::symbol_get_past_external(a2->m_class_type); ASR::symbol_t* b2_typesym = ASRUtils::symbol_get_past_external(b2->m_derived_type); if( a2_typesym->type != b2_typesym->type ) { return false; } - if( a2_typesym->type == ASR::symbolType::ClassType ) { - ASR::ClassType_t *a2_type = ASR::down_cast(a2_typesym); - ASR::ClassType_t *b2_type = ASR::down_cast(b2_typesym); + if( a2_typesym->type == ASR::symbolType::Class ) { + ASR::Class_t *a2_type = ASR::down_cast(a2_typesym); + ASR::Class_t *b2_type = ASR::down_cast(b2_typesym); return a2_type == b2_type; } else if( a2_typesym->type == ASR::symbolType::Struct ) { ASR::Struct_t *a2_type = ASR::down_cast(a2_typesym); @@ -3412,18 +3729,18 @@ inline bool types_equal_with_substitution(ASR::ttype_t *a, ASR::ttype_t *b, return false; } -inline bool check_equal_type(ASR::ttype_t* x, ASR::ttype_t* y, bool check_for_dimensions=false) { +inline bool check_equal_type(ASR::ttype_t* x, ASR::ttype_t* y, bool check_for_dimensions) { ASR::ttype_t *x_underlying, *y_underlying; x_underlying = nullptr; y_underlying = nullptr; - if( ASR::is_a(*x) ) { - ASR::Enum_t *x_enum = ASR::down_cast(x); - ASR::EnumType_t *x_enum_type = ASR::down_cast(x_enum->m_enum_type); + if( ASR::is_a(*x) ) { + ASR::EnumType_t *x_enum = ASR::down_cast(x); + ASR::Enum_t *x_enum_type = ASR::down_cast(x_enum->m_enum_type); x_underlying = x_enum_type->m_type; } - if( ASR::is_a(*y) ) { - ASR::Enum_t *y_enum = ASR::down_cast(y); - ASR::EnumType_t *y_enum_type = ASR::down_cast(y_enum->m_enum_type); + if( ASR::is_a(*y) ) { + ASR::EnumType_t *y_enum = ASR::down_cast(y); + ASR::Enum_t *y_enum_type = ASR::down_cast(y_enum->m_enum_type); y_underlying = y_enum_type->m_type; } if( x_underlying || y_underlying ) { @@ -3540,6 +3857,18 @@ ASR::asr_t* symbol_resolve_external_generic_procedure_without_eval( SymbolTable* current_scope, Allocator& al, const std::function err); +static inline ASR::storage_typeType symbol_StorageType(const ASR::symbol_t* s){ + switch( s->type ) { + case ASR::symbolType::Variable: { + return ASR::down_cast(s)->m_storage; + } + default: { + throw LCompilersException("Cannot return storage type of, " + + std::to_string(s->type) + " symbol."); + } + } +} + static inline ASR::intentType symbol_intent(const ASR::symbol_t *f) { switch( f->type ) { @@ -3561,7 +3890,7 @@ static inline ASR::intentType expr_intent(ASR::expr_t* expr) { } default: { throw LCompilersException("Cannot extract intent of ASR::exprType::" + - std::to_string(expr->type)); + ASRUtils::type_to_str_python(ASRUtils::expr_type(expr))); } } return ASR::intentType::Unspecified; @@ -3669,11 +3998,15 @@ static inline ASR::symbol_t* import_struct_instance_member(Allocator& al, ASR::s nullptr, 0, s2c(al, struct_type_name), ASR::accessType::Public)); scope->add_symbol(struct_type_name_, imported_struct_type); } - mem_type = ASRUtils::TYPE(ASRUtils::make_StructType_t_util(al, mem_type->base.loc, - scope->get_symbol(struct_type_name_))); + mem_type = ASRUtils::TYPE(ASR::make_StructType_t(al, mem_type->base.loc, + struct_t->m_data_member_types, struct_t->n_data_member_types, + struct_t->m_member_function_types, struct_t->n_member_function_types, + struct_t->m_is_cstruct, scope->get_symbol(struct_type_name_))); } else { - mem_type = ASRUtils::TYPE(ASRUtils::make_StructType_t_util(al, mem_type->base.loc, - scope->resolve_symbol(struct_type_name))); + mem_type = ASRUtils::TYPE(ASR::make_StructType_t(al, mem_type->base.loc, + struct_t->m_data_member_types, struct_t->n_data_member_types, + struct_t->m_member_function_types, struct_t->n_member_function_types, + struct_t->m_is_cstruct, scope->resolve_symbol(struct_type_name))); } } if( n_dims > 0 ) { @@ -3682,7 +4015,7 @@ static inline ASR::symbol_t* import_struct_instance_member(Allocator& al, ASR::s } if( ASR::is_a(*mem_type_) ) { - mem_type = ASRUtils::TYPE(ASR::make_Allocatable_t(al, + mem_type = ASRUtils::TYPE(ASRUtils::make_Allocatable_t_util(al, mem_type->base.loc, mem_type)); } else if( ASR::is_a(*mem_type_) ) { mem_type = ASRUtils::TYPE(ASR::make_Pointer_t(al, @@ -3890,6 +4223,23 @@ class ExprStmtDuplicator: public ASR::BaseExprStmtDuplicator }; +class ExprStmtWithScopeDuplicator: public ASR::BaseExprStmtDuplicator +{ + public: + SymbolTable* current_scope; + ExprStmtWithScopeDuplicator(Allocator &al, SymbolTable* current_scope): BaseExprStmtDuplicator(al), current_scope(current_scope) {} + + ASR::asr_t* duplicate_Var(ASR::Var_t* x) { + ASR::symbol_t* m_v = current_scope->get_symbol(ASRUtils::symbol_name(x->m_v)); + if (m_v == nullptr) { + // we are dealing with an external/statement function, duplicate node with same symbol + return ASR::make_Var_t(al, x->base.base.loc, x->m_v); + } + return ASR::make_Var_t(al, x->base.base.loc, m_v); + } + +}; + class FixScopedTypeVisitor: public ASR::BaseExprReplacer { private: @@ -4063,7 +4413,8 @@ inline ASR::asr_t* make_Function_t_util(Allocator& al, const Location& loc, ASR::deftypeType m_deftype, char* m_bindc_name, bool m_elemental, bool m_pure, bool m_module, bool m_inline, bool m_static, ASR::symbol_t** m_restrictions, size_t n_restrictions, bool m_is_restriction, - bool m_deterministic, bool m_side_effect_free, char *m_c_header=nullptr) { + bool m_deterministic, bool m_side_effect_free, char *m_c_header=nullptr, Location* m_start_name = nullptr, + Location* m_end_name = nullptr) { ASR::ttype_t* func_type = ASRUtils::TYPE(ASRUtils::make_FunctionType_t_util( al, loc, a_args, n_args, m_return_var, m_abi, m_deftype, m_bindc_name, m_elemental, m_pure, m_module, m_inline, m_static, @@ -4071,9 +4422,10 @@ inline ASR::asr_t* make_Function_t_util(Allocator& al, const Location& loc, return ASR::make_Function_t( al, loc, m_symtab, m_name, func_type, m_dependencies, n_dependencies, a_args, n_args, m_body, n_body, m_return_var, m_access, m_deterministic, - m_side_effect_free, m_c_header); + m_side_effect_free, m_c_header, m_start_name, m_end_name); } + class SymbolDuplicator { private: @@ -4135,6 +4487,12 @@ class SymbolDuplicator { new_symbol_name = struct_type->m_name; break; } + case ASR::symbolType::GenericProcedure: { + ASR::GenericProcedure_t* generic_procedure = ASR::down_cast(symbol); + new_symbol = duplicate_GenericProcedure(generic_procedure, destination_symtab); + new_symbol_name = generic_procedure->m_name; + break; + } default: { throw LCompilersException("Duplicating ASR::symbolType::" + std::to_string(symbol->type) + " is not supported yet."); @@ -4173,7 +4531,7 @@ class SymbolDuplicator { } } return ASR::down_cast( - ASR::make_Variable_t(al, variable->base.base.loc, destination_symtab, + ASRUtils::make_Variable_t_util(al, variable->base.base.loc, destination_symtab, variable->m_name, variable->m_dependencies, variable->n_dependencies, variable->m_intent, m_symbolic_value, m_value, variable->m_storage, m_type, variable->m_type_declaration, variable->m_abi, variable->m_access, @@ -4221,13 +4579,15 @@ class SymbolDuplicator { duplicate_SymbolTable(function->m_symtab, function_symtab); Vec new_body; new_body.reserve(al, function->n_body); - ASRUtils::ExprStmtDuplicator node_duplicator(al); - node_duplicator.allow_procedure_calls = true; - node_duplicator.allow_reshape = false; + + ASRUtils::ExprStmtWithScopeDuplicator scoped_node_duplicator(al, function_symtab); + scoped_node_duplicator.allow_procedure_calls = true; + scoped_node_duplicator.allow_reshape = false; + for( size_t i = 0; i < function->n_body; i++ ) { - node_duplicator.success = true; - ASR::stmt_t* new_stmt = node_duplicator.duplicate_stmt(function->m_body[i]); - if( !node_duplicator.success ) { + scoped_node_duplicator.success = true; + ASR::stmt_t* new_stmt = scoped_node_duplicator.duplicate_stmt(function->m_body[i]); + if (!scoped_node_duplicator.success) { return nullptr; } new_body.push_back(al, new_stmt); @@ -4236,17 +4596,9 @@ class SymbolDuplicator { Vec new_args; new_args.reserve(al, function->n_args); for( size_t i = 0; i < function->n_args; i++ ) { - node_duplicator.success = true; - ASR::expr_t* new_arg = node_duplicator.duplicate_expr(function->m_args[i]); - if (ASR::is_a(*new_arg)) { - ASR::Var_t* var = ASR::down_cast(new_arg); - if (ASR::is_a(*(var->m_v))) { - ASR::Variable_t* variable = ASR::down_cast(var->m_v); - ASR::symbol_t* arg_symbol = function_symtab->get_symbol(variable->m_name); - new_arg = ASRUtils::EXPR(make_Var_t(al, var->base.base.loc, arg_symbol)); - } - } - if( !node_duplicator.success ) { + scoped_node_duplicator.success = true; + ASR::expr_t* new_arg = scoped_node_duplicator.duplicate_expr(function->m_args[i]); + if (!scoped_node_duplicator.success) { return nullptr; } new_args.push_back(al, new_arg); @@ -4254,14 +4606,9 @@ class SymbolDuplicator { ASR::expr_t* new_return_var = function->m_return_var; if( new_return_var ) { - node_duplicator.success = true; - new_return_var = node_duplicator.duplicate_expr(function->m_return_var); - if (ASR::is_a(*new_return_var)) { - ASR::Var_t* var = ASR::down_cast(new_return_var); - std::string var_sym_name = ASRUtils::symbol_name(var->m_v); - new_return_var = ASRUtils::EXPR(make_Var_t(al, var->base.base.loc, function_symtab->get_symbol(var_sym_name))); - } - if( !node_duplicator.success ) { + scoped_node_duplicator.success = true; + new_return_var = scoped_node_duplicator.duplicate_expr(function->m_return_var); + if (!scoped_node_duplicator.success) { return nullptr; } } @@ -4311,13 +4658,18 @@ class SymbolDuplicator { return ASR::down_cast(ASR::make_Struct_t( al, struct_type_t->base.base.loc, struct_type_symtab, struct_type_t->m_name, struct_type_t->m_dependencies, struct_type_t->n_dependencies, - struct_type_t->m_members, struct_type_t->n_members, - struct_type_t->m_member_functions, struct_type_t->n_member_functions, - struct_type_t->m_abi, + struct_type_t->m_members, struct_type_t->n_members, struct_type_t->m_member_functions, + struct_type_t->n_member_functions, struct_type_t->m_abi, struct_type_t->m_access, struct_type_t->m_is_packed, struct_type_t->m_is_abstract, struct_type_t->m_initializers, struct_type_t->n_initializers, struct_type_t->m_alignment, struct_type_t->m_parent)); } + ASR::symbol_t* duplicate_GenericProcedure(ASR::GenericProcedure_t* genericProcedure, SymbolTable* destination_symtab){ + return ASR::down_cast(ASR::make_GenericProcedure_t( + al, genericProcedure->base.base.loc, destination_symtab, + genericProcedure->m_name, genericProcedure->m_procs, + genericProcedure->n_procs, genericProcedure->m_access)); + } }; @@ -4402,8 +4754,14 @@ ASR::asr_t* make_Cast_t_value(Allocator &al, const Location &a_loc, ASR::expr_t* a_arg, ASR::cast_kindType a_kind, ASR::ttype_t* a_type); static inline ASR::expr_t* compute_length_from_start_end(Allocator& al, ASR::expr_t* start, ASR::expr_t* end) { - ASR::expr_t* start_value = ASRUtils::expr_value(start); - ASR::expr_t* end_value = ASRUtils::expr_value(end); + ASR::expr_t* start_value = nullptr; + ASR::expr_t* end_value = nullptr; + if (start != nullptr) { + start_value = ASRUtils::expr_value(start); + } + if (end != nullptr) { + end_value = ASRUtils::expr_value(end); + } // If both start and end have compile time values // then length can be computed easily by extracting @@ -4548,7 +4906,7 @@ static inline bool is_pass_array_by_data_possible(ASR::Function_t* x, std::vecto continue; } typei = ASRUtils::expr_type(x->m_args[i]); - if( ASR::is_a(*typei) || + if( ASR::is_a(*typei) || ASR::is_a(*typei) ) { continue ; } @@ -4567,7 +4925,7 @@ static inline bool is_pass_array_by_data_possible(ASR::Function_t* x, std::vecto argi->m_intent == ASRUtils::intent_inout) && !ASR::is_a(*argi->m_type) && !ASR::is_a(*argi->m_type) && - !ASR::is_a(*argi->m_type) && + !ASR::is_a(*argi->m_type) && argi->m_presence != ASR::presenceType::Optional) { v.push_back(i); } @@ -4575,9 +4933,9 @@ static inline bool is_pass_array_by_data_possible(ASR::Function_t* x, std::vecto return v.size() > 0; } -template +template static inline ASR::expr_t* get_bound(ASR::expr_t* arr_expr, int dim, - std::string bound, Allocator& al) { + std::string bound, Allocator& al, diag::Diagnostics &diag) { ASR::ttype_t* int32_type = ASRUtils::TYPE(ASR::make_Integer_t(al, arr_expr->base.loc, 4)); ASR::expr_t* dim_expr = ASRUtils::EXPR(ASR::make_IntegerConstant_t(al, arr_expr->base.loc, dim, int32_type)); @@ -4602,7 +4960,10 @@ static inline ASR::expr_t* get_bound(ASR::expr_t* arr_expr, int dim, msg = "Variable " + std::string(non_array_variable->m_name) + " does not have enough dimensions."; } - throw SemanticError(msg, arr_expr->base.loc); + diag.add(diag::Diagnostic( + msg, diag::Level::Error, diag::Stage::Semantic, { + diag::Label("", {arr_expr->base.loc})})); + throw SemanticAbort(); } else if ( ASR::is_a(*arr_expr )) { ASR::StructInstanceMember_t* non_array_struct_inst_mem = ASR::down_cast(arr_expr); ASR::Variable_t* non_array_variable = ASR::down_cast( @@ -4615,9 +4976,16 @@ static inline ASR::expr_t* get_bound(ASR::expr_t* arr_expr, int dim, msg = "Type member " + std::string(non_array_variable->m_name) + " does not have enough dimensions."; } - throw SemanticError(msg, arr_expr->base.loc); + diag.add(diag::Diagnostic( + msg, diag::Level::Error, diag::Stage::Semantic, { + diag::Label("", {arr_expr->base.loc})})); + throw SemanticAbort(); } else { - throw SemanticError("Expression cannot be indexed.", arr_expr->base.loc); + diag.add(diag::Diagnostic( + "Expression cannot be indexed", + diag::Level::Error, diag::Stage::Semantic, { + diag::Label("", {arr_expr->base.loc})})); + throw SemanticAbort(); } } dim = dim - 1; @@ -4660,28 +5028,28 @@ static inline ASR::expr_t* get_size(ASR::expr_t* arr_expr, int dim, int32_type, nullptr)); } -static inline ASR::expr_t* get_size(ASR::expr_t* arr_expr, Allocator& al) { +static inline ASR::expr_t* get_size(ASR::expr_t* arr_expr, Allocator& al, bool for_type=true) { ASR::ttype_t* int32_type = ASRUtils::TYPE(ASR::make_Integer_t(al, arr_expr->base.loc, 4)); - return ASRUtils::EXPR(ASRUtils::make_ArraySize_t_util(al, arr_expr->base.loc, arr_expr, nullptr, int32_type, nullptr)); + return ASRUtils::EXPR(ASRUtils::make_ArraySize_t_util(al, arr_expr->base.loc, arr_expr, nullptr, int32_type, nullptr, for_type)); } -static inline ASR::EnumType_t* get_EnumType_from_symbol(ASR::symbol_t* s) { +static inline ASR::Enum_t* get_Enum_from_symbol(ASR::symbol_t* s) { ASR::Variable_t* s_var = ASR::down_cast(s); - if( ASR::is_a(*s_var->m_type) ) { - ASR::Enum_t* enum_ = ASR::down_cast(s_var->m_type); - return ASR::down_cast(enum_->m_enum_type); + if( ASR::is_a(*s_var->m_type) ) { + ASR::EnumType_t* enum_ = ASR::down_cast(s_var->m_type); + return ASR::down_cast(enum_->m_enum_type); } ASR::symbol_t* enum_type_cand = ASR::down_cast(s_var->m_parent_symtab->asr_owner); - LCOMPILERS_ASSERT(ASR::is_a(*enum_type_cand)); - return ASR::down_cast(enum_type_cand); + LCOMPILERS_ASSERT(ASR::is_a(*enum_type_cand)); + return ASR::down_cast(enum_type_cand); } static inline bool is_abstract_class_type(ASR::ttype_t* type) { type = ASRUtils::type_get_past_array(type); - if( !ASR::is_a(*type) ) { + if( !ASR::is_a(*type) ) { return false; } - ASR::Class_t* class_t = ASR::down_cast(type); + ASR::ClassType_t* class_t = ASR::down_cast(type); return std::string( ASRUtils::symbol_name( ASRUtils::symbol_get_past_external(class_t->m_class_type)) ) == "~abstract_type"; @@ -4941,13 +5309,13 @@ static inline void import_struct_t(Allocator& al, if( is_pointer ) { var_type = ASRUtils::TYPE(ASR::make_Pointer_t(al, loc, var_type)); } else if( is_allocatable ) { - var_type = ASRUtils::TYPE(ASR::make_Allocatable_t(al, loc, var_type)); + var_type = ASRUtils::TYPE(ASRUtils::make_Allocatable_t_util(al, loc, var_type)); } } - } else if( ASR::is_a(*var_type_unwrapped) ) { - ASR::Character_t* char_t = ASR::down_cast(var_type_unwrapped); + } else if( ASR::is_a(*var_type_unwrapped) ) { + ASR::String_t* char_t = ASR::down_cast(var_type_unwrapped); if( char_t->m_len == -1 && intent == ASR::intentType::Local ) { - var_type = ASRUtils::TYPE(ASR::make_Character_t(al, loc, char_t->m_kind, 1, nullptr)); + var_type = ASRUtils::TYPE(ASR::make_String_t(al, loc, char_t->m_kind, 1, nullptr, ASR::string_physical_typeType::PointerString)); if( is_array ) { var_type = ASRUtils::make_Array_t_util(al, loc, var_type, m_dims, n_dims, ASR::abiType::Source, false, ptype, true); @@ -4955,7 +5323,7 @@ static inline void import_struct_t(Allocator& al, if( is_pointer ) { var_type = ASRUtils::TYPE(ASR::make_Pointer_t(al, loc, var_type)); } else if( is_allocatable ) { - var_type = ASRUtils::TYPE(ASR::make_Allocatable_t(al, loc, var_type)); + var_type = ASRUtils::TYPE(ASRUtils::make_Allocatable_t_util(al, loc, var_type)); } } } @@ -4987,37 +5355,402 @@ static inline ASR::asr_t* make_ArrayPhysicalCast_t_util(Allocator &al, const Loc return ASR::make_ArrayPhysicalCast_t(al, a_loc, a_arg, a_old, a_new, a_type, a_value); } -inline void flatten_ArrayConstant(Allocator& al, ASR::expr_t** a_args, size_t n_args, Vec &new_args) { - for (size_t i = 0; i < n_args; i++) { - if (ASR::is_a(*a_args[i])) { - ASR::ArrayConstant_t* a_arg = ASR::down_cast(a_args[i]); - flatten_ArrayConstant(al, a_arg->m_args, a_arg->n_args, new_args); - } else if (ASR::is_a(*ASRUtils::expr_value(a_args[i]))) { - ASR::ArrayConstant_t* a_arg = ASR::down_cast(ASRUtils::expr_value(a_args[i])); - flatten_ArrayConstant(al, a_arg->m_args, a_arg->n_args, new_args); - } else { - new_args.push_back(al, ASRUtils::expr_value(a_args[i])); - } - } -} +// inline void flatten_ArrayConstant(Allocator& al, void* data, size_t n_args, Vec &new_args) { +// for (size_t i = 0; i < n_args; i++) { +// if (ASR::is_a(*a_args[i])) { +// ASR::ArrayConstant_t* a_arg = ASR::down_cast(a_args[i]); +// flatten_ArrayConstant(al, a_arg->m_args, a_arg->n_args, new_args); +// } else if (ASR::is_a(*ASRUtils::expr_value(a_args[i]))) { +// ASR::ArrayConstant_t* a_arg = ASR::down_cast(ASRUtils::expr_value(a_args[i])); +// flatten_ArrayConstant(al, a_arg->m_args, a_arg->n_args, new_args); +// } else { +// new_args.push_back(al, ASRUtils::expr_value(a_args[i])); +// } +// } +// } -inline ASR::asr_t* make_ArrayConstructor_t_util(Allocator &al, const Location &a_loc, - ASR::expr_t** a_args, size_t n_args, ASR::ttype_t* a_type, ASR::arraystorageType a_storage_format) { - if( !ASRUtils::is_array(a_type) ) { - Vec dims; - dims.reserve(al, 1); - ASR::dimension_t dim; - dim.loc = a_loc; - dim.m_length = ASRUtils::EXPR(ASR::make_IntegerConstant_t( - al, a_loc, n_args, ASRUtils::TYPE(ASR::make_Integer_t(al, a_loc, 4)))); - dim.m_start = ASRUtils::EXPR(ASR::make_IntegerConstant_t( - al, a_loc, 0, ASRUtils::TYPE(ASR::make_Integer_t(al, a_loc, 4)))); - dims.push_back(al, dim); - a_type = ASRUtils::make_Array_t_util(al, dim.loc, - a_type, dims.p, dims.size(), ASR::abiType::Source, - false, ASR::array_physical_typeType::PointerToDataArray, true); - } else if( ASR::is_a(*a_type) ) { - ASR::dimension_t* m_dims = nullptr; +// Assigns "x->m_data[i] = value", casting the internal data pointer correctly using the type of "value" +inline void set_ArrayConstant_value(ASR::ArrayConstant_t* x, ASR::expr_t* value, int i) { + value = ASRUtils::expr_value(value); + + ASR::ttype_t* type = ASRUtils::type_get_past_array(ASRUtils::type_get_past_allocatable(ASRUtils::expr_type(value))); + int kind = ASRUtils::extract_kind_from_ttype_t(type); + + switch (type->type) { + case ASR::ttypeType::Integer: { + ASR::IntegerConstant_t* value_int = ASR::down_cast(value); + switch (kind) { + case 1: ((int8_t*)x->m_data)[i] = value_int->m_n; break; + case 2: ((int16_t*)x->m_data)[i] = value_int->m_n; break; + case 4: ((int32_t*)x->m_data)[i] = value_int->m_n; break; + case 8: ((int64_t*)x->m_data)[i] = value_int->m_n; break; + default: + throw LCompilersException("Unsupported kind for integer array constant."); + } + } + case ASR::ttypeType::Real: { + ASR::RealConstant_t* value_real = ASR::down_cast(value); + switch (kind) { + case 4: ((float*)x->m_data)[i] = value_real->m_r; break; + case 8: ((double*)x->m_data)[i] = value_real->m_r; break; + default: + throw LCompilersException("Unsupported kind for real array constant."); + } + } + case ASR::ttypeType::UnsignedInteger: { + ASR::IntegerConstant_t* value_int = ASR::down_cast(value); + switch (kind) { + case 1: ((uint8_t*)x->m_data)[i] = value_int->m_n; break; + case 2: ((uint16_t*)x->m_data)[i] = value_int->m_n; break; + case 4: ((uint32_t*)x->m_data)[i] = value_int->m_n; break; + case 8: ((uint64_t*)x->m_data)[i] = value_int->m_n; break; + default: + throw LCompilersException("Unsupported kind for unsigned integer array constant."); + } + } + case ASR::ttypeType::Complex: { + ASR::ComplexConstant_t* value_complex = ASR::down_cast(value); + switch (kind) { + case 4: + ((float*)x->m_data)[i] = value_complex->m_re; + ((float*)x->m_data)[i+1] = value_complex->m_im; break; + case 8: + ((double*)x->m_data)[i] = value_complex->m_re; + ((double*)x->m_data)[i+1] = value_complex->m_im; break; + default: + throw LCompilersException("Unsupported kind for complex array constant."); + } + } + case ASR::ttypeType::Logical: { + ASR::LogicalConstant_t* value_logical = ASR::down_cast(value); + ((bool*)x->m_data)[i] = value_logical->m_value; + break; + } + case ASR::ttypeType::String: { + ASR::String_t* char_type = ASR::down_cast(type); + int len = char_type->m_len; + ASR::StringConstant_t* value_str = ASR::down_cast(value); + char* data = value_str->m_s; + for (int j = 0; j < len; j++) { + *(((char*)x->m_data) + i*len + j) = data[j]; + } + break; + } + default: + throw LCompilersException("Unsupported type for array constant."); + } +} + +template +inline std::string to_string_with_precision(const T a_value, const int n) { + std::ostringstream out; + out.precision(n); + out << std::scientific << a_value; + return std::move(out).str(); +} + +inline std::string fetch_ArrayConstant_value(void *data, ASR::ttype_t* type, int i) { + int kind = ASRUtils::extract_kind_from_ttype_t(type); + + switch (type->type) { + case ASR::ttypeType::Integer: { + switch (kind) { + case 1: return std::to_string(((int8_t*)data)[i]); + case 2: return std::to_string(((int16_t*)data)[i]); + case 4: return std::to_string(((int32_t*)data)[i]); + case 8: return std::to_string(((int64_t*)data)[i]); + default: + throw LCompilersException("Unsupported kind for integer array constant."); + } + } + case ASR::ttypeType::Real: { + switch (kind) { + case 4: return to_string_with_precision(((float*)data)[i], 8); + case 8: return to_string_with_precision(((double*)data)[i], 16); + default: + throw LCompilersException("Unsupported kind for real array constant."); + } + } + case ASR::ttypeType::UnsignedInteger: { + switch (kind) { + case 1: return std::to_string(((uint8_t*)data)[i]); + case 2: return std::to_string(((uint16_t*)data)[i]); + case 4: return std::to_string(((uint32_t*)data)[i]); + case 8: return std::to_string(((uint64_t*)data)[i]); + default: + throw LCompilersException("Unsupported kind for unsigned integer array constant."); + } + } + case ASR::ttypeType::Complex: { + switch (kind) { + case 4: return "("+(to_string_with_precision(*(((float*)data) + 2*i), 8))+", "+ (to_string_with_precision(*(((float*)data) + 2*i + 1), 8)) + ")"; + case 8: return "("+(to_string_with_precision(*(((double*)data) + 2*i), 16))+", "+ (to_string_with_precision(*(((double*)data) + 2*i + 1), 16)) + ")"; + default: + throw LCompilersException("Unsupported kind for complex array constant."); + } + } + case ASR::ttypeType::Logical: { + if (((bool*)data)[i] == 1) return ".true."; + return ".false."; + } + case ASR::ttypeType::String: { + ASR::String_t* char_type = ASR::down_cast(type); + int len = char_type->m_len; + char* data_char = (char*)data + i*len; + // take first len characters + char* new_char = new char[len + 1]; + for (int j = 0; j < len; j++) { + new_char[j] = data_char[j]; + } + new_char[len] = '\0'; + return '\"' + std::string(new_char) + '\"'; + } + default: + throw LCompilersException("Unsupported type for array constant."); + } +} + +inline std::string fetch_ArrayConstant_value(ASR::ArrayConstant_t* x, int i) { + ASR::ttype_t* type = ASRUtils::type_get_past_array(ASRUtils::type_get_past_allocatable(x->m_type)); + return fetch_ArrayConstant_value(x->m_data, type, i); +} + +inline std::string fetch_ArrayConstant_value(ASR::ArrayConstant_t &x, int i) { + ASR::ttype_t* type = ASRUtils::type_get_past_array(ASRUtils::type_get_past_allocatable(x.m_type)); + return fetch_ArrayConstant_value(x.m_data, type, i); +} + +inline std::string fetch_ArrayConstant_value(const ASR::ArrayConstant_t &x, int i) { + ASR::ttype_t* type = ASRUtils::type_get_past_array(ASRUtils::type_get_past_allocatable(x.m_type)); + return fetch_ArrayConstant_value(x.m_data, type, i); +} + +inline ASR::expr_t* fetch_ArrayConstant_value_helper(Allocator &al, const Location& loc, void *data, ASR::ttype_t* type, int i) { + int kind = ASRUtils::extract_kind_from_ttype_t(type); + ASR::expr_t* value = nullptr; + switch (type->type) { + case ASR::ttypeType::Integer : { + switch (kind) { + case 1: value = EXPR(ASR::make_IntegerConstant_t(al, loc, + ((int8_t*)data)[i], type)); break; + case 2: value = EXPR(ASR::make_IntegerConstant_t(al, loc, + ((int16_t*)data)[i], type)); break; + case 4: value = EXPR(ASR::make_IntegerConstant_t(al, loc, + ((int32_t*)data)[i], type)); break; + case 8: value = EXPR(ASR::make_IntegerConstant_t(al, loc, + ((int64_t*)data)[i], type)); break; + default: + throw LCompilersException("Unsupported kind for integer array constant."); + } + return value; + } + case ASR::ttypeType::Real: { + switch (kind) { + case 4: value = EXPR(ASR::make_RealConstant_t(al, loc, + ((float*)data)[i], type)); break; + case 8: value = EXPR(ASR::make_RealConstant_t(al, loc, + ((double*)data)[i], type)); break; + default: + throw LCompilersException("Unsupported kind for real array constant."); + } + return value; + } + case ASR::ttypeType::UnsignedInteger: { + switch (kind) { + case 1: value = EXPR(ASR::make_IntegerConstant_t(al, loc, + ((uint8_t*)data)[i], type)); break; + case 2: value = EXPR(ASR::make_IntegerConstant_t(al, loc, + ((uint16_t*)data)[i], type)); break; + case 4: value = EXPR(ASR::make_IntegerConstant_t(al, loc, + ((uint32_t*)data)[i], type)); break; + case 8: value = EXPR(ASR::make_IntegerConstant_t(al, loc, + ((uint64_t*)data)[i], type)); break; + default: + throw LCompilersException("Unsupported kind for unsigned integer array constant."); + } + return value; + } + case ASR::ttypeType::Complex: { + switch (kind) { + case 4: value = EXPR(ASR::make_ComplexConstant_t(al, loc, + *(((float*)data) + 2*i), *(((float*)data) + 2*i + 1), type)); break; + case 8: value = EXPR(ASR::make_ComplexConstant_t(al, loc, + *(((double*)data) + 2*i), *(((double*)data) + 2*i + 1), type)); break; + default: + throw LCompilersException("Unsupported kind for complex array constant."); + } + return value; + } + case ASR::ttypeType::Logical: { + value = EXPR(ASR::make_LogicalConstant_t(al, loc, + ((bool*)data)[i], type)); + return value; + } + case ASR::ttypeType::String: { + ASR::String_t* char_type = ASR::down_cast(type); + int len = char_type->m_len; + char* data_char = (char*)data; + std::string str = std::string(data_char + i*len, len); + value = EXPR(ASR::make_StringConstant_t(al, loc, + s2c(al, str), type)); + return value; + } + default: + throw LCompilersException("Unsupported type for array constant."); + } +} + +inline ASR::expr_t* fetch_ArrayConstant_value(Allocator &al, ASR::ArrayConstant_t* x, int i) { + ASR::ttype_t* type = ASRUtils::type_get_past_array(ASRUtils::type_get_past_allocatable(x->m_type)); + return fetch_ArrayConstant_value_helper(al, x->base.base.loc, x->m_data, type, i); +} + +inline ASR::expr_t* fetch_ArrayConstant_value(Allocator &al, ASR::ArrayConstant_t &x, int i) { + ASR::ttype_t* type = ASRUtils::type_get_past_array(ASRUtils::type_get_past_allocatable(x.m_type)); + return fetch_ArrayConstant_value_helper(al, x.base.base.loc, x.m_data, type, i); +} + +inline ASR::expr_t* fetch_ArrayConstant_value(Allocator &al, const ASR::ArrayConstant_t &x, int i) { + ASR::ttype_t* type = ASRUtils::type_get_past_array(ASRUtils::type_get_past_allocatable(x.m_type)); + return fetch_ArrayConstant_value_helper(al, x.base.base.loc, x.m_data, type, i); +} + +template +T* set_data_int(T* data, ASR::expr_t** a_args, size_t n_args) { + for (size_t i = 0; i < n_args; i++) { + if( !ASRUtils::extract_value(ASRUtils::expr_value(a_args[i]), data[i]) ) { + LCOMPILERS_ASSERT(false); + } + // data[i] = ASR::down_cast(ASRUtils::expr_value(a_args[i]))->m_n; + } + return data; +} + +template +T* set_data_real(T* data, ASR::expr_t** a_args, size_t n_args) { + for (size_t i = 0; i < n_args; i++) { + data[i] = ASR::down_cast(ASRUtils::expr_value(a_args[i]))->m_r; + } + return data; +} + +template +T* set_data_complex(T* data, ASR::expr_t** a_args, size_t n_args) { + for (size_t i = 0; i < n_args; i++) { + data[2*i] = ASR::down_cast(ASRUtils::expr_value(a_args[i]))->m_re; + data[2*i + 1] = ASR::down_cast(ASRUtils::expr_value(a_args[i]))->m_im; + } + return data; +} + +inline void* set_ArrayConstant_data(ASR::expr_t** a_args, size_t n_args, ASR::ttype_t* a_type) { + int kind = ASRUtils::extract_kind_from_ttype_t(a_type); + switch (a_type->type) { + case ASR::ttypeType::Integer: { + switch (kind) { + case 1: return set_data_int(new int8_t[n_args], a_args, n_args); + case 2: return set_data_int(new int16_t[n_args], a_args, n_args); + case 4: return set_data_int(new int32_t[n_args], a_args, n_args); + case 8: return set_data_int(new int64_t[n_args], a_args, n_args); + default: + throw LCompilersException("Unsupported kind for integer array constant."); + } + } + case ASR::ttypeType::Real: { + switch (kind) { + case 4: return set_data_real(new float[n_args], a_args, n_args); + case 8: return set_data_real(new double[n_args], a_args, n_args); + default: + throw LCompilersException("Unsupported kind for real array constant."); + } + } + case ASR::ttypeType::UnsignedInteger: { + switch (kind) { + case 1: return set_data_int(new uint8_t[n_args], a_args, n_args); + case 2: return set_data_int(new uint16_t[n_args], a_args, n_args); + case 4: return set_data_int(new uint32_t[n_args], a_args, n_args); + case 8: return set_data_int(new uint64_t[n_args], a_args, n_args); + default: + throw LCompilersException("Unsupported kind for unsigned integer array constant."); + } + } + case ASR::ttypeType::Complex: { + switch (kind) { + case 4: return set_data_complex(new float[2*n_args], a_args, n_args); + case 8: return set_data_complex(new double[2*n_args], a_args, n_args); + default: + throw LCompilersException("Unsupported kind for complex array constant."); + } + } + case ASR::ttypeType::Logical: { + bool* data = new bool[n_args]; + for (size_t i = 0; i < n_args; i++) { + data[i] = ASR::down_cast(ASRUtils::expr_value(a_args[i]))->m_value; + } + return (void*) data; + } + case ASR::ttypeType::String: { + int len = ASR::down_cast(a_type)->m_len; + char* data = new char[len*n_args + 1]; + for (size_t i = 0; i < n_args; i++) { + char* value = ASR::down_cast(ASRUtils::expr_value(a_args[i]))->m_s; + for (int j = 0; j < len; j++) { + data[i*len + j] = value[j]; + } + } + data[len*n_args] = '\0'; + return (void*) data; + } + default: + throw LCompilersException("Unsupported type for array constant."); + } +} + +inline void flatten_ArrayConstant_data(Allocator &al, Vec &data, ASR::expr_t** a_args, size_t n_args, ASR::ttype_t* a_type, int &curr_idx, ASR::ArrayConstant_t* x = nullptr) { + if (x != nullptr) { + // this is array constant, we have it's data available + void* x_data = x->m_data; + for (size_t i = 0; i < (size_t) ASRUtils::get_fixed_size_of_array(x->m_type); i++) { + ASR::expr_t* value = fetch_ArrayConstant_value_helper(al, x->base.base.loc, x_data, a_type, i); + if (ASR::is_a(*value)) { + ASR::ArrayConstant_t* value_ = ASR::down_cast(value); + flatten_ArrayConstant_data(al, data, a_args, n_args, a_type, curr_idx, value_); + } else { + data.push_back(al, value); + curr_idx++; + } + } + return; + } + for (size_t i = 0; i < n_args; i++) { + ASR::expr_t* a_value = ASRUtils::expr_value(a_args[i]); + if (ASR::is_a(*a_value)) { + ASR::ArrayConstant_t* a_value_ = ASR::down_cast(a_value); + flatten_ArrayConstant_data(al, data, a_args, n_args, a_type, curr_idx, a_value_); + } else { + data.push_back(al, a_value); + curr_idx++; + } + } +} + +inline ASR::asr_t* make_ArrayConstructor_t_util(Allocator &al, const Location &a_loc, + ASR::expr_t** a_args, size_t n_args, ASR::ttype_t* a_type, ASR::arraystorageType a_storage_format) { + if( !ASRUtils::is_array(a_type) ) { + Vec dims; + dims.reserve(al, 1); + ASR::dimension_t dim; + dim.loc = a_loc; + dim.m_length = ASRUtils::EXPR(ASR::make_IntegerConstant_t( + al, a_loc, n_args, ASRUtils::TYPE(ASR::make_Integer_t(al, a_loc, 4)))); + dim.m_start = ASRUtils::EXPR(ASR::make_IntegerConstant_t( + al, a_loc, 0, ASRUtils::TYPE(ASR::make_Integer_t(al, a_loc, 4)))); + dims.push_back(al, dim); + a_type = ASRUtils::make_Array_t_util(al, dim.loc, + a_type, dims.p, dims.size(), ASR::abiType::Source, + false, ASR::array_physical_typeType::PointerToDataArray, true); + } else if( ASR::is_a(*a_type) ) { + ASR::dimension_t* m_dims = nullptr; int n_dims = ASRUtils::extract_dimensions_from_ttype(a_type, m_dims); if( !ASRUtils::is_dimension_empty(m_dims, n_dims) ) { a_type = ASRUtils::duplicate_type_with_empty_dims(al, a_type); @@ -5026,6 +5759,17 @@ inline ASR::asr_t* make_ArrayConstructor_t_util(Allocator &al, const Location &a LCOMPILERS_ASSERT(ASRUtils::is_array(a_type)); bool all_expr_evaluated = n_args > 0; + bool is_array_item_constant = n_args > 0 && (ASR::is_a(*a_args[0]) || + ASR::is_a(*a_args[0]) || + ASR::is_a(*a_args[0]) || + ASR::is_a(*a_args[0]) || + ASR::is_a(*a_args[0]) || + ASR::is_a(*a_args[0]) || + ASR::is_a(*a_args[0])); + if( n_args > 0 ) { + is_array_item_constant = is_array_item_constant || ASR::is_a(*a_args[0]); + } + ASR::expr_t* value = nullptr; for (size_t i = 0; i < n_args; i++) { ASR::expr_t* a_value = ASRUtils::expr_value(a_args[i]); if (!is_value_constant(a_value)) { @@ -5034,24 +5778,50 @@ inline ASR::asr_t* make_ArrayConstructor_t_util(Allocator &al, const Location &a } if (all_expr_evaluated) { Vec a_args_values; a_args_values.reserve(al, n_args); - flatten_ArrayConstant(al, a_args, n_args, a_args_values); + int curr_idx = 0; + a_type = ASRUtils::type_get_past_pointer(a_type); ASR::Array_t* a_type_ = ASR::down_cast(a_type); + flatten_ArrayConstant_data(al, a_args_values, a_args, n_args, a_type_->m_type, curr_idx, nullptr); Vec dims; dims.reserve(al, 1); ASR::dimension_t dim; dim.loc = a_type_->m_dims[0].loc; dim.m_start = a_type_->m_dims[0].m_start; - dim.m_length = ASRUtils::EXPR(ASR::make_IntegerConstant_t(al, a_type_->m_dims[0].m_length->base.loc, - a_args_values.n, + dim.m_length = ASRUtils::EXPR(ASR::make_IntegerConstant_t(al, a_type_->m_dims[0].loc, + curr_idx, ASRUtils::TYPE(ASR::make_Integer_t(al, a_loc, 4)))); dims.push_back(al, dim); ASR::ttype_t* new_type = ASRUtils::TYPE(ASR::make_Array_t(al, a_type->base.loc, a_type_->m_type, dims.p, dims.n, a_type_->m_physical_type)); - return ASR::make_ArrayConstant_t(al, a_loc, a_args_values.p, a_args_values.n, new_type, a_storage_format); - } else { - return ASR::make_ArrayConstructor_t(al, a_loc, a_args, n_args, a_type, nullptr, a_storage_format); + void *data = set_ArrayConstant_data(a_args_values.p, curr_idx, a_type_->m_type); + // data is always allocated to n_data bytes + int64_t n_data = curr_idx * extract_kind_from_ttype_t(a_type_->m_type); + if (is_character(*a_type_->m_type)) { + n_data = curr_idx * ASR::down_cast(a_type_->m_type)->m_len; + } + value = ASRUtils::EXPR(ASR::make_ArrayConstant_t(al, a_loc, n_data, data, new_type, a_storage_format)); } + + return is_array_item_constant && all_expr_evaluated ? (ASR::asr_t*) value : + ASR::make_ArrayConstructor_t(al, a_loc, a_args, n_args, a_type, + value, a_storage_format); } void make_ArrayBroadcast_t_util(Allocator& al, const Location& loc, - ASR::expr_t*& expr1, ASR::expr_t*& expr2); + ASR::expr_t*& expr1, ASR::expr_t*& expr2, bool is_simd_array=false); + +// Wraps argument in stringformat if it's not a single argument of type Character. +static inline ASR::asr_t* make_print_t_util(Allocator& al, const Location& loc, + ASR::expr_t** a_args, size_t n_args){ + LCOMPILERS_ASSERT(n_args > 0); + if(n_args == 1 && ASR::is_a(*ASRUtils::expr_type(a_args[0]))){ + return ASR::make_Print_t(al, loc, a_args[0]); + } else { + ASR::ttype_t *char_type = ASRUtils::TYPE(ASR::make_String_t( + al, loc, -1, 0, nullptr, ASR::string_physical_typeType::PointerString)); + return ASR::make_Print_t(al, loc, + ASRUtils::EXPR(ASR::make_StringFormat_t(al, loc, nullptr, a_args,n_args, + ASR::string_format_kindType::FormatFortran, char_type, nullptr))); + } +} + static inline void Call_t_body(Allocator& al, ASR::symbol_t* a_name, ASR::call_arg_t* a_args, size_t n_args, ASR::expr_t* a_dt, ASR::stmt_t** cast_stmt, @@ -5064,8 +5834,7 @@ static inline void Call_t_body(Allocator& al, ASR::symbol_t* a_name, ASR::FunctionType_t* func_type = get_FunctionType(a_name); for( size_t i = 0; i < n_args; i++ ) { - if( a_args[i].m_value == nullptr || - ASR::is_a(*a_args[i].m_value) ) { + if( a_args[i].m_value == nullptr ) { continue; } ASR::expr_t* arg = a_args[i].m_value; @@ -5073,9 +5842,15 @@ static inline void Call_t_body(Allocator& al, ASR::symbol_t* a_name, ASRUtils::type_get_past_pointer(ASRUtils::expr_type(arg))); ASR::ttype_t* orig_arg_type = ASRUtils::type_get_past_allocatable( ASRUtils::type_get_past_pointer(func_type->m_arg_types[i + is_method])); + // cast string source based on the dest + if( ASRUtils::is_character(*orig_arg_type) && + !ASRUtils::is_descriptorString(orig_arg_type) && + ASRUtils::is_descriptorString(ASRUtils::expr_type(a_args[i].m_value))){ + a_args[i].m_value = ASRUtils::cast_string_descriptor_to_pointer(al, a_args[i].m_value); + } if( !ASRUtils::is_intrinsic_symbol(a_name_) && - !(ASR::is_a(*ASRUtils::type_get_past_array(arg_type)) || - ASR::is_a(*ASRUtils::type_get_past_array(orig_arg_type))) && + !(ASR::is_a(*ASRUtils::type_get_past_array(arg_type)) || + ASR::is_a(*ASRUtils::type_get_past_array(orig_arg_type))) && !(ASR::is_a(*ASRUtils::type_get_past_array(arg_type)) || ASR::is_a(*ASRUtils::type_get_past_array(orig_arg_type))) && a_dt == nullptr ) { @@ -5116,7 +5891,7 @@ static inline void Call_t_body(Allocator& al, ASR::symbol_t* a_name, ASR::ttype_t* pointer_type = ASRUtils::TYPE(ASR::make_Pointer_t(al, orig_arg_type->base.loc, arg_array_type)); std::string cast_sym_name = current_scope->get_unique_name(sym_name + "_cast", false); - ASR::asr_t* cast_ = ASR::make_Variable_t(al, arg->base.loc, + ASR::asr_t* cast_ = ASRUtils::make_Variable_t_util(al, arg->base.loc, current_scope, s2c(al, cast_sym_name), nullptr, 0, ASR::intentType::Local, nullptr, nullptr, ASR::storage_typeType::Default, pointer_type, nullptr, @@ -5206,23 +5981,80 @@ static inline void Call_t_body(Allocator& al, ASR::symbol_t* a_name, dimension_.from_pointer_n_copy(al, orig_arg_array_t->m_dims, orig_arg_array_t->n_dims); dimensions = &dimension_; } - - physical_cast_arg.m_value = ASRUtils::EXPR(ASRUtils::make_ArrayPhysicalCast_t_util( - al, arg->base.loc, arg, arg_array_t->m_physical_type, orig_arg_array_t->m_physical_type, - ASRUtils::duplicate_type(al, ASRUtils::expr_type(arg), dimensions, orig_arg_array_t->m_physical_type, true), - nullptr)); + //TO DO : Add appropriate errors in 'asr_uttils.h'. + LCOMPILERS_ASSERT_MSG(dimensions_compatible(arg_array_t->m_dims, arg_array_t->n_dims, + orig_arg_array_t->m_dims, orig_arg_array_t->n_dims, false), + "Incompatible dimensions passed to " + (std::string)(ASR::down_cast(a_name_)->m_name) + + "(" + std::to_string(get_fixed_size_of_array(arg_array_t->m_dims,arg_array_t->n_dims)) + "/" + std::to_string(get_fixed_size_of_array(orig_arg_array_t->m_dims,orig_arg_array_t->n_dims))+")"); + + ASR::ttype_t* physical_cast_type = ASRUtils::type_get_past_allocatable( + ASRUtils::expr_type(arg)); + physical_cast_arg.m_value = ASRUtils::EXPR( + ASRUtils::make_ArrayPhysicalCast_t_util( + al, + arg->base.loc, + arg, + arg_array_t->m_physical_type, + orig_arg_array_t->m_physical_type, + ASRUtils::duplicate_type(al, + physical_cast_type, + dimensions, + orig_arg_array_t->m_physical_type, + true), + nullptr)); a_args[i] = physical_cast_arg; } } } } +static inline bool is_elemental(ASR::symbol_t* x) { + x = ASRUtils::symbol_get_past_external(x); + if( !ASR::is_a(*x) ) { + return false; + } + return ASRUtils::get_FunctionType( + ASR::down_cast(x))->m_elemental; +} + static inline ASR::asr_t* make_FunctionCall_t_util( Allocator &al, const Location &a_loc, ASR::symbol_t* a_name, ASR::symbol_t* a_original_name, ASR::call_arg_t* a_args, size_t n_args, - ASR::ttype_t* a_type, ASR::expr_t* a_value, ASR::expr_t* a_dt) { - - Call_t_body(al, a_name, a_args, n_args, a_dt, nullptr, false, false); + ASR::ttype_t* a_type, ASR::expr_t* a_value, ASR::expr_t* a_dt, bool nopass=false) { + + Call_t_body(al, a_name, a_args, n_args, a_dt, nullptr, false, nopass); + + if( ASRUtils::is_array(a_type) && ASRUtils::is_elemental(a_name) && + !ASRUtils::is_fixed_size_array(a_type) && + !ASRUtils::is_dimension_dependent_only_on_arguments(a_type) ) { + ASR::ttype_t* type_ = ASRUtils::extract_type(a_type); + #define i32j(j) ASRUtils::EXPR(ASR::make_IntegerConstant_t(al, a_loc, j, \ + ASRUtils::TYPE(ASR::make_Integer_t(al, a_loc, 4)))) + ASR::expr_t* i32one = i32j(1); + for( size_t i = 0; i < n_args; i++ ) { + ASR::ttype_t* type = ASRUtils::expr_type(a_args[i].m_value); + if (ASRUtils::is_array(type)) { + ASR::dimension_t* m_dims = nullptr; + size_t n_dims = ASRUtils::extract_dimensions_from_ttype(type, m_dims); + if( ASRUtils::is_dimension_empty(m_dims, n_dims) ) { + Vec m_dims_vec; m_dims_vec.reserve(al, n_dims); + for( size_t j = 0; j < n_dims; j++ ) { + ASR::dimension_t m_dim_vec; + m_dim_vec.loc = m_dims[j].loc; + m_dim_vec.m_start = i32one; + m_dim_vec.m_length = ASRUtils::EXPR(ASRUtils::make_ArraySize_t_util(al, m_dims[j].loc, + a_args[i].m_value, i32j(j + 1), ASRUtils::expr_type(i32one), nullptr)); + m_dims_vec.push_back(al, m_dim_vec); + } + m_dims = m_dims_vec.p; + n_dims = m_dims_vec.size(); + } + a_type = ASRUtils::make_Array_t_util(al, type->base.loc, type_, m_dims, n_dims, + ASR::abiType::Source, false, ASR::array_physical_typeType::DescriptorArray, true); + break; + } + } + } return ASR::make_FunctionCall_t(al, a_loc, a_name, a_original_name, a_args, n_args, a_type, a_value, a_dt); @@ -5239,12 +6071,36 @@ static inline ASR::asr_t* make_SubroutineCall_t_util( *ASRUtils::symbol_get_past_external(a_name)) && ASR::is_a(*ASRUtils::symbol_type(a_name)) ) { a_dt = ASRUtils::EXPR(ASR::make_StructInstanceMember_t(al, a_loc, - a_dt, a_name, ASRUtils::symbol_type(a_name), nullptr)); + a_dt, a_name, ASRUtils::duplicate_type(al, ASRUtils::symbol_type(a_name)), nullptr)); } return ASR::make_SubroutineCall_t(al, a_loc, a_name, a_original_name, a_args, n_args, a_dt); } +/* + Checks if the function `f` is elemental and any of argument in + `args` is an array type, if yes, it returns the first array + argument, otherwise returns nullptr +*/ +static inline ASR::expr_t* find_first_array_arg_if_elemental( + const ASR::Function_t* f, + const Vec& args +) { + ASR::expr_t* first_array_argument = nullptr; + bool is_elemental = ASRUtils::get_FunctionType(f)->m_elemental; + if (!is_elemental || f->n_args == 0) { + return first_array_argument; + } + for (size_t i=0; i < args.size(); i++) { + if (args[i].m_value && is_array(ASRUtils::expr_type(args[i].m_value))) { + // return the very first *array* argument + first_array_argument = args[i].m_value; + break; + } + } + return first_array_argument; +} + static inline void promote_ints_to_kind_8(ASR::expr_t** m_args, size_t n_args, Allocator& al, const Location& loc) { for (size_t i = 0; i < n_args; i++) { @@ -5260,9 +6116,24 @@ static inline void promote_ints_to_kind_8(ASR::expr_t** m_args, size_t n_args, static inline ASR::asr_t* make_StringFormat_t_util(Allocator &al, const Location &a_loc, ASR::expr_t* a_fmt, ASR::expr_t** a_args, size_t n_args, ASR::string_format_kindType a_kind, ASR::ttype_t* a_type, ASR::expr_t* a_value) { - - promote_ints_to_kind_8(a_args, n_args, al, a_loc); - + if (a_fmt && ASR::is_a(*a_fmt)) { + ASR::Variable_t* fmt_str = ASR::down_cast(ASR::down_cast(a_fmt)->m_v); + if (ASR::is_a( + *ASRUtils::extract_type(fmt_str->m_type))) { + ASR::String_t* str_type = ASR::down_cast( + ASRUtils::extract_type(fmt_str->m_type)); + if (str_type->m_physical_type != ASR::string_physical_typeType::PointerString) { + a_fmt = ASRUtils::EXPR(ASR::make_StringPhysicalCast_t( + al, + a_fmt->base.loc, + a_fmt, + str_type->m_physical_type, + ASR::string_physical_typeType::PointerString, + a_type, + nullptr)); + } + } + } return ASR::make_StringFormat_t(al, a_loc, a_fmt, a_args, n_args, a_kind, a_type, a_value); } @@ -5288,8 +6159,7 @@ static inline ASR::asr_t* make_IntrinsicElementalFunction_t_util( ASR::ttype_t* a_type, ASR::expr_t* a_value) { for( size_t i = 0; i < n_args; i++ ) { - if( a_args[i] == nullptr || - ASR::is_a(*a_args[i]) ) { + if( a_args[i] == nullptr ) { continue; } ASR::expr_t* arg = a_args[i]; @@ -5298,6 +6168,14 @@ static inline ASR::asr_t* make_IntrinsicElementalFunction_t_util( if( ASRUtils::is_array(arg_type) ) { a_args[i] = cast_to_descriptor(al, arg); + if( !ASRUtils::is_array(a_type) ) { + ASR::ttype_t* underlying_type = ASRUtils::extract_type(arg_type); + ASR::Array_t* e = ASR::down_cast( + ASRUtils::type_get_past_allocatable( + ASRUtils::type_get_past_pointer(arg_type))); + a_type = TYPE(ASR::make_Array_t(al, a_type->base.loc, underlying_type, + e->m_dims, e->n_dims, e->m_physical_type)); + } } } @@ -5311,8 +6189,7 @@ static inline ASR::asr_t* make_IntrinsicArrayFunction_t_util( ASR::ttype_t* a_type, ASR::expr_t* a_value) { for( size_t i = 0; i < n_args; i++ ) { - if( a_args[i] == nullptr || - ASR::is_a(*a_args[i]) ) { + if( a_args[i] == nullptr ) { continue; } ASR::expr_t* arg = a_args[i]; @@ -5361,6 +6238,92 @@ static inline ASR::asr_t* make_Associate_t_util( return ASR::make_Associate_t(al, a_loc, a_target, a_value); } +static inline ASR::expr_t* extract_array_variable(ASR::expr_t* x) { + LCOMPILERS_ASSERT(ASRUtils::is_array(ASRUtils::expr_type(x))); + if( x->type == ASR::exprType::ArrayItem ) { + return ASR::down_cast(x)->m_v; + } else if( x->type == ASR::exprType::ArraySection ) { + return ASR::down_cast(x)->m_v; + } + + return x; +} + +static inline void extract_array_indices(ASR::expr_t* x, Allocator &al, + Vec& m_args, int& n_args) { + if( x->type == ASR::exprType::ArrayItem ) { + ASR::ArrayItem_t* arr = ASR::down_cast(x); + for(size_t i = 0; i < arr->n_args; i++){ + if((arr->m_args[i].m_left && arr->m_args[i].m_right && arr->m_args[i].m_step) || + (arr->m_args[i].m_right && ASRUtils::is_array(ASRUtils::expr_type(arr->m_args[i].m_right)))){ + m_args.push_back(al, arr->m_args[i]); + n_args++; + } + } + return ; + } else if( x->type == ASR::exprType::ArraySection ) { + ASR::ArraySection_t* arr = ASR::down_cast(x); + for(size_t i = 0; i < arr->n_args; i++){ + if((arr->m_args[i].m_left && arr->m_args[i].m_right && arr->m_args[i].m_step) || + (arr->m_args[i].m_right && ASRUtils::is_array(ASRUtils::expr_type(arr->m_args[i].m_right)))){ + m_args.push_back(al, arr->m_args[i]); + n_args++; + } + } + } +} + +static inline void extract_indices(ASR::expr_t* x, + ASR::array_index_t*& m_args, size_t& n_args) { + if( x->type == ASR::exprType::ArrayItem ) { + m_args = ASR::down_cast(x)->m_args; + n_args = ASR::down_cast(x)->n_args; + return ; + } else if( x->type == ASR::exprType::ArraySection ) { + m_args = ASR::down_cast(x)->m_args; + n_args = ASR::down_cast(x)->n_args; + return ; + } + + m_args = nullptr; + n_args = 0; +} + +static inline bool is_array_indexed_with_array_indices(ASR::array_index_t* m_args, size_t n_args) { + for( size_t i = 0; i < n_args; i++ ) { + if( m_args[i].m_left == nullptr && + m_args[i].m_right != nullptr && + m_args[i].m_step == nullptr && + ASRUtils::is_array( + ASRUtils::expr_type(m_args[i].m_right)) ) { + return true; + } + } + + return false; +} + +template +static inline bool is_array_indexed_with_array_indices(T* x) { + return is_array_indexed_with_array_indices(x->m_args, x->n_args); +} + +static inline ASR::ttype_t* create_array_type_with_empty_dims(Allocator& al, + size_t value_n_dims, ASR::ttype_t* value_type) { + Vec empty_dims; empty_dims.reserve(al, value_n_dims); + for( size_t i = 0; i < value_n_dims; i++ ) { + ASR::dimension_t empty_dim; + Location loc; loc.first = 1, loc.last = 1; + empty_dim.loc = loc; + empty_dim.m_length = nullptr; + empty_dim.m_start = nullptr; + empty_dims.push_back(al, empty_dim); + } + return ASRUtils::make_Array_t_util(al, value_type->base.loc, + ASRUtils::extract_type(value_type), empty_dims.p, empty_dims.size()); +} + + static inline ASR::asr_t* make_ArrayItem_t_util(Allocator &al, const Location &a_loc, ASR::expr_t* a_v, ASR::array_index_t* a_args, size_t n_args, ASR::ttype_t* a_type, ASR::arraystorageType a_storage_format, ASR::expr_t* a_value) { @@ -5368,6 +6331,22 @@ static inline ASR::asr_t* make_ArrayItem_t_util(Allocator &al, const Location &a a_v = ASR::down_cast(a_v)->m_arg; } + if( !ASRUtils::is_array_indexed_with_array_indices(a_args, n_args) ) { + a_type = ASRUtils::extract_type(a_type); + } + + if( ASRUtils::is_allocatable(a_type) ) { + ASR::dimension_t* m_dims = nullptr; + size_t n_dims = ASRUtils::extract_dimensions_from_ttype(a_type, m_dims); + if( !ASRUtils::is_dimension_empty(m_dims, n_dims) ) { + a_type = ASRUtils::create_array_type_with_empty_dims( + al, n_dims, ASRUtils::extract_type(a_type)); + a_type = ASRUtils::TYPE(ASR::make_Allocatable_t(al, a_loc, a_type)); + } + } + + ASRUtils::ExprStmtDuplicator type_duplicator(al); + a_type = type_duplicator.duplicate_ttype(a_type); return ASR::make_ArrayItem_t(al, a_loc, a_v, a_args, n_args, a_type, a_storage_format, a_value); } @@ -5389,12 +6368,16 @@ int64_t compute_leading_zeros(int64_t number, int64_t kind); void append_error(diag::Diagnostics& diag, const std::string& msg, const Location& loc); -static inline bool is_simd_array(ASR::expr_t *v) { - return (ASR::is_a(*expr_type(v)) && - ASR::down_cast(expr_type(v))->m_physical_type +static inline bool is_simd_array(ASR::ttype_t* t) { + return (ASR::is_a(*t) && + ASR::down_cast(t)->m_physical_type == ASR::array_physical_typeType::SIMDArray); } +static inline bool is_simd_array(ASR::expr_t *v) { + return is_simd_array(expr_type(v)); +} + static inline bool is_argument_of_type_CPtr(ASR::expr_t *var) { bool is_argument = false; if (ASR::is_a(*expr_type(var))) { @@ -5450,6 +6433,104 @@ void declare_function(Allocator &al, ASRFunc fn, const Location &l, SymbolTable void declare_functions(Allocator &al, std::vector fns, const Location &l, SymbolTable *parent_scope, std::string header_name=""); +static inline void promote_arguments_kinds(Allocator &al, const Location &loc, + Vec &args, diag::Diagnostics &diag) { + int target_kind = -1; + for (size_t i = 0; i < args.size(); i++) { + ASR::ttype_t *arg_type = ASRUtils::expr_type(args[i]); + int kind = ASRUtils::extract_kind_from_ttype_t(arg_type); + if (is_array(arg_type)){ + target_kind = kind; + break; + } + if (kind > target_kind) { + target_kind = kind; + } + } + + for (size_t i = 0; i < args.size(); i++) { + ASR::ttype_t *arg_type = ASRUtils::expr_type(args[i]); + int kind = ASRUtils::extract_kind_from_ttype_t(arg_type); + if (kind==target_kind) { + continue; + } + if (ASR::is_a(*arg_type)) { + if (ASR::is_a(*args[i])) { + args.p[i] = EXPR(ASR::make_RealConstant_t( + al, loc, ASR::down_cast(args[i])->m_r, + ASRUtils::TYPE(ASR::make_Real_t(al, loc, target_kind)))); + } else { + args.p[i] = EXPR(ASR::make_Cast_t( + al, loc, args.p[i], ASR::cast_kindType::RealToReal, + ASRUtils::TYPE(ASR::make_Real_t(al, loc, target_kind)), nullptr)); + } + } else if (ASR::is_a(*arg_type)) { + if (ASR::is_a(*args[i])) { + args.p[i] = EXPR(ASR::make_IntegerConstant_t( + al, loc, ASR::down_cast(args[i])->m_n, + ASRUtils::TYPE(ASR::make_Integer_t(al, loc, target_kind)))); + } else { + args.p[i] = EXPR(ASR::make_Cast_t( + al, loc, args[i], ASR::cast_kindType::IntegerToInteger, + ASRUtils::TYPE(ASR::make_Integer_t(al, loc, target_kind)), nullptr)); + } + } else { + diag.semantic_error_label("Unsupported argument type for kind adjustment", {loc}, + "help: ensure all arguments are of a convertible type"); + } + } +} + +class RemoveArrayProcessingNodeReplacer: public ASR::BaseExprReplacer { + + public: + + Allocator& al; + + RemoveArrayProcessingNodeReplacer(Allocator& al_): al(al_) { + } + + void replace_ArrayBroadcast(ASR::ArrayBroadcast_t* x) { + *current_expr = x->m_array; + } + + void replace_ArrayPhysicalCast(ASR::ArrayPhysicalCast_t* x) { + if( x->m_new == ASR::array_physical_typeType::SIMDArray ) { + return ; + } + ASR::BaseExprReplacer::replace_ArrayPhysicalCast(x); + if( !ASRUtils::is_array(ASRUtils::expr_type(x->m_arg)) ) { + *current_expr = x->m_arg; + } + } + +}; + +class RemoveArrayProcessingNodeVisitor: public ASR::CallReplacerOnExpressionsVisitor { + + private: + + RemoveArrayProcessingNodeReplacer replacer; + + public: + + void call_replacer() { + replacer.current_expr = current_expr; + replacer.replace_expr(*current_expr); + } + + RemoveArrayProcessingNodeVisitor(Allocator& al_): replacer(al_) {} + + void visit_ArrayPhysicalCast(const ASR::ArrayPhysicalCast_t& x) { + if( x.m_new == ASR::array_physical_typeType::SIMDArray ) { + return ; + } + + ASR::CallReplacerOnExpressionsVisitor::visit_ArrayPhysicalCast(x); + } + +}; + } // namespace ASRUtils } // namespace LCompilers diff --git a/src/libasr/asr_verify.cpp b/src/libasr/asr_verify.cpp index 4ebfe83aa2..9c54e3096c 100644 --- a/src/libasr/asr_verify.cpp +++ b/src/libasr/asr_verify.cpp @@ -6,6 +6,8 @@ #include #include +#include + namespace LCompilers { namespace ASR { @@ -78,19 +80,19 @@ class VerifyVisitor : public BaseWalkVisitor // The symbol table was found and the symbol `sym` is in it return true; } else { - diagnostics.message_label("ASR verify: The symbol table was found and the symbol in it shares the name, but is not equal to `sym`", + diagnostics.message_label("The symbol table was found and the symbol in it shares the name, but is not equal to `sym`", {sym->base.loc}, "failed here", diag::Level::Error, diag::Stage::ASRVerify); return false; } } else { - diagnostics.message_label("ASR verify: The symbol table was found, but the symbol `sym` is not in it", + diagnostics.message_label("The symbol table was found, but the symbol `sym` is not in it", {sym->base.loc}, "failed here", diag::Level::Error, diag::Stage::ASRVerify); return false; } } s = s->parent; } - diagnostics.message_label("ASR verify: The symbol table was not found in the scope of `symtab`.", + diagnostics.message_label("The symbol table was not found in the scope of `symtab`.", {sym->base.loc}, "failed here", diag::Level::Error, diag::Stage::ASRVerify); return false; } @@ -366,6 +368,8 @@ class VerifyVisitor : public BaseWalkVisitor ASR::symbol_t* target_sym = ASRUtils::symbol_get_past_external(target_Var->m_v); if( target_sym && ASR::is_a(*target_sym) ) { ASR::Variable_t* var = ASR::down_cast(target_sym); + require(var->m_intent != ASR::intentType::In, "Assignment target `" + + std::string(var->m_name) + "` with intent `IN` not allowed"); target_type = var->m_type; is_target_const = var->m_storage == ASR::storage_typeType::Parameter; } @@ -420,8 +424,7 @@ class VerifyVisitor : public BaseWalkVisitor } void visit_Function(const Function_t &x) { - ASR::FunctionType_t* x_func_type = ASR::down_cast(x.m_function_signature); - if (x_func_type->m_abi == abiType::Interactive) { + if (ASRUtils::get_FunctionType(&x)->m_abi == abiType::Interactive) { require(x.n_body == 0, "The Function::n_body should be 0 if abi set to Interactive"); } @@ -527,10 +530,9 @@ class VerifyVisitor : public BaseWalkVisitor if( ASR::is_a(*a.second) || ASR::is_a(*a.second) || ASR::is_a(*a.second) || - ASR::is_a(*a.second) || + ASR::is_a(*a.second) || ASR::is_a(*a.second) || - ASR::is_a(*a.second) || - ASR::is_a(*a.second)) { + ASR::is_a(*a.second) ) { continue ; } // TODO: Uncomment the following line @@ -541,14 +543,14 @@ class VerifyVisitor : public BaseWalkVisitor if( ASR::is_a(*var_type) ) { sym = ASR::down_cast(var_type)->m_derived_type; aggregate_type_name = ASRUtils::symbol_name(sym); - } else if( ASR::is_a(*var_type) ) { - sym = ASR::down_cast(var_type)->m_enum_type; + } else if( ASR::is_a(*var_type) ) { + sym = ASR::down_cast(var_type)->m_enum_type; aggregate_type_name = ASRUtils::symbol_name(sym); - } else if( ASR::is_a(*var_type) ) { - sym = ASR::down_cast(var_type)->m_union_type; + } else if( ASR::is_a(*var_type) ) { + sym = ASR::down_cast(var_type)->m_union_type; aggregate_type_name = ASRUtils::symbol_name(sym); - } else if( ASR::is_a(*var_type) ) { - sym = ASR::down_cast(var_type)->m_class_type; + } else if( ASR::is_a(*var_type) ) { + sym = ASR::down_cast(var_type)->m_class_type; aggregate_type_name = ASRUtils::symbol_name(sym); } if( aggregate_type_name && ASRUtils::symbol_parent_symtab(sym) != current_symtab ) { @@ -585,23 +587,23 @@ class VerifyVisitor : public BaseWalkVisitor " is not a positive power of 2."); } - void visit_EnumType(const EnumType_t& x) { + void visit_Enum(const Enum_t& x) { visit_UserDefinedType(x); require(x.m_type != nullptr, - "The common type of Enum cannot be nullptr. " + + "The common type of EnumType cannot be nullptr. " + std::string(x.m_name) + " doesn't seem to follow this rule."); ASR::ttype_t* common_type = x.m_type; std::map value2count; for( auto itr: x.m_symtab->get_scope() ) { ASR::Variable_t* itr_var = ASR::down_cast(itr.second); require(itr_var->m_symbolic_value != nullptr, - "All members of Enum must have their values to be set. " + + "All members of EnumType must have their values to be set. " + std::string(itr_var->m_name) + " doesn't seem to follow this rule in " - + std::string(x.m_name) + " Enum."); + + std::string(x.m_name) + " EnumType."); require(ASRUtils::check_equal_type(itr_var->m_type, common_type), - "All members of Enum must the same type. " + + "All members of EnumType must the same type. " + std::string(itr_var->m_name) + " doesn't seem to follow this rule in " + - std::string(x.m_name) + " Enum."); + std::string(x.m_name) + " EnumType."); ASR::expr_t* value = ASRUtils::expr_value(itr_var->m_symbolic_value); int64_t value_int64 = -1; ASRUtils::extract_value(value, value_int64); @@ -635,10 +637,10 @@ class VerifyVisitor : public BaseWalkVisitor is_enumtype_correct = !is_enum_integer; } require(is_enumtype_correct, "Properties of enum value members don't match correspond " - "to EnumType::m_enum_value_type"); + "to Enum::m_enum_value_type"); } - void visit_UnionType(const UnionType_t& x) { + void visit_Union(const Union_t& x) { visit_UserDefinedType(x); } @@ -653,6 +655,8 @@ class VerifyVisitor : public BaseWalkVisitor const symbol_t *current_sym = &x.base; require(symtab_sym == current_sym, "Variable's parent symbol table does not point to it"); + require(current_symtab == symtab, + "Variable's parent-symbolTable and actuall parent symbolTable don't match (Maybe inserted from another symbolTable)"); require(id_symtab_map.find(symtab->counter) != id_symtab_map.end(), "Variable::m_parent_symtab must be present in the ASR (" + std::string(x.m_name) + ")"); @@ -673,8 +677,8 @@ class VerifyVisitor : public BaseWalkVisitor // For now restrict this check only to variables which are present // inside symbols which have a body. require( (x.m_symbolic_value == nullptr && x.m_value == nullptr) || - (x.m_symbolic_value != nullptr && x.m_value != nullptr) || - (x.m_symbolic_value != nullptr && ASRUtils::is_value_constant(x.m_symbolic_value)), + (x.m_symbolic_value != nullptr && x.m_value != nullptr) || + (x.m_symbolic_value != nullptr && ASRUtils::is_value_constant(x.m_symbolic_value)), "Initialisation of " + std::string(x.m_name) + " must reduce to a compile time constant."); } @@ -721,8 +725,8 @@ class VerifyVisitor : public BaseWalkVisitor "ExternalSymbol::m_original_name must match external->m_name"); ASR::Module_t *m = ASRUtils::get_sym_module(x.m_external); ASR::Struct_t* sm = nullptr; - ASR::EnumType_t* em = nullptr; - ASR::UnionType_t* um = nullptr; + ASR::Enum_t* em = nullptr; + ASR::Union_t* um = nullptr; ASR::Function_t* fm = nullptr; bool is_valid_owner = false; is_valid_owner = m != nullptr && ((ASR::symbol_t*) m == ASRUtils::get_asr_owner(x.m_external)); @@ -730,17 +734,17 @@ class VerifyVisitor : public BaseWalkVisitor if( !is_valid_owner ) { ASR::symbol_t* asr_owner_sym = ASRUtils::get_asr_owner(x.m_external); is_valid_owner = (ASR::is_a(*asr_owner_sym) || - ASR::is_a(*asr_owner_sym) || + ASR::is_a(*asr_owner_sym) || ASR::is_a(*asr_owner_sym) || - ASR::is_a(*asr_owner_sym)); + ASR::is_a(*asr_owner_sym)); if( ASR::is_a(*asr_owner_sym) ) { sm = ASR::down_cast(asr_owner_sym); asr_owner_name = sm->m_name; - } else if( ASR::is_a(*asr_owner_sym) ) { - em = ASR::down_cast(asr_owner_sym); + } else if( ASR::is_a(*asr_owner_sym) ) { + em = ASR::down_cast(asr_owner_sym); asr_owner_name = em->m_name; - } else if( ASR::is_a(*asr_owner_sym) ) { - um = ASR::down_cast(asr_owner_sym); + } else if( ASR::is_a(*asr_owner_sym) ) { + um = ASR::down_cast(asr_owner_sym); asr_owner_name = um->m_name; } else if( ASR::is_a(*asr_owner_sym) ) { fm = ASR::down_cast(asr_owner_sym); @@ -797,9 +801,9 @@ class VerifyVisitor : public BaseWalkVisitor s = ASRUtils::symbol_get_past_external(x.m_v); } require(is_a(*s) || is_a(*s) - || is_a(*s) || is_a(*s), + || is_a(*s) || is_a(*s), "Var_t::m_v " + x_mv_name + " does not point to a Variable_t, " \ - "Function_t, or EnumType_t (possibly behind ExternalSymbol_t)"); + "Function_t, or Enum_t (possibly behind ExternalSymbol_t)"); require(symtab_in_scope(current_symtab, x.m_v), "Var::m_v `" + x_mv_name + "` cannot point outside of its symbol table"); variable_dependencies.push_back(x_mv_name); @@ -840,7 +844,7 @@ class VerifyVisitor : public BaseWalkVisitor check_var_external(*x.m_v); int n_dims = ASRUtils::extract_n_dims_from_ttype( ASRUtils::expr_type(x.m_v)); - if (ASR::is_a(*x.m_type) && n_dims == 0) { + if (ASR::is_a(*x.m_type) && n_dims == 0) { // TODO: This seems like a bug, we should not use ArrayItem with // strings but StringItem. For now we ignore it, but we should // fix it @@ -852,10 +856,31 @@ class VerifyVisitor : public BaseWalkVisitor } void visit_ArrayItem(const ArrayItem_t &x) { + if( check_external ) { + if( ASRUtils::is_array_indexed_with_array_indices(x.m_args, x.n_args) ) { + require(ASRUtils::is_array(x.m_type), + "ArrayItem::m_type with array indices must be an array.") + } else { + require(!ASRUtils::is_array(x.m_type), + "ArrayItem::m_type cannot be array.") + } + } handle_ArrayItemSection(x); } + void visit_ArraySize(const ArraySize_t& x) { + if (check_external) { + require(ASRUtils::is_array(ASRUtils::expr_type(x.m_v)), + "ArraySize::m_v must be an array"); + } + BaseWalkVisitor::visit_ArraySize(x); + } + void visit_ArraySection(const ArraySection_t &x) { + require( + ASR::is_a(*x.m_type), + "ArrayItemSection::m_type can only be an Array" + ); handle_ArrayItemSection(x); } @@ -896,11 +921,13 @@ class VerifyVisitor : public BaseWalkVisitor require(x.m_new != x.m_old, "ArrayPhysicalCast is redundant, " "the old physical type and new physical type must be different."); } - require(x.m_new == ASRUtils::extract_physical_type(x.m_type), - "Destination physical type conflicts with the physical type of target"); - require(x.m_old == ASRUtils::extract_physical_type(ASRUtils::expr_type(x.m_arg)), - "Old physical type conflicts with the physical type of argument " + std::to_string(x.m_old) - + " " + std::to_string(ASRUtils::extract_physical_type(ASRUtils::expr_type(x.m_arg)))); + if(check_external){ + require(x.m_new == ASRUtils::extract_physical_type(x.m_type), + "Destination physical type conflicts with the physical type of target"); + require(x.m_old == ASRUtils::extract_physical_type(ASRUtils::expr_type(x.m_arg)), + "Old physical type conflicts with the physical type of argument " + std::to_string(x.m_old) + + " " + std::to_string(ASRUtils::extract_physical_type(ASRUtils::expr_type(x.m_arg)))); + } } void visit_SubroutineCall(const SubroutineCall_t &x) { @@ -910,7 +937,7 @@ class VerifyVisitor : public BaseWalkVisitor ASR::symbol_t *s = ASRUtils::symbol_get_past_external(x.m_name); if (ASR::is_a(*s)) { ASR::Variable_t *v = ASR::down_cast(s); - require(v->m_type_declaration && ASR::is_a(*v->m_type_declaration), + require(v->m_type_declaration && ASR::is_a(*ASRUtils::symbol_get_past_external(v->m_type_declaration)), "SubroutineCall::m_name '" + std::string(symbol_name(x.m_name)) + "' is a Variable, but does not point to Function"); require(ASR::is_a(*v->m_type), "SubroutineCall::m_name '" + std::string(symbol_name(x.m_name)) + "' is a Variable, but the type is not FunctionType"); @@ -973,13 +1000,13 @@ class VerifyVisitor : public BaseWalkVisitor type_sym = ASR::down_cast(t2)->m_derived_type; break; } - case (ASR::ttypeType::Class): { - type_sym = ASR::down_cast(t2)->m_class_type; + case (ASR::ttypeType::ClassType): { + type_sym = ASR::down_cast(t2)->m_class_type; break; } default : require_with_loc(false, - "m_dt::m_v::m_type must point to a type with a symbol table (StructType or Class)", + "m_dt::m_v::m_type must point to a type with a symbol table (StructType or ClassType)", dt->base.loc); } return get_dt_symtab(type_sym); @@ -1014,8 +1041,8 @@ class VerifyVisitor : public BaseWalkVisitor parent = der_type->m_parent; break; } - case (ASR::ttypeType::Class): { - type_sym = ASR::down_cast(t2)->m_class_type; + case (ASR::ttypeType::ClassType): { + type_sym = ASR::down_cast(t2)->m_class_type; type_sym = ASRUtils::symbol_get_past_external(type_sym); if( type_sym->type == ASR::symbolType::Struct ) { ASR::Struct_t* der_type = ASR::down_cast(type_sym); @@ -1156,30 +1183,31 @@ class VerifyVisitor : public BaseWalkVisitor require(ASRUtils::is_array(x.m_type), "Type of ArrayConstant must be an array"); - for (size_t i = 0; i < x.n_args; i++) { - require(!ASR::is_a(*x.m_args[i]), - "ArrayConstant cannot have ArrayConstant as its elements"); - ASR::expr_t* arg_value = ASRUtils::expr_value(x.m_args[i]); - require( - ASRUtils::is_value_constant(arg_value), - "ArrayConstant must have constant values"); + int64_t n_data = ASRUtils::get_fixed_size_of_array(x.m_type) * ASRUtils::extract_kind_from_ttype_t(x.m_type); + if (ASRUtils::is_character(*x.m_type)) { + ASR::ttype_t* t = ASRUtils::type_get_past_array(x.m_type); + n_data = ASRUtils::get_fixed_size_of_array(x.m_type) * ASR::down_cast(t)->m_len; } - + require(n_data == x.m_n_data, "ArrayConstant::m_n_data must match the byte size of the array"); visit_ttype(*x.m_type); } void visit_dimension(const dimension_t &x) { if (x.m_start) { - require_with_loc(ASRUtils::is_integer( - *ASRUtils::expr_type(x.m_start)), - "Start dimension must be a signed integer", x.loc); + if(check_external){ + require_with_loc(ASRUtils::is_integer( + *ASRUtils::expr_type(x.m_start)), + "Start dimension must be a signed integer", x.loc); + } visit_expr(*x.m_start); } if (x.m_length) { - require_with_loc(ASRUtils::is_integer( - *ASRUtils::expr_type(x.m_length)), - "Length dimension must be a signed integer", x.loc); + if(check_external){ + require_with_loc(ASRUtils::is_integer( + *ASRUtils::expr_type(x.m_length)), + "Length dimension must be a signed integer", x.loc); + } visit_expr(*x.m_length); } } @@ -1214,19 +1242,39 @@ class VerifyVisitor : public BaseWalkVisitor void visit_Allocatable(const Allocatable_t &x) { require(!ASR::is_a(*x.m_type), "Allocatable type conflicts with Pointer type"); + ASR::dimension_t* m_dims = nullptr; + size_t n_dims = ASRUtils::extract_dimensions_from_ttype(x.m_type, m_dims); + for( size_t i = 0; i < n_dims; i++ ) { + require(m_dims[i].m_length == nullptr, + "Length of allocatable should be deferred (empty)."); + } visit_ttype(*x.m_type); } void visit_Allocate(const Allocate_t &x) { - for( size_t i = 0; i < x.n_args; i++ ) { - require(ASR::is_a(*ASRUtils::expr_type(x.m_args[i].m_a)) || - ASR::is_a(*ASRUtils::expr_type(x.m_args[i].m_a)), - "Allocate should only be called with Allocatable or Pointer type inputs, found " + - std::string(ASRUtils::get_type_code(ASRUtils::expr_type(x.m_args[i].m_a)))); + if(check_external){ + for( size_t i = 0; i < x.n_args; i++ ) { + require(ASR::is_a(*ASRUtils::expr_type(x.m_args[i].m_a)) || + ASR::is_a(*ASRUtils::expr_type(x.m_args[i].m_a)), + "Allocate should only be called with Allocatable or Pointer type inputs, found " + + std::string(ASRUtils::get_type_code(ASRUtils::expr_type(x.m_args[i].m_a)))); + } } BaseWalkVisitor::visit_Allocate(x); } + void visit_DoConcurrentLoop(const DoConcurrentLoop_t &x) { + for ( size_t i = 0; i < x.n_local; i++ ) { + require(ASR::is_a(*x.m_local[i]), + "DoConcurrentLoop::m_local must be a Var"); + } + for ( size_t i = 0; i < x.n_shared; i++ ) { + require(ASR::is_a(*x.m_shared[i]), + "DoConcurrentLoop::m_shared must be a Var"); + } + BaseWalkVisitor::visit_DoConcurrentLoop(x); + } + }; diff --git a/src/libasr/asr_walk_visitor.h b/src/libasr/asr_walk_visitor.h new file mode 100644 index 0000000000..4e53bccedb --- /dev/null +++ b/src/libasr/asr_walk_visitor.h @@ -0,0 +1,1448 @@ +#pragma once + +// Generated by grammar/asdl_cpp.py + +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace LCompilers::ASR { +/******************************************************************************/ +// Walk Visitor base class + +template +class BaseWalkVisitor : public BaseVisitor +{ +private: + StructType& self() { return static_cast(*this); } +public: + bool visit_compile_time_value = true; + void visit_TranslationUnit(const TranslationUnit_t &x) { + for (auto &a : x.m_symtab->get_scope()) { + this->visit_symbol(*a.second); + } + } + void visit_Program(const Program_t &x) { + for (auto &a : x.m_symtab->get_scope()) { + this->visit_symbol(*a.second); + } + for (size_t i=0; iget_scope()) { + this->visit_symbol(*a.second); + } + } + void visit_Function(const Function_t &x) { + for (auto &a : x.m_symtab->get_scope()) { + this->visit_symbol(*a.second); + } + self().visit_ttype(*x.m_function_signature); + for (size_t i=0; iget_scope()) { + this->visit_symbol(*a.second); + } + for (size_t i=0; iget_scope()) { + this->visit_symbol(*a.second); + } + self().visit_ttype(*x.m_type); + } + void visit_Union(const Union_t &x) { + for (auto &a : x.m_symtab->get_scope()) { + this->visit_symbol(*a.second); + } + for (size_t i=0; iget_scope()) { + this->visit_symbol(*a.second); + } + } + void visit_ClassProcedure(const ClassProcedure_t &x) { + if ((bool&)x) { } // Suppress unused warning + } + void visit_AssociateBlock(const AssociateBlock_t &x) { + for (auto &a : x.m_symtab->get_scope()) { + this->visit_symbol(*a.second); + } + for (size_t i=0; iget_scope()) { + this->visit_symbol(*a.second); + } + for (size_t i=0; iget_scope()) { + this->visit_symbol(*a.second); + } + for (size_t i=0; iget_scope()) { + this->visit_symbol(*a.second); + } + for (size_t i=0; i #include +#include #include namespace LCompilers { +std::string static inline uint16_to_string(uint16_t i) { + char bytes[2]; + bytes[0] = (i >> 8) & 0xFF; + bytes[1] = i & 0xFF; + return std::string(bytes, 2); +} + std::string static inline uint32_to_string(uint32_t i) { char bytes[4]; bytes[0] = (i >> 24) & 0xFF; @@ -30,6 +38,27 @@ std::string static inline uint64_to_string(uint64_t i) { return std::string(bytes, 8); } +std::string static inline uintptr_to_string(uintptr_t i) { + char bytes[8]; + bytes[0] = (i >> 56) & 0xFF; + bytes[1] = (i >> 48) & 0xFF; + bytes[2] = (i >> 40) & 0xFF; + bytes[3] = (i >> 32) & 0xFF; + bytes[4] = (i >> 24) & 0xFF; + bytes[5] = (i >> 16) & 0xFF; + bytes[6] = (i >> 8) & 0xFF; + bytes[7] = i & 0xFF; + return std::string(bytes, 8); +} + +uint16_t static inline string_to_uint16(const char *s) { + // The cast from signed char to unsigned char is important, + // otherwise the signed char shifts return wrong value for negative numbers + const uint8_t *p = (const unsigned char*)s; + return (((uint16_t)p[0]) << 8) | + p[1]; +} + uint32_t static inline string_to_uint32(const char *s) { // The cast from signed char to unsigned char is important, // otherwise the signed char shifts return wrong value for negative numbers @@ -54,6 +83,25 @@ uint64_t static inline string_to_uint64(const char *s) { p[7]; } + +uintptr_t static inline string_to_uintptr(const char *s) { + // The cast from signed char to unsigned char is important, + // otherwise the signed char shifts return wrong value for negative numbers + const uint8_t *p = (const unsigned char*)s; + return (((uintptr_t)p[0]) << 56) | + (((uintptr_t)p[1]) << 48) | + (((uintptr_t)p[2]) << 40) | + (((uintptr_t)p[3]) << 32) | + (((uintptr_t)p[4]) << 24) | + (((uintptr_t)p[5]) << 16) | + (((uintptr_t)p[6]) << 8) | + p[7]; +} + +uint16_t static inline string_to_uint16(const std::string &s) { + return string_to_uint16(&s[0]); +} + uint32_t static inline string_to_uint32(const std::string &s) { return string_to_uint32(&s[0]); } @@ -62,6 +110,14 @@ uint64_t static inline string_to_uint64(const std::string &s) { return string_to_uint64(&s[0]); } +uintptr_t static inline string_to_uintptr(const std::string &s) { + return string_to_uintptr(&s[0]); +} + +static inline void* string_to_void(const char *s) { + return (void*)string_to_uintptr(s); +} + // BinaryReader / BinaryWriter encapsulate access to the file by providing // primitives that other classes just use. class BinaryWriter @@ -78,6 +134,10 @@ class BinaryWriter s.append(std::string(&c, 1)); } + void write_int16(uint16_t i) { + s.append(uint16_to_string(i)); + } + void write_int32(uint32_t i) { s.append(uint32_to_string(i)); } @@ -97,6 +157,17 @@ class BinaryWriter write_int64(*ip); } + void write_uintptr(uintptr_t i) { + s.append(uintptr_to_string(i)); + } + + void write_void(void *p, int64_t n_data) { + for (int64_t i = 0; i < n_data; i++) { + uint8_t* p_i8 = (uint8_t*)p; + write_int8(p_i8[i]); + } + } + }; class BinaryReader @@ -116,6 +187,15 @@ class BinaryReader return n; } + uint16_t read_int16() { + if (pos+2 > s.size()) { + throw LCompilersException("read_int16: String is too short for deserialization."); + } + uint16_t n = string_to_uint16(&s[pos]); + pos += 2; + return n; + } + uint32_t read_int32() { if (pos+4 > s.size()) { throw LCompilersException("read_int32: String is too short for deserialization."); @@ -151,6 +231,20 @@ class BinaryReader double *dp = (double*)p; return *dp; } + + void* read_void(int64_t n_data) { + void *p = new char[n_data]; + + for (int64_t i = 0; i < n_data; i++) { + uint8_t x = read_int8(); + uint8_t *ip = &x; + void *p_i = (void*)((uintptr_t)p + i); + uint8_t *p_i_8 = (uint8_t*)p_i; + *p_i_8 = *ip; + } + + return p; + } }; // TextReader / TextWriter encapsulate access to the file by providing @@ -170,6 +264,16 @@ class TextWriter s += " "; } + void write_int16(uint16_t i) { + s.append(std::to_string(i)); + s += " "; + } + + void write_int32(uint32_t i) { + s.append(std::to_string(i)); + s += " "; + } + void write_int64(uint64_t i) { s.append(std::to_string(i)); s += " "; @@ -187,6 +291,19 @@ class TextWriter s.append(str.str()); s += " "; } + + void write_uintptr(uintptr_t i) { + s.append(uintptr_to_string(i)); + s += " "; + } + + void write_void(void *p, int64_t n_data) { + for (int64_t i = 0; i < n_data; i++) { + uint8_t* p_i8 = (uint8_t*)p; + write_int8(p_i8[i]); + } + } + }; class TextReader @@ -206,6 +323,24 @@ class TextReader } } + uint16_t read_int16() { + uint64_t n = read_int64(); + if (n < 65535) { + return n; + } else { + throw LCompilersException("read_int16: Integer too large to fit 16 bits."); + } + } + + uint32_t read_int32() { + uint64_t n = read_int64(); + if (n < 4294967295) { + return n; + } else { + throw LCompilersException("read_int32: Integer too large to fit 32 bits."); + } + } + uint64_t read_int64() { std::string tmp; while (s[pos] != ' ') { @@ -250,6 +385,20 @@ class TextReader pos ++; return r; } + + void* read_void(int64_t n_data) { + void *p = new char[n_data]; + + for (int64_t i = 0; i < n_data; i++) { + uint8_t x = read_int8(); + uint8_t *ip = &x; + void *p_i = (void*)((uintptr_t)p + i); + uint8_t *p_i_8 = (uint8_t*)p_i; + *p_i_8 = *ip; + } + + return p; + } }; } // namespace LCompilers diff --git a/src/libasr/casting_utils.cpp b/src/libasr/casting_utils.cpp index 68e3971839..45ab744304 100644 --- a/src/libasr/casting_utils.cpp +++ b/src/libasr/casting_utils.cpp @@ -41,8 +41,7 @@ namespace LCompilers::CastingUtil { {ASR::ttypeType::Complex, ASR::cast_kindType::ComplexToComplex}, {ASR::ttypeType::Real, ASR::cast_kindType::RealToReal}, {ASR::ttypeType::Integer, ASR::cast_kindType::IntegerToInteger}, - {ASR::ttypeType::UnsignedInteger, ASR::cast_kindType::UnsignedIntegerToUnsignedInteger}, - {ASR::ttypeType::StructType, ASR::cast_kindType::DerivedToBase} + {ASR::ttypeType::UnsignedInteger, ASR::cast_kindType::UnsignedIntegerToUnsignedInteger} }; int get_type_priority(ASR::ttypeType type) { diff --git a/src/libasr/codegen/KaleidoscopeJIT.h b/src/libasr/codegen/KaleidoscopeJIT.h index df83c850d2..250dd3dfce 100644 --- a/src/libasr/codegen/KaleidoscopeJIT.h +++ b/src/libasr/codegen/KaleidoscopeJIT.h @@ -108,9 +108,14 @@ class KaleidoscopeJIT { return res; } +#if LLVM_VERSION_MAJOR < 17 Expected lookup(StringRef Name) { +#else + Expected lookup(StringRef Name) { +#endif return ES->lookup({&JITDL}, Mangle(Name.str())); } + }; } // end namespace orc diff --git a/src/libasr/codegen/asr_to_c.cpp b/src/libasr/codegen/asr_to_c.cpp index ca0178ac89..5c80ceec8e 100644 --- a/src/libasr/codegen/asr_to_c.cpp +++ b/src/libasr/codegen/asr_to_c.cpp @@ -1,4 +1,3 @@ -#include #include #include @@ -153,7 +152,7 @@ class ASRToCVisitor : public BaseCCPPVisitor std::string indent, std::string name) { for( auto itr: der_type_t->m_symtab->get_scope() ) { ASR::symbol_t *sym = ASRUtils::symbol_get_past_external(itr.second); - if( ASR::is_a(*sym) || + if( ASR::is_a(*sym) || ASR::is_a(*sym) ) { continue ; } @@ -388,7 +387,7 @@ class ASRToCVisitor : public BaseCCPPVisitor sub = format_type_c("", "void**", v.m_name, false, false); } else { diag.codegen_error_label("Type number '" - + std::to_string(t2->type) + + ASRUtils::type_to_str_python(t2) + "' not supported", {v.base.base.loc}, ""); throw Abort(); } @@ -492,9 +491,9 @@ class ASRToCVisitor : public BaseCCPPVisitor sub = format_type_c(dims, "struct " + der_type_name + ptr_char, v.m_name, use_ref, dummy); } - } else if (ASR::is_a(*v_m_type)) { + } else if (ASR::is_a(*v_m_type)) { std::string indent(indentation_level*indentation_spaces, ' '); - ASR::Union_t *t = ASR::down_cast(v_m_type); + ASR::UnionType_t *t = ASR::down_cast(v_m_type); std::string der_type_name = ASRUtils::symbol_name( ASRUtils::symbol_get_past_external(t->m_union_type)); if( is_array ) { @@ -543,16 +542,16 @@ class ASRToCVisitor : public BaseCCPPVisitor false, false); } else if (ASR::is_a(*v_m_type)) { sub = format_type_c("", "void*", v.m_name, false, false); - } else if (ASR::is_a(*v_m_type)) { - ASR::Enum_t* enum_ = ASR::down_cast(v_m_type); - ASR::EnumType_t* enum_type = ASR::down_cast(enum_->m_enum_type); + } else if (ASR::is_a(*v_m_type)) { + ASR::EnumType_t* enum_ = ASR::down_cast(v_m_type); + ASR::Enum_t* enum_type = ASR::down_cast(enum_->m_enum_type); sub = format_type_c("", "enum " + std::string(enum_type->m_name), v.m_name, false, false); } else if (ASR::is_a(*v_m_type)) { // Ignore type variables return ""; } else { diag.codegen_error_label("Type number '" - + std::to_string(v_m_type->type) + + ASRUtils::type_to_str_python(v_m_type) + "' not supported", {v.base.base.loc}, ""); throw Abort(); } @@ -632,8 +631,8 @@ R"( std::map> struct_dep_graph; for (auto &item : x.m_symtab->get_scope()) { if (ASR::is_a(*item.second) || - ASR::is_a(*item.second) || - ASR::is_a(*item.second)) { + ASR::is_a(*item.second) || + ASR::is_a(*item.second)) { std::vector struct_deps_vec; std::pair struct_deps_ptr = ASRUtils::symbol_dependencies(item.second); for( size_t i = 0; i < struct_deps_ptr.second; i++ ) { @@ -754,8 +753,8 @@ R"( std::map> struct_dep_graph; for (auto &item : x.m_symtab->get_scope()) { if (ASR::is_a(*item.second) || - ASR::is_a(*item.second) || - ASR::is_a(*item.second)) { + ASR::is_a(*item.second) || + ASR::is_a(*item.second)) { std::vector struct_deps_vec; std::pair struct_deps_ptr = ASRUtils::symbol_dependencies(item.second); for( size_t i = 0; i < struct_deps_ptr.second; i++ ) { @@ -820,7 +819,7 @@ R"( } std::string body; - if (compiler_options.po.enable_cpython) { + if (compiler_options.enable_cpython) { headers.insert("Python.h"); body += R"( Py_Initialize(); @@ -851,7 +850,7 @@ R"( // Initialise Numpy body += src; } - if (compiler_options.po.enable_cpython) { + if (compiler_options.enable_cpython) { body += R"( if (Py_FinalizeEx() < 0) { fprintf(stderr,"BindPython: Unknown Error\n"); @@ -875,8 +874,8 @@ R"( // Initialise Numpy std::string body = ""; int indendation_level_copy = indentation_level; for( auto itr: x.m_symtab->get_scope() ) { - if( ASR::is_a(*itr.second) ) { - visit_AggregateTypeUtil(*ASR::down_cast(itr.second), + if( ASR::is_a(*itr.second) ) { + visit_AggregateTypeUtil(*ASR::down_cast(itr.second), "union", src_dest); } else if( ASR::is_a(*itr.second) ) { std::string struct_c_type_name = get_StructTypeCTypeName( @@ -933,18 +932,18 @@ R"( // Initialise Numpy src = ""; } - void visit_UnionType(const ASR::UnionType_t& x) { + void visit_Union(const ASR::Union_t& x) { visit_AggregateTypeUtil(x, "union", array_types_decls); } - void visit_EnumType(const ASR::EnumType_t& x) { + void visit_Enum(const ASR::Enum_t& x) { if( x.m_enum_value_type == ASR::enumtypeType::NonInteger ) { - throw CodeGenError("C backend only supports integer valued Enum. " + + throw CodeGenError("C backend only supports integer valued EnumType. " + std::string(x.m_name) + " is not integer valued."); } if( x.m_enum_value_type == ASR::enumtypeType::IntegerNotUnique ) { - throw CodeGenError("C backend only supports uniquely valued integer Enum. " + - std::string(x.m_name) + " Enum is having duplicate values for its members."); + throw CodeGenError("C backend only supports uniquely valued integer EnumType. " + + std::string(x.m_name) + " EnumType is having duplicate values for its members."); } if( x.m_enum_value_type == ASR::enumtypeType::IntegerUnique && x.m_abi == ASR::abiType::BindC ) { @@ -997,15 +996,15 @@ R"( // Initialise Numpy src = ""; } - void visit_EnumTypeConstructor(const ASR::EnumTypeConstructor_t& x) { + void visit_EnumConstructor(const ASR::EnumConstructor_t& x) { LCOMPILERS_ASSERT(x.n_args == 1); ASR::expr_t* m_arg = x.m_args[0]; this->visit_expr(*m_arg); - ASR::EnumType_t* enum_type = ASR::down_cast(x.m_dt_sym); + ASR::Enum_t* enum_type = ASR::down_cast(x.m_dt_sym); src = "(enum " + std::string(enum_type->m_name) + ") (" + src + ")"; } - void visit_UnionTypeConstructor(const ASR::UnionTypeConstructor_t& /*x*/) { + void visit_UnionConstructor(const ASR::UnionConstructor_t& /*x*/) { } @@ -1023,8 +1022,8 @@ R"( // Initialise Numpy void visit_EnumName(const ASR::EnumName_t& x) { CHECK_FAST_C(compiler_options, x) int64_t min_value = INT64_MAX; - ASR::Enum_t* enum_t = ASR::down_cast(x.m_enum_type); - ASR::EnumType_t* enum_type = ASR::down_cast(enum_t->m_enum_type); + ASR::EnumType_t* enum_t = ASR::down_cast(x.m_enum_type); + ASR::Enum_t* enum_type = ASR::down_cast(enum_t->m_enum_type); for( auto itr: enum_type->m_symtab->get_scope() ) { ASR::Variable_t* itr_var = ASR::down_cast(itr.second); ASR::expr_t* value = ASRUtils::expr_value(itr_var->m_symbolic_value); @@ -1118,8 +1117,7 @@ R"( // Initialise Numpy for (int i = n_dims - 1; i >= 0; i--) { std::string start = "0", length = "0"; if( lower_bounds ) { - visit_expr(*lower_bounds->m_args[i]); - start = src; + start = ASRUtils::fetch_ArrayConstant_value(lower_bounds, i); } if( m_dims[i].m_length ) { this->visit_expr(*m_dims[i].m_length); @@ -1147,15 +1145,26 @@ R"( // Initialise Numpy bracket_open++; std::vector v; std::string separator; - if (x.m_separator) { - this->visit_expr(*x.m_separator); - separator = src; + separator = "\" \""; + //HACKISH way to handle print refactoring (always using stringformat). + // TODO : Implement stringformat visitor. + ASR::StringFormat_t* str_fmt; + size_t n_values = 0; + if(ASR::is_a(*x.m_text)){ + str_fmt = ASR::down_cast(x.m_text); + n_values = str_fmt->n_args; + } else if (ASR::is_a(*ASRUtils::expr_type(x.m_text))) { + this->visit_expr(*x.m_text); + src = indent + "printf(\"%s\\n\"," + src + ");\n"; + return; } else { - separator = "\" \""; + throw CodeGenError("print statment supported for stringformat and single character argument", + x.base.base.loc); } - for (size_t i=0; ivisit_expr(*x.m_values[i]); - ASR::ttype_t* value_type = ASRUtils::expr_type(x.m_values[i]); + + for (size_t i=0; ivisit_expr(*(str_fmt->m_args[i])); + ASR::ttype_t* value_type = ASRUtils::expr_type(str_fmt->m_args[i]); if( ASRUtils::is_array(value_type) ) { src += "->data"; } @@ -1175,25 +1184,19 @@ R"( // Initialise Numpy out += indent + p_func + "(" + src + ");\n"; continue; } - tmp_gen += c_ds_api->get_print_type(value_type, ASR::is_a(*x.m_values[i])); + tmp_gen +=c_ds_api->get_print_type(value_type, ASR::is_a(*(str_fmt->m_args[i]))); v.push_back(src); if (ASR::is_a(*value_type)) { v.pop_back(); v.push_back("creal(" + src + ")"); v.push_back("cimag(" + src + ")"); } - if (i+1!=x.n_values) { + if (i+1!=n_values) { tmp_gen += "\%s"; v.push_back(separator); } } - if (x.m_end) { - this->visit_expr(*x.m_end); - tmp_gen += "\%s\""; - v.push_back(src); - } else { - tmp_gen += "\\n\""; - } + tmp_gen += "\\n\""; if (!v.empty()) { for (auto &s: v) { tmp_gen += ", " + s; @@ -1296,9 +1299,8 @@ R"( // Initialise Numpy // TODO: Support and test for multi-dimensional array constants headers.insert("stdarg.h"); std::string array_const = ""; - for( size_t i = 0; i < x.n_args; i++ ) { - visit_expr(*x.m_args[i]); - array_const += src + ", "; + for( size_t i = 0; i < (size_t) ASRUtils::get_fixed_size_of_array(x.m_type); i++ ) { + array_const += ASRUtils::fetch_ArrayConstant_value(x, i) + ", "; } array_const.pop_back(); array_const.pop_back(); @@ -1309,7 +1311,7 @@ R"( // Initialise Numpy std::string return_type = c_ds_api->get_array_type(array_type_name, array_encoded_type_name,array_types_decls, false); src = c_utils_functions->get_array_constant(return_type, array_type_name, array_encoded_type_name) + - "(" + std::to_string(x.n_args) + ", " + array_const + ")"; + "(" + std::to_string(ASRUtils::get_fixed_size_of_array(x.m_type)) + ", " + array_const + ")"; } void visit_ArrayItem(const ASR::ArrayItem_t &x) { diff --git a/src/libasr/codegen/asr_to_c_cpp.h b/src/libasr/codegen/asr_to_c_cpp.h index a36fcff862..9e0a01829b 100644 --- a/src/libasr/codegen/asr_to_c_cpp.h +++ b/src/libasr/codegen/asr_to_c_cpp.h @@ -11,7 +11,6 @@ * for both C and C++ code generation. */ -#include #include #include @@ -28,7 +27,6 @@ #include -#include #define CHECK_FAST_C_CPP(compiler_options, x) \ if (compiler_options.po.fast && x.m_value != nullptr) { \ @@ -565,7 +563,6 @@ R"(#include if( is_c ) { CDeclarationOptions c_decl_options; c_decl_options.pre_initialise_derived_type = false; - c_decl_options.do_not_initialize = true; func += self().convert_variable_decl(*arg, &c_decl_options); } else { CPPDeclarationOptions cpp_decl_options; @@ -1069,11 +1066,13 @@ PyMODINIT_FUNC PyInit_lpython_module_)" + fn_name + R"((void) { bracket_open++; std::string args = ""; for (size_t i=0; i(*m_args[i].m_value) && - ASR::is_a( - *(ASR::down_cast(m_args[i].m_value)->m_v))) { + ASR::expr_t* call_arg = m_args[i].m_value; + self().visit_expr(*call_arg); + ASR::ttype_t* type = ASRUtils::expr_type(call_arg); + if (ASR::is_a(*call_arg) + && ASR::is_a( + *ASRUtils::symbol_get_past_external( + ASR::down_cast(m_args[i].m_value)->m_v))) { ASR::Variable_t* param = ASRUtils::EXPR2VAR(f->m_args[i]); if( (is_c && (param->m_intent == ASRUtils::intent_inout || param->m_intent == ASRUtils::intent_out) @@ -1091,7 +1090,7 @@ PyMODINIT_FUNC PyInit_lpython_module_)" + fn_name + R"((void) { } else { args += src; } - } else if (ASR::is_a(*m_args[i].m_value)) { + } else if (ASR::is_a(*call_arg)) { ASR::Variable_t* param = ASRUtils::EXPR2VAR(f->m_args[i]); if (param->m_intent == ASRUtils::intent_inout || param->m_intent == ASRUtils::intent_out || ASR::is_a(*type)) { @@ -1244,15 +1243,6 @@ PyMODINIT_FUNC PyInit_lpython_module_)" + fn_name + R"((void) { src = "_lfortran_strrepeat_c(" + s + ", " + n + ")"; } - void visit_StringContains(const ASR::StringContains_t &x) { - CHECK_FAST_C_CPP(compiler_options, x) - self().visit_expr(*x.m_substr); - std::string substr = src; - self().visit_expr(*x.m_str); - std::string str = src; - src = "_lfortran_str_contains(" + str + ", " + substr + ")"; - } - void visit_Assignment(const ASR::Assignment_t &x) { std::string target; ASR::ttype_t* m_target_type = ASRUtils::expr_type(x.m_target); @@ -1356,7 +1346,7 @@ PyMODINIT_FUNC PyInit_lpython_module_)" + fn_name + R"((void) { LCOMPILERS_ASSERT(false) } from_std_vector_helper.clear(); - if( ASR::is_a(*x.m_value) ) { + if( ASR::is_a(*x.m_value) ) { src = ""; return ; } @@ -1563,7 +1553,7 @@ PyMODINIT_FUNC PyInit_lpython_module_)" + fn_name + R"((void) { std::string stride = "1"; for( int i = value_rank - 1; i >= 0; i-- ) { if( ds[i] != "" ) { - std::string dim_length = "(((" + ubs[i] + " - " + lbs[i] + ")" + "/" + ds[i] + ") + 1)"; + std::string dim_length = "((( (" + ubs[i] + ") - (" + lbs[i] + ") )" + "/" + ds[i] + ") + 1)"; std::string target_dim_des = target_dim_des_array + "[" + std::to_string(j) + "]"; update_target_desc += indent + target_dim_des + ".stride = " + stride + ";\n"; update_target_desc += indent + target_dim_des + ".lower_bound = 1;\n"; @@ -1694,7 +1684,7 @@ PyMODINIT_FUNC PyInit_lpython_module_)" + fn_name + R"((void) { std::to_string(x.n_args) + ");\n"; for( size_t i = 0; i < x.n_args; i++ ) { self().visit_expr(*x.m_args[i]); - if( ASR::is_a(*t->m_type) ) { + if( ASR::is_a(*t->m_type) ) { src_tmp += indent + var_name + ".data[" + std::to_string(i) +"] = NULL;\n"; } src_tmp += indent + c_ds_api->get_deepcopy(t->m_type, src, @@ -1720,7 +1710,7 @@ PyMODINIT_FUNC PyInit_lpython_module_)" + fn_name + R"((void) { for (size_t i = 0; i < x.n_elements; i++) { self().visit_expr(*x.m_elements[i]); std::string ele = ".element_" + std::to_string(i); - if (ASR::is_a(*t->m_type[i])) { + if (ASR::is_a(*t->m_type[i])) { src_tmp += indent + var_name + ele + " = NULL;\n"; } src_tmp += indent + c_ds_api->get_deepcopy(t->m_type[i], src, var_name + ele) + "\n"; @@ -2180,7 +2170,7 @@ PyMODINIT_FUNC PyInit_lpython_module_)" + fn_name + R"((void) { last_expr_precedence = 2; break; } - case (ASR::cast_kindType::LogicalToCharacter) : { + case (ASR::cast_kindType::LogicalToString) : { src = "(" + src + " ? \"True\" : \"False\")"; last_expr_precedence = 2; break; @@ -2206,7 +2196,7 @@ PyMODINIT_FUNC PyInit_lpython_module_)" + fn_name + R"((void) { last_expr_precedence = 2; break; } - case (ASR::cast_kindType::CharacterToLogical) : { + case (ASR::cast_kindType::StringToLogical) : { src = "(bool)(strlen(" + src + ") > 0)"; last_expr_precedence = 2; break; @@ -2216,7 +2206,7 @@ PyMODINIT_FUNC PyInit_lpython_module_)" + fn_name + R"((void) { last_expr_precedence = 2; break; } - case (ASR::cast_kindType::IntegerToCharacter) : { + case (ASR::cast_kindType::IntegerToString) : { if (is_c) { ASR::ttype_t *arg_type = ASRUtils::expr_type(x.m_arg); int arg_kind = ASRUtils::extract_kind_from_ttype_t(arg_type); @@ -2225,7 +2215,7 @@ PyMODINIT_FUNC PyInit_lpython_module_)" + fn_name + R"((void) { case 2: src = "_lfortran_int_to_str2(" + src + ")"; break; case 4: src = "_lfortran_int_to_str4(" + src + ")"; break; case 8: src = "_lfortran_int_to_str8(" + src + ")"; break; - default: throw CodeGenError("Cast IntegerToCharacter: Unsupported Kind " + \ + default: throw CodeGenError("Cast IntegerToString: Unsupported Kind " + \ std::to_string(arg_kind)); } @@ -2235,7 +2225,7 @@ PyMODINIT_FUNC PyInit_lpython_module_)" + fn_name + R"((void) { last_expr_precedence = 2; break; } - case (ASR::cast_kindType::CharacterToInteger) : { + case (ASR::cast_kindType::StringToInteger) : { if (is_c) { src = "atoi(" + src + ")"; } else { @@ -2244,14 +2234,14 @@ PyMODINIT_FUNC PyInit_lpython_module_)" + fn_name + R"((void) { last_expr_precedence = 2; break; } - case (ASR::cast_kindType::RealToCharacter) : { + case (ASR::cast_kindType::RealToString) : { if (is_c) { ASR::ttype_t *arg_type = ASRUtils::expr_type(x.m_arg); int arg_kind = ASRUtils::extract_kind_from_ttype_t(arg_type); switch (arg_kind) { case 4: src = "_lfortran_float_to_str4(" + src + ")"; break; case 8: src = "_lfortran_float_to_str8(" + src + ")"; break; - default: throw CodeGenError("Cast RealToCharacter: Unsupported Kind " + \ + default: throw CodeGenError("Cast RealToString: Unsupported Kind " + \ std::to_string(arg_kind)); } } else { @@ -2618,7 +2608,7 @@ PyMODINIT_FUNC PyInit_lpython_module_)" + fn_name + R"((void) { type = ASRUtils::expr_type(tmp_expr); } else { throw CodeGenError("Cannot deallocate variables in expression " + - std::to_string(tmp_expr->type), + ASRUtils::type_to_str_python(ASRUtils::expr_type(tmp_expr)), tmp_expr->base.loc); } std::string sym = ASRUtils::symbol_name(tmp_sym); @@ -2703,7 +2693,7 @@ PyMODINIT_FUNC PyInit_lpython_module_)" + fn_name + R"((void) { tmp_sym = tmp_var->m_v; } else { throw CodeGenError("Cannot deallocate variables in expression " + - std::to_string(tmp_expr->type), + ASRUtils::type_to_str_python(ASRUtils::expr_type(tmp_expr)), tmp_expr->base.loc); } out += std::string(ASRUtils::symbol_name(tmp_sym)) + ", "; @@ -2723,7 +2713,7 @@ PyMODINIT_FUNC PyInit_lpython_module_)" + fn_name + R"((void) { tmp_sym = tmp_var->m_v; } else { throw CodeGenError("Cannot deallocate variables in expression " + - std::to_string(tmp_expr->type), + ASRUtils::type_to_str_python(ASRUtils::expr_type(tmp_expr)), tmp_expr->base.loc); } out += std::string(ASRUtils::symbol_name(tmp_sym)) + ", "; @@ -3069,6 +3059,8 @@ PyMODINIT_FUNC PyInit_lpython_module_)" + fn_name + R"((void) { SET_INTRINSIC_NAME(StringContainsSet, "verify"); SET_INTRINSIC_NAME(StringFindSet, "scan"); SET_INTRINSIC_NAME(SubstrIndex, "index"); + SET_INTRINSIC_NAME(StringLenTrim, "len_trim"); + SET_INTRINSIC_NAME(StringTrim, "trim"); case (static_cast(ASRUtils::IntrinsicElementalFunctions::FMA)) : { this->visit_expr(*x.m_args[0]); std::string a = src; diff --git a/src/libasr/codegen/asr_to_cpp.cpp b/src/libasr/codegen/asr_to_cpp.cpp index 4c50fed4bd..3d4cd53bf9 100644 --- a/src/libasr/codegen/asr_to_cpp.cpp +++ b/src/libasr/codegen/asr_to_cpp.cpp @@ -1,4 +1,3 @@ -#include #include #include @@ -260,7 +259,7 @@ class ASRToCPPVisitor : public BaseCCPPVisitor handle_array(t2, type_name, true) } else { diag.codegen_error_label("Type number '" - + std::to_string(v.m_type->type) + + ASRUtils::type_to_str_python(v.m_type) + "' not supported", {v.base.base.loc}, ""); throw Abort(); } @@ -307,7 +306,7 @@ class ASRToCPPVisitor : public BaseCCPPVisitor false, false); } else { diag.codegen_error_label("Type number '" - + std::to_string(v.m_type->type) + + ASRUtils::type_to_str_python(v.m_type) + "' not supported", {v.base.base.loc}, ""); throw Abort(); } @@ -537,10 +536,9 @@ Kokkos::View from_std_vector(const std::vector &v) std::string indent(indentation_level * indentation_spaces, ' '); from_std_vector_helper = indent + "Kokkos::View r;\n"; std::string out = "from_std_vector({"; - for (size_t i=0; ivisit_expr(*x.m_args[i]); - out += src; - if (i < x.n_args-1) out += ", "; + for (size_t i=0; i<(size_t) ASRUtils::get_fixed_size_of_array(x.m_type); i++) { + out += ASRUtils::fetch_ArrayConstant_value(x, i); + if (i < (size_t) ASRUtils::get_fixed_size_of_array(x.m_type)-1) out += ", "; } out += "})"; from_std_vector_helper += indent + "r = " + out + ";\n"; @@ -603,33 +601,46 @@ Kokkos::View from_std_vector(const std::vector &v) void visit_Print(const ASR::Print_t &x) { std::string indent(indentation_level*indentation_spaces, ' '); std::string out = indent + "std::cout ", sep; - if (x.m_separator) { - this->visit_expr(*x.m_separator); - sep = src; + //HACKISH way to handle print refactoring (always using stringformat). + // TODO : Implement stringformat visitor. + ASR::StringFormat_t* str_fmt; + size_t n_values = 0; + sep = "\" \""; + if(ASR::is_a(*x.m_text)) { + str_fmt = ASR::down_cast(x.m_text); + n_values = str_fmt->n_args; + } else if(ASR::is_a(*ASRUtils::expr_type(x.m_text))){ + this->visit_expr(*x.m_text); + src = "std::cout<< " + src + "<visit_expr(*x.m_values[i]); + for (size_t i=0; ivisit_expr(*(str_fmt->m_args[i])); out += "<< " + src + " "; - if (i+1 != x.n_values) { + if (i+1 != n_values) { out += "<< " + sep + " "; } } - if (x.m_end) { - this->visit_expr(*x.m_end); - out += "<< " + src + ";\n"; - } else { - out += "<< std::endl;\n"; - } + out += "<< std::endl;\n"; src = out; } void visit_FileWrite(const ASR::FileWrite_t &x) { std::string indent(indentation_level*indentation_spaces, ' '); std::string out = indent + "std::cout "; - for (size_t i=0; ivisit_expr(*x.m_values[i]); + //HACKISH way to handle print refactoring (always using stringformat). + // TODO : Implement stringformat visitor. + ASR::StringFormat_t* str_fmt = nullptr; + size_t n_values = x.n_values; + if(x.m_values[0] && ASR::is_a(*x.m_values[0])) { + str_fmt = ASR::down_cast(x.m_values[0]); + n_values = str_fmt->n_args; + } + for (size_t i=0; ivisit_expr(*(str_fmt->m_args[i])): this->visit_expr(*x.m_values[i]); out += "<< " + src + " "; } out += "<< std::endl;\n"; @@ -651,11 +662,12 @@ Kokkos::View from_std_vector(const std::vector &v) std::string indent(indentation_level*indentation_spaces, ' '); std::string out = indent + "Kokkos::parallel_for("; out += "Kokkos::RangePolicy("; - visit_expr(*x.m_head.m_start); + LCOMPILERS_ASSERT(x.n_head == 1); + visit_expr(*x.m_head[0].m_start); out += src + ", "; - visit_expr(*x.m_head.m_end); + visit_expr(*x.m_head[0].m_end); out += src + "+1)"; - ASR::Variable_t *loop_var = ASRUtils::EXPR2VAR(x.m_head.m_v); + ASR::Variable_t *loop_var = ASRUtils::EXPR2VAR(x.m_head[0].m_v); sym_info[get_hash((ASR::asr_t*) loop_var)].needs_declaration = false; out += ", KOKKOS_LAMBDA(const long " + std::string(loop_var->m_name) + ") {\n"; diff --git a/src/libasr/codegen/asr_to_fortran.cpp b/src/libasr/codegen/asr_to_fortran.cpp index 02cb20ad9b..b624df6fa9 100644 --- a/src/libasr/codegen/asr_to_fortran.cpp +++ b/src/libasr/codegen/asr_to_fortran.cpp @@ -7,6 +7,8 @@ using LCompilers::ASR::is_a; using LCompilers::ASR::down_cast; +Allocator al(8); + namespace LCompilers { enum Precedence { @@ -143,15 +145,20 @@ class ASRToFortranVisitor : public ASR::BaseVisitor } } - void handle_line_truncation(std::string &r, int i_level, int line_length=80) { - int line_segments_count = r.size()/line_length; - for (int i = 1; i <= line_segments_count; i ++) { - int index = r.find_last_of(',', line_length*i); - r.insert(index + 2, "&\n" + indent + - std::string(i_level*indent_spaces, ' ')); + void handle_line_truncation(std::string &r, int i_level, int line_length=120) { + size_t current_pos = 0; + std::string indent = std::string(i_level * indent_spaces, ' '); + while (current_pos + line_length < r.length()) { + size_t break_pos = r.find_last_of(',', current_pos + line_length); + if (break_pos == std::string::npos || break_pos <= current_pos) { + break_pos = current_pos + line_length - 1; + } + r.insert(break_pos + 1, "&\n" + indent); + current_pos = break_pos + 2 + i_level * indent_spaces; } } + std::string get_type(const ASR::ttype_t *t) { std::string r = ""; switch (t->type) { @@ -170,8 +177,8 @@ class ASRToFortranVisitor : public ASR::BaseVisitor r += std::to_string(down_cast(t)->m_kind); r += ")"; break; - } case ASR::ttypeType::Character: { - ASR::Character_t *c = down_cast(t); + } case ASR::ttypeType::String: { + ASR::String_t *c = down_cast(t); r = "character(len="; if(c->m_len > 0) { r += std::to_string(c->m_len); @@ -239,6 +246,9 @@ class ASRToFortranVisitor : public ASR::BaseVisitor import_struct_type.push_back(struct_name); } break; + } case ASR::ttypeType::CPtr: { + r = "type(c_ptr)"; + break; } default: throw LCompilersException("The type `" @@ -296,6 +306,7 @@ class ASRToFortranVisitor : public ASR::BaseVisitor r = "program"; r += " "; r.append(x.m_name); + handle_line_truncation(r, 2); r += "\n"; for (auto &item : x.m_symtab->get_scope()) { if (is_a(*item.second)) { @@ -308,8 +319,8 @@ class ASRToFortranVisitor : public ASR::BaseVisitor std::map> struct_dep_graph; for (auto &item : x.m_symtab->get_scope()) { if (ASR::is_a(*item.second) || - ASR::is_a(*item.second) || - ASR::is_a(*item.second)) { + ASR::is_a(*item.second) || + ASR::is_a(*item.second)) { std::vector struct_deps_vec; std::pair struct_deps_ptr = ASRUtils::symbol_dependencies(item.second); for( size_t i = 0; i < struct_deps_ptr.second; i++ ) { @@ -367,9 +378,13 @@ class ASRToFortranVisitor : public ASR::BaseVisitor void visit_Module(const ASR::Module_t &x) { std::string r; + if (strcmp(x.m_name,"lfortran_intrinsic_iso_c_binding")==0 && x.m_intrinsic) { + return; + } r = "module"; r += " "; r.append(x.m_name); + handle_line_truncation(r, 2); r += "\n"; for (auto &item : x.m_symtab->get_scope()) { if (is_a(*item.second)) { @@ -389,8 +404,8 @@ class ASRToFortranVisitor : public ASR::BaseVisitor std::map> struct_dep_graph; for (auto &item : x.m_symtab->get_scope()) { if (ASR::is_a(*item.second) || - ASR::is_a(*item.second) || - ASR::is_a(*item.second)) { + ASR::is_a(*item.second) || + ASR::is_a(*item.second)) { std::vector struct_deps_vec; std::pair struct_deps_ptr = ASRUtils::symbol_dependencies(item.second); for( size_t i = 0; i < struct_deps_ptr.second; i++ ) { @@ -507,6 +522,7 @@ class ASRToFortranVisitor : public ASR::BaseVisitor r += " result(" + return_var + ")"; } } + handle_line_truncation(r, 2); r += "\n"; inc_indent(); @@ -530,6 +546,7 @@ class ASRToFortranVisitor : public ASR::BaseVisitor if (i < import_struct_type.size() - 1) { r += ", "; } else { + handle_line_truncation(r, 2); r += "\n"; } } @@ -548,6 +565,7 @@ class ASRToFortranVisitor : public ASR::BaseVisitor inc_indent(); visit_symbol(*item.second); r += src; + handle_line_truncation(r, 2); r += "\n"; dec_indent(); r += indent; @@ -578,6 +596,7 @@ class ASRToFortranVisitor : public ASR::BaseVisitor std::string r = indent; r += "interface "; r.append(x.m_name); + handle_line_truncation(r, 2); r += "\n"; inc_indent(); r += indent; @@ -587,6 +606,7 @@ class ASRToFortranVisitor : public ASR::BaseVisitor if (i < x.n_procs-1) r += ", "; } dec_indent(); + handle_line_truncation(r, 2); r += "\n"; r += "end interface "; r.append(x.m_name); @@ -599,7 +619,17 @@ class ASRToFortranVisitor : public ASR::BaseVisitor void visit_ExternalSymbol(const ASR::ExternalSymbol_t &x) { ASR::symbol_t *sym = down_cast( ASRUtils::symbol_parent_symtab(x.m_external)->asr_owner); - if (!is_a(*sym)) { + if (strcmp(x.m_module_name,"lfortran_intrinsic_iso_c_binding")==0 && + sym && ASR::is_a(*sym) && ASR::down_cast(sym)->m_intrinsic) { + src = indent; + src += "use "; + src += "iso_c_binding"; + src += ", only: "; + src.append(x.m_original_name); + src += "\n"; + return; + } + if (!is_a(*sym) && !is_a(*sym)) { src = indent; src += "use "; src.append(x.m_module_name); @@ -613,6 +643,7 @@ class ASRToFortranVisitor : public ASR::BaseVisitor std::string r = indent; r += "type :: "; r.append(x.m_name); + handle_line_truncation(r, 2); r += "\n"; inc_indent(); std::vector var_order = ASRUtils::determine_variable_declaration_order(x.m_symtab); @@ -630,9 +661,27 @@ class ASRToFortranVisitor : public ASR::BaseVisitor src = r; } - // void visit_EnumType(const ASR::EnumType_t &x) {} + void visit_Enum(const ASR::Enum_t &x) { + std::string r = indent; + r += "enum, bind(c)\n"; + inc_indent(); + for (auto it: x.m_symtab->get_scope()) { + ASR::Variable_t* var = ASR::down_cast(it.second); + r += indent; + r += "enumerator :: "; + r.append(var->m_name); + r += " = "; + visit_expr(*var->m_value); + r += src; + r += "\n"; + } + dec_indent(); + r += indent; + r += "end enum\n"; + src = r; + } - // void visit_UnionType(const ASR::UnionType_t &x) {} + // void visit_Union(const ASR::Union_t &x) {} void visit_Variable(const ASR::Variable_t &x) { std::string r = indent; @@ -672,6 +721,9 @@ class ASRToFortranVisitor : public ASR::BaseVisitor if (x.m_value_attr) { r += ", value"; } + if (x.m_target_attr) { + r += ", target"; + } r += " :: "; r.append(x.m_name); if (x.m_symbolic_value && x.m_value && ASR::is_a(*x.m_symbolic_value) && ASR::is_a(*x.m_value)) { @@ -687,11 +739,12 @@ class ASRToFortranVisitor : public ASR::BaseVisitor visit_expr(*x.m_symbolic_value); r += src; } + handle_line_truncation(r, 2); r += "\n"; src = r; } - // void visit_ClassType(const ASR::ClassType_t &x) {} + // void visit_Class(const ASR::Class_t &x) {} // void visit_ClassProcedure(const ASR::ClassProcedure_t &x) {} @@ -721,7 +774,9 @@ class ASRToFortranVisitor : public ASR::BaseVisitor } if (i < x.n_args-1) r += ", "; } - r += ")\n"; + r += ")"; + handle_line_truncation(r, 2); + r += "\n"; src = r; } @@ -736,6 +791,7 @@ class ASRToFortranVisitor : public ASR::BaseVisitor r += "to"; r += " "; r += x.m_variable; + handle_line_truncation(r, 2); r += "\n"; src = r; } @@ -747,6 +803,7 @@ class ASRToFortranVisitor : public ASR::BaseVisitor r += " = "; visit_expr(*x.m_value); r += src; + handle_line_truncation(r, 2); r += "\n"; src = r; } @@ -776,6 +833,7 @@ class ASRToFortranVisitor : public ASR::BaseVisitor if (i < x.n_vars-1) r += ", "; } r += ")"; + handle_line_truncation(r, 2); r += "\n"; src = r; } @@ -793,7 +851,38 @@ class ASRToFortranVisitor : public ASR::BaseVisitor src = r; } - // void visit_DoConcurrentLoop(const ASR::DoConcurrentLoop_t &x) {} + void visit_DoConcurrentLoop(const ASR::DoConcurrentLoop_t &x) { + std::string r = indent; + + r += "do concurrent"; + r += " ( "; + for (size_t i = 0; i < x.n_head; i++) { + visit_expr(*x.m_head[i].m_v); + r += src; + r += " = "; + visit_expr(*x.m_head[i].m_start); + r += src; + r += ": "; + visit_expr(*x.m_head[i].m_end); + r += src; + if (x.m_head[i].m_increment) { + r += ":"; + visit_expr(*x.m_head[i].m_increment); + r += src; + } + if ( i < x.n_head - 1 ) { + r+=", "; + } + } + r+=" )"; + handle_line_truncation(r, 2); + r += "\n"; + visit_body(x, r); + r += indent; + r += "end do"; + r += "\n"; + src = r; + } void visit_DoLoop(const ASR::DoLoop_t &x) { std::string r = indent; @@ -816,6 +905,7 @@ class ASRToFortranVisitor : public ASR::BaseVisitor visit_expr(*x.m_head.m_increment); r += src; } + handle_line_truncation(r, 2); r += "\n"; visit_body(x, r); r += indent; @@ -848,6 +938,7 @@ class ASRToFortranVisitor : public ASR::BaseVisitor r += "go to"; r += " "; r += std::to_string(x.m_target_id); + handle_line_truncation(r, 2); r += "\n"; src = r; } @@ -857,6 +948,7 @@ class ASRToFortranVisitor : public ASR::BaseVisitor r += std::to_string(x.m_id); r += " "; r += "continue"; + handle_line_truncation(r, 2); r += "\n"; src = r; } @@ -869,15 +961,18 @@ class ASRToFortranVisitor : public ASR::BaseVisitor r += src; r += ") "; r += "then"; + handle_line_truncation(r, 2); r += "\n"; visit_body(x, r); - for (size_t i = 0; i < x.n_orelse; i++) { + if (x.n_orelse > 0) { r += indent; r += "else"; r += "\n"; inc_indent(); - visit_stmt(*x.m_orelse[i]); - r += src; + for (size_t i = 0; i < x.n_orelse; i++) { + visit_stmt(*x.m_orelse[i]); + r += src; + } dec_indent(); } r += indent; @@ -892,22 +987,33 @@ class ASRToFortranVisitor : public ASR::BaseVisitor std::string r = indent; r += "print"; r += " "; - if (x.n_values > 0 && is_a(*x.m_values[0])) { - ASR::StringFormat_t *sf = down_cast(x.m_values[0]); - visit_expr(*sf->m_fmt); - if (is_a(*sf->m_fmt) - && (!startswith(src, "\"(") || !endswith(src, ")\""))) { - src = "\"(" + src.substr(1, src.size()-2) + ")\""; + if (is_a(*x.m_text)) { + ASR::StringFormat_t *sf = down_cast(x.m_text); + if(sf->m_fmt){ + visit_expr(*(sf->m_fmt)); + if (is_a(*sf->m_fmt) + && (!startswith(src, "\"(") || !endswith(src, ")\""))) { + src = "\"(" + src.substr(1, src.size()-2) + ")\""; + } + r += src; + } else { + r += "*"; } - r += src; - } else { + for (size_t i = 0; i < sf->n_args; i++) { + r += ", "; + visit_expr(*sf->m_args[i]); + r += src; + } + } else if (ASR::is_a(*ASRUtils::expr_type(x.m_text))) { r += "*"; - } - for (size_t i = 0; i < x.n_values; i++) { r += ", "; - visit_expr(*x.m_values[i]); + visit_expr(*x.m_text); r += src; + } else { + throw CodeGenError("print statment supported for stringformat and single character argument", + x.base.base.loc); } + handle_line_truncation(r, 2); r += "\n"; src = r; } @@ -942,6 +1048,7 @@ class ASRToFortranVisitor : public ASR::BaseVisitor r += src; } r += ")"; + handle_line_truncation(r, 2); r += "\n"; src = r; } @@ -958,6 +1065,7 @@ class ASRToFortranVisitor : public ASR::BaseVisitor throw CodeGenError("close() function must be called with a file unit number"); } r += ")"; + handle_line_truncation(r, 2); r += "\n"; src = r; } @@ -1005,6 +1113,7 @@ class ASRToFortranVisitor : public ASR::BaseVisitor r += src; if (i < x.n_values - 1) r += ", "; } + handle_line_truncation(r, 2); r += "\n"; src = r; } @@ -1024,12 +1133,16 @@ class ASRToFortranVisitor : public ASR::BaseVisitor } if (x.n_values > 0 && is_a(*x.m_values[0])) { ASR::StringFormat_t *sf = down_cast(x.m_values[0]); - visit_expr(*sf->m_fmt); - if (is_a(*sf->m_fmt) - && (!startswith(src, "\"(") || !endswith(src, ")\""))) { - src = "\"(" + src.substr(1, src.size()-2) + ")\""; + if(sf->m_fmt){ + visit_expr(*sf->m_fmt); + if (is_a(*sf->m_fmt) + && (!startswith(src, "\"(") || !endswith(src, ")\""))) { + src = "\"(" + src.substr(1, src.size()-2) + ")\""; + } + r += src; + } else { + r += "*"; } - r += src; } else { r += "*"; } @@ -1039,6 +1152,7 @@ class ASRToFortranVisitor : public ASR::BaseVisitor r += src; if (i < x.n_values-1) r += ", "; } + handle_line_truncation(r, 2); r += "\n"; src = r; } @@ -1046,6 +1160,7 @@ class ASRToFortranVisitor : public ASR::BaseVisitor void visit_Return(const ASR::Return_t &/*x*/) { std::string r = indent; r += "return"; + handle_line_truncation(r, 2); r += "\n"; src = r; } @@ -1056,7 +1171,9 @@ class ASRToFortranVisitor : public ASR::BaseVisitor r += " ("; visit_expr(*x.m_test); r += src; - r += ")\n"; + r += ")"; + handle_line_truncation(r, 2); + r += "\n"; inc_indent(); if (x.n_body > 0) { for(size_t i = 0; i < x.n_body; i ++) { @@ -1099,8 +1216,10 @@ class ASRToFortranVisitor : public ASR::BaseVisitor r += src; if (i < x.n_args-1) r += ", "; } - r += ")\n"; - handle_line_truncation(r, 1); + + r += ")"; + handle_line_truncation(r, 2); + r += "\n"; src = r; } @@ -1112,11 +1231,14 @@ class ASRToFortranVisitor : public ASR::BaseVisitor r += "("; visit_expr(*x.m_test); r += src; - r += ")\n"; + r += ")"; + handle_line_truncation(r, 2); + r += "\n"; visit_body(x, r); for (size_t i = 0; i < x.n_orelse; i++) { r += indent; r += "else where"; + handle_line_truncation(r, 2); r += "\n"; inc_indent(); visit_stmt(*x.m_orelse[i]); @@ -1139,7 +1261,9 @@ class ASRToFortranVisitor : public ASR::BaseVisitor r += " ("; visit_expr(*x.m_test); r += src; - r += ")\n"; + r += ")"; + handle_line_truncation(r, 2); + r += "\n"; visit_body(x, r); r += indent; r += "end do"; @@ -1150,7 +1274,21 @@ class ASRToFortranVisitor : public ASR::BaseVisitor src = r; } - // void visit_Nullify(const ASR::Nullify_t &x) {} + void visit_Nullify(const ASR::Nullify_t &x) { + std::string r = indent; + r += "nullify ("; + for (int i = 0; i < static_cast(x.n_vars); i++) { + visit_expr(*x.m_vars[i]); + r += src; + if(i != static_cast(x.n_vars-1)) { + r += ", "; + } + } + r += ")"; + handle_line_truncation(r, 2); + r += "\n"; + src = r; + } // void visit_Flush(const ASR::Flush_t &x) {} @@ -1183,7 +1321,7 @@ class ASRToFortranVisitor : public ASR::BaseVisitor std::string re = src; visit_expr(*x.m_im); std::string im = src; - src = "(" + re + ", " + im + ")"; + src = "cmplx(" + re + ", " + im + ")"; } // void visit_NamedExpr(const ASR::NamedExpr_t &x) {} @@ -1195,12 +1333,6 @@ class ASRToFortranVisitor : public ASR::BaseVisitor } else { r += ASRUtils::symbol_name(x.m_name); } - if (r == "bit_size") { - // TODO: Remove this once bit_size is implemented in IntrinsicElementalFunction - visit_expr(*x.m_value); - return; - } - r += "("; for (size_t i = 0; i < x.n_args; i ++) { visit_expr(*x.m_args[i].m_value); @@ -1211,35 +1343,23 @@ class ASRToFortranVisitor : public ASR::BaseVisitor src = r; } - void visit_TypeInquiry(const ASR::TypeInquiry_t &x) { - std::string out = ""; - switch (x.m_inquiry_id) { - SET_INTRINSIC_NAME(Epsilon, "epsilon" ); - SET_INTRINSIC_NAME(Huge, "huge" ); - SET_INTRINSIC_NAME(Precision, "precision"); - SET_INTRINSIC_NAME(Radix, "radix" ); - SET_INTRINSIC_NAME(Range, "range" ); - SET_INTRINSIC_NAME(Rank, "rank" ); - SET_INTRINSIC_NAME(Tiny, "tiny" ); - default : { - throw LCompilersException("TypeInquiry: `" - + ASRUtils::get_intrinsic_name(x.m_inquiry_id) - + "` is not implemented"); - } - } - this->visit_expr(*x.m_arg); - out += "(" + src + ")"; - src = out; - } - void visit_IntrinsicImpureSubroutine( const ASR::IntrinsicImpureSubroutine_t &x ) { std::string out; out = "call "; - switch ( x.m_intrinsic_id ) { + switch ( x.m_sub_intrinsic_id ) { SET_INTRINSIC_SUBROUTINE_NAME(RandomNumber, "random_number"); + SET_INTRINSIC_SUBROUTINE_NAME(RandomInit, "random_init"); + SET_INTRINSIC_SUBROUTINE_NAME(RandomSeed, "random_seed"); + SET_INTRINSIC_SUBROUTINE_NAME(GetCommand, "get_command"); + SET_INTRINSIC_SUBROUTINE_NAME(GetCommandArgument, "get_command_argument"); + SET_INTRINSIC_SUBROUTINE_NAME(GetEnvironmentVariable, "get_environment_variable"); + SET_INTRINSIC_SUBROUTINE_NAME(ExecuteCommandLine, "execute_command_line"); + SET_INTRINSIC_SUBROUTINE_NAME(Srand, "srand"); + SET_INTRINSIC_SUBROUTINE_NAME(SystemClock, "system_clock"); + SET_INTRINSIC_SUBROUTINE_NAME(DateAndTime, "date_and_time"); default : { throw LCompilersException("IntrinsicImpureSubroutine: `" - + ASRUtils::get_intrinsic_name(x.m_intrinsic_id) + + ASRUtils::get_intrinsic_name(x.m_sub_intrinsic_id) + "` is not implemented"); } } @@ -1253,75 +1373,83 @@ class ASRToFortranVisitor : public ASR::BaseVisitor src = out; } - void visit_IntrinsicElementalFunction(const ASR::IntrinsicElementalFunction_t &x) { - std::string out; - switch (x.m_intrinsic_id) { - SET_INTRINSIC_NAME(Abs, "abs"); - SET_INTRINSIC_NAME(Exp, "exp"); - SET_INTRINSIC_NAME(Max, "max"); - SET_INTRINSIC_NAME(Min, "min"); - SET_INTRINSIC_NAME(Sqrt, "sqrt"); - SET_INTRINSIC_NAME(Mod, "mod"); - SET_INTRINSIC_NAME(Sin, "sin"); - SET_INTRINSIC_NAME(Char, "char"); - SET_INTRINSIC_NAME(StringContainsSet, "verify"); - SET_INTRINSIC_NAME(StringFindSet, "scan"); - SET_INTRINSIC_NAME(SubstrIndex, "index"); - SET_INTRINSIC_NAME(Modulo, "modulo"); - default : { - throw LCompilersException("IntrinsicElementalFunction: `" - + ASRUtils::get_intrinsic_name(x.m_intrinsic_id) - + "` is not implemented"); - } - } - out += "("; - for (size_t i = 0; i < x.n_args; i ++) { + void visit_IntrinsicElementalFunction_helper(std::string &out, std::string func_name, const ASR::IntrinsicElementalFunction_t &x) { + src = ""; + out += func_name; + if (x.n_args > 0) visit_expr(*x.m_args[0]); + out += "(" + src; + for (size_t i = 1; i < x.n_args; i++) { + out += ", "; visit_expr(*x.m_args[i]); out += src; - if (i < x.n_args-1) out += ", "; } out += ")"; src = out; } - #define SET_ARR_INTRINSIC_NAME(X, func_name) \ - case (static_cast(ASRUtils::IntrinsicArrayFunctions::X)) : { \ - visit_expr(*x.m_args[0]); \ - out += func_name; break; \ + void visit_IntrinsicElementalFunction(const ASR::IntrinsicElementalFunction_t &x) { + std::string out; + std::string intrinsic_func_name = ASRUtils::get_intrinsic_name(static_cast(x.m_intrinsic_id)); + if(intrinsic_func_name == "StringFindSet") intrinsic_func_name = "scan"; + else if(intrinsic_func_name == "StringContainsSet") intrinsic_func_name = "verify"; + else if(intrinsic_func_name == "SubstrIndex") intrinsic_func_name = "index"; + else if(intrinsic_func_name == "SelectedRealKind") intrinsic_func_name = "selected_real_kind"; + else if(intrinsic_func_name == "SelectedIntKind") intrinsic_func_name = "selected_int_kind"; + else if(intrinsic_func_name == "SelectedCharKind") intrinsic_func_name = "selected_char_kind"; + else if(intrinsic_func_name == "LogGamma") intrinsic_func_name = "log_gamma"; + else if(intrinsic_func_name == "SetExponent") intrinsic_func_name = "set_exponent"; + else if(intrinsic_func_name == "Mergebits") intrinsic_func_name = "merge_bits"; + else if(intrinsic_func_name == "StringLenTrim") intrinsic_func_name = "len_trim"; + else if(intrinsic_func_name == "StringTrim") intrinsic_func_name = "trim"; + else if(intrinsic_func_name == "MoveAlloc") intrinsic_func_name = "move_alloc"; + else if(intrinsic_func_name == "CompilerOptions") intrinsic_func_name = "compiler_options"; + else if(intrinsic_func_name == "CompilerVersion") intrinsic_func_name = "compiler_version"; + visit_IntrinsicElementalFunction_helper(out, intrinsic_func_name, x); + } + + void visit_TypeInquiry_helper(std::string &out, std::string func_name, const ASR::TypeInquiry_t &x) { + out += func_name; + visit_expr(*x.m_arg); + out += "(" + src + ")"; + src = out; + } + + void visit_TypeInquiry(const ASR::TypeInquiry_t &x) { + std::string out; + std::string intrinsic_func_name = ASRUtils::get_intrinsic_name(static_cast(x.m_inquiry_id)); + if(intrinsic_func_name == "BitSize") intrinsic_func_name = "bit_size"; + else if(intrinsic_func_name == "NewLine") intrinsic_func_name = "new_line"; + visit_TypeInquiry_helper(out, intrinsic_func_name, x); + } + + void visit_IntrinsicArrayFunction_helper(std::string &out, std::string func_name, const ASR::IntrinsicArrayFunction_t &x) { + out += func_name; + visit_expr(*x.m_args[0]); + out += "(" + src; + for (size_t i = 1; i < x.n_args; i++) { + out += ", "; + visit_expr(*x.m_args[i]); + out += src; } + out += ")"; + src = out; + } void visit_IntrinsicArrayFunction(const ASR::IntrinsicArrayFunction_t &x) { std::string out; - switch (x.m_arr_intrinsic_id) { - SET_ARR_INTRINSIC_NAME(Any, "any"); - SET_ARR_INTRINSIC_NAME(Sum, "sum"); - SET_ARR_INTRINSIC_NAME(Shape, "shape"); - SET_ARR_INTRINSIC_NAME(MaxVal, "maxval"); - SET_ARR_INTRINSIC_NAME(MinVal, "minval"); - case (static_cast(ASRUtils::IntrinsicArrayFunctions::Pack)) : { - out += "pack"; - visit_expr(*x.m_args[0]); - out += "(" + src + ", "; - visit_expr(*x.m_args[1]); - out += src; - if (x.n_args == 3) { - out += ", "; - visit_expr(*x.m_args[2]); - out += src; - } - out += ")"; - src = out; - out = ""; - break; - } - default : { - throw LCompilersException("IntrinsicArrayFunction: `" - + ASRUtils::get_array_intrinsic_name(x.m_arr_intrinsic_id) - + "` is not implemented"); - } + std::string intrinsic_func_name = ASRUtils::get_array_intrinsic_name(static_cast(x.m_arr_intrinsic_id)); + if(intrinsic_func_name == "DotProduct") intrinsic_func_name = "dot_product"; + if(intrinsic_func_name == "Spread" && x.m_overload_id == -1){ + ASR::ArrayPhysicalCast_t *arr_physical = ASR::down_cast(x.m_args[0]); + if(ASR::is_a(*arr_physical->m_arg)){ + ASR::ArrayConstant_t *arr_const = ASR::down_cast(arr_physical->m_arg); + x.m_args[0] = ASRUtils::fetch_ArrayConstant_value(al, arr_const, 0); + } else if(ASR::is_a(*arr_physical->m_arg)){ + ASR::ArrayConstructor_t *arr_const = ASR::down_cast(arr_physical->m_arg); + x.m_args[0] = arr_const->m_args[0]; + } } - out += "(" + src + ")"; - src = out; + visit_IntrinsicArrayFunction_helper(out, intrinsic_func_name, x); } // void visit_IntrinsicImpureFunction(const ASR::IntrinsicImpureFunction_t &x) {} @@ -1339,13 +1467,38 @@ class ASRToFortranVisitor : public ASR::BaseVisitor src = r; } - // void visit_EnumTypeConstructor(const ASR::EnumTypeConstructor_t &x) {} + // void visit_EnumConstructor(const ASR::EnumConstructor_t &x) {} - // void visit_UnionTypeConstructor(const ASR::UnionTypeConstructor_t &x) {} + // void visit_UnionConstructor(const ASR::UnionConstructor_t &x) {} - // void visit_ImpliedDoLoop(const ASR::ImpliedDoLoop_t &x) {} + void visit_ImpliedDoLoop(const ASR::ImpliedDoLoop_t &x) { + std::string r = "("; + for (size_t i = 0; i < x.n_values; i++) { + visit_expr(*x.m_values[i]); + r += src; + if (i != x.n_values - 1) r += ", "; + } + r += ", "; + visit_expr(*x.m_var); + r += src; + r += " = "; + visit_expr(*x.m_start); + r += src; + r += ", "; + visit_expr(*x.m_end); + r += src; + if (x.m_increment) { + r += ", "; + visit_expr(*x.m_increment); + r += src; + } + r += ")"; + src = r; + return; + } void visit_IntegerConstant(const ASR::IntegerConstant_t &x) { + // TODO: handle IntegerBOZ src = std::to_string(x.m_n); int kind = ASRUtils::extract_kind_from_ttype_t(x.m_type); if (kind != 4) { @@ -1356,8 +1509,6 @@ class ASRToFortranVisitor : public ASR::BaseVisitor last_expr_precedence = Precedence::Ext; } - // void visit_IntegerBOZ(const ASR::IntegerBOZ_t &x) {} - // void visit_IntegerBitNot(const ASR::IntegerBitNot_t &x) {} void visit_IntegerUnaryMinus(const ASR::IntegerUnaryMinus_t &x) { @@ -1399,9 +1550,9 @@ class ASRToFortranVisitor : public ASR::BaseVisitor void visit_RealConstant(const ASR::RealConstant_t &x) { int kind = ASRUtils::extract_kind_from_ttype_t(x.m_type); if (kind >= 8) { - src = std::to_string(x.m_r) + "d0"; + src = ASRUtils::to_string_with_precision(x.m_r, 16) + "_8"; } else { - src = std::to_string(x.m_r); + src = ASRUtils::to_string_with_precision(x.m_r, 8); } last_expr_precedence = Precedence::Ext; } @@ -1491,9 +1642,27 @@ class ASRToFortranVisitor : public ASR::BaseVisitor src = r; } + void visit_StringSection(const ASR::StringSection_t &x) { + std::string r = ""; + visit_expr(*x.m_arg); + r += src; + r += "("; + visit_expr(*x.m_start); + r += src; + r += ":"; + visit_expr(*x.m_end); + r += src; + r += ")"; + src = r; + } + void visit_StringConstant(const ASR::StringConstant_t &x) { src = "\""; - src.append(x.m_s); + if(std::strcmp(x.m_s, "\n") == 0) { + src.append("\\n"); + } else { + src.append(x.m_s); + } src += "\""; last_expr_precedence = Precedence::Ext; } @@ -1559,6 +1728,10 @@ class ASRToFortranVisitor : public ASR::BaseVisitor src = r; } + void visit_StringPhysicalCast(const ASR::StringPhysicalCast_t &x) { + visit_expr(*x.m_arg); + } + // void visit_CPtrCompare(const ASR::CPtrCompare_t &x) {} // void visit_SymbolicCompare(const ASR::SymbolicCompare_t &x) {} @@ -1584,10 +1757,9 @@ class ASRToFortranVisitor : public ASR::BaseVisitor void visit_ArrayConstant(const ASR::ArrayConstant_t &x) { std::string r = "["; - for(size_t i = 0; i < x.n_args; i++) { - visit_expr(*x.m_args[i]); - r += src; - if (i < x.n_args-1) r += ", "; + for(size_t i = 0; i < (size_t) ASRUtils::get_fixed_size_of_array(x.m_type); i++) { + r += ASRUtils::fetch_ArrayConstant_value(x, i); + if (i < (size_t) ASRUtils::get_fixed_size_of_array(x.m_type)-1) r += ", "; } r += "]"; src = r; @@ -1688,20 +1860,6 @@ class ASRToFortranVisitor : public ASR::BaseVisitor src = r; } - void visit_ArrayAll(const ASR::ArrayAll_t &x) { - std::string r; - r += "all"; - r += "("; - visit_expr(*x.m_mask); - r += src; - if (x.m_dim) { - visit_expr(*x.m_dim); - r += src; - } - r += ")"; - src = r; - } - // void visit_BitCast(const ASR::BitCast_t &x) {} void visit_StructInstanceMember(const ASR::StructInstanceMember_t &x) { @@ -1793,7 +1951,10 @@ class ASRToFortranVisitor : public ASR::BaseVisitor // void visit_CLoc(const ASR::CLoc_t &x) {} - // void visit_PointerToCPtr(const ASR::PointerToCPtr_t &x) {} + void visit_PointerToCPtr(const ASR::PointerToCPtr_t &x) { + visit_expr(*x.m_arg); + src = "c_loc(" + src + ")"; + } // void visit_GetPointer(const ASR::GetPointer_t &x) {} @@ -1812,6 +1973,35 @@ class ASRToFortranVisitor : public ASR::BaseVisitor src = "iachar(" + src + ")"; } + void visit_ArrayIsContiguous(const ASR::ArrayIsContiguous_t &x) { + visit_expr(*x.m_array); + src = "is_contiguous(" + src + ")"; + } + + void visit_ReAlloc(const ASR::ReAlloc_t &x) { + std::string r = indent; + r += "reallocate("; + for (size_t i = 0; i < x.n_args; i++) { + visit_expr(*x.m_args[i].m_a); + r += src; + if (x.m_args[i].n_dims > 0) { + r += "("; + for (size_t j = 0; j < x.m_args[i].n_dims; j++) { + visit_expr(*x.m_args[i].m_dims[j].m_length); + r += src; + if (j < x.m_args[i].n_dims - 1) r += ", "; + } + r += ")"; + } + if (i < x.n_args - 1) r += ", "; + } + r += ")"; + handle_line_truncation(r, 2); + r += "\n"; + src = r; + } + + // void visit_SizeOfType(const ASR::SizeOfType_t &x) {} // void visit_PointerNullConstant(const ASR::PointerNullConstant_t &x) {} @@ -1832,7 +2022,9 @@ class ASRToFortranVisitor : public ASR::BaseVisitor r += src; if (i < x.n_test-1) r += ", "; } - r += ")\n"; + r += ")"; + handle_line_truncation(r, 2); + r += "\n"; inc_indent(); for(size_t i = 0; i < x.n_body; i ++) { visit_stmt(*x.m_body[i]); @@ -1854,7 +2046,9 @@ class ASRToFortranVisitor : public ASR::BaseVisitor visit_expr(*x.m_end); r += src; } - r += ")\n"; + r += ")"; + handle_line_truncation(r, 2); + r += "\n"; inc_indent(); for(size_t i = 0; i < x.n_body; i ++) { visit_stmt(*x.m_body[i]); diff --git a/src/libasr/codegen/asr_to_julia.cpp b/src/libasr/codegen/asr_to_julia.cpp index 04dd706b09..192068cbde 100644 --- a/src/libasr/codegen/asr_to_julia.cpp +++ b/src/libasr/codegen/asr_to_julia.cpp @@ -307,7 +307,7 @@ class ASRToJuliaVisitor : public ASR::BaseVisitor sub = format_type(type_name, v.m_name, use_ref); } } else { - diag.codegen_error_label("Type number '" + std::to_string(v.m_type->type) + diag.codegen_error_label("Type '" + ASRUtils::type_to_str_python(v.m_type) + "' not supported", { v.base.base.loc }, ""); @@ -404,7 +404,7 @@ class ASRToJuliaVisitor : public ASR::BaseVisitor sub = format_type(der_type_name, v.m_name, use_ref); } } else { - diag.codegen_error_label("Type number '" + std::to_string(v_m_type->type) + diag.codegen_error_label("Type '" + ASRUtils::type_to_str_python(v_m_type) + "' not supported", { v.base.base.loc }, ""); @@ -937,7 +937,7 @@ class ASRToJuliaVisitor : public ASR::BaseVisitor tmp_sym = tmp_var->m_v; } else { throw CodeGenError("Cannot deallocate variables in expression " + - std::to_string(tmp_expr->type), + ASRUtils::type_to_str_python(ASRUtils::expr_type(tmp_expr)), tmp_expr->base.loc); } const ASR::Variable_t* v = ASR::down_cast( @@ -984,7 +984,7 @@ class ASRToJuliaVisitor : public ASR::BaseVisitor generate_array_decl( out, std::string(v->m_name), der_type_name, _dims, nullptr, n_dims, true, true); } else { - diag.codegen_error_label("Type number '" + std::to_string(v->m_type->type) + diag.codegen_error_label("Type '" + ASRUtils::type_to_str_python(v->m_type) + "' not supported", { v->base.base.loc }, ""); @@ -1237,8 +1237,11 @@ class ASRToJuliaVisitor : public ASR::BaseVisitor void visit_DoConcurrentLoop(const ASR::DoConcurrentLoop_t& x) { - const ASR::DoLoop_t do_loop = ASR::DoLoop_t{ x.base, nullptr, x.m_head, x.m_body, x.n_body, nullptr, 0 }; + // LCOMPILERS_ASSERT(x.n_head == 1); + for (size_t i = 0; i < x.n_head; i++) { + const ASR::DoLoop_t do_loop = ASR::DoLoop_t{ x.base, nullptr, x.m_head[i], x.m_body, x.n_body, nullptr, 0 }; visit_DoLoop(do_loop, true); + } } void visit_If(const ASR::If_t& x) @@ -1435,10 +1438,9 @@ class ASRToJuliaVisitor : public ASR::BaseVisitor { std::string indent(indentation_level * indentation_spaces, ' '); std::string out = "["; - for (size_t i = 0; i < x.n_args; i++) { - visit_expr(*x.m_args[i]); - out += src; - if (i < x.n_args - 1) + for (size_t i = 0; i < (size_t) ASRUtils::get_fixed_size_of_array(x.m_type); i++) { + out += ASRUtils::fetch_ArrayConstant_value(x, i); + if (i < (size_t) ASRUtils::get_fixed_size_of_array(x.m_type) - 1) out += ", "; } out += "]"; @@ -1843,24 +1845,28 @@ class ASRToJuliaVisitor : public ASR::BaseVisitor { std::string indent(indentation_level * indentation_spaces, ' '); std::string out = indent + "println(", sep; - if (x.m_separator) { - visit_expr(*x.m_separator); - sep = src; + sep = "\" \""; + //HACKISH way to handle print refactoring (always using stringformat). + // TODO : Implement stringformat visitor. + ASR::StringFormat_t* str_fmt; + size_t n_values = 0; + if(ASR::is_a(*x.m_text)){ + str_fmt = ASR::down_cast(x.m_text); + n_values = str_fmt->n_args; + } else if (ASR::is_a(*ASRUtils::expr_type(x.m_text))){ + visit_expr(*x.m_text); + out += src; } else { - sep = "\" \""; - } - for (size_t i = 0; i < x.n_values; i++) { - visit_expr(*x.m_values[i]); + throw CodeGenError("print statment supported for stringformat and single character argument", + x.base.base.loc); + } + for (size_t i = 0; i < n_values; i++) { + visit_expr(*str_fmt->m_args[i]); out += src; - if (i + 1 != x.n_values) { + if (i + 1 != n_values) { out += ", " + sep + ", "; } } - if (x.m_end) { - visit_expr(*x.m_end); - out += src; - } - out += ")\n"; src = out; } @@ -1901,11 +1907,12 @@ class ASRToJuliaVisitor : public ASR::BaseVisitor SET_INTRINSIC_NAME(Expm1, "expm1"); SET_INTRINSIC_NAME(Trunc, "trunc"); SET_INTRINSIC_NAME(Fix, "fix"); - SET_INTRINSIC_NAME(Kind, "kind"); SET_INTRINSIC_NAME(StringContainsSet, "verify"); SET_INTRINSIC_NAME(StringFindSet, "scan"); SET_INTRINSIC_NAME(SubstrIndex, "index"); SET_INTRINSIC_NAME(Modulo, "modulo"); + SET_INTRINSIC_NAME(StringLenTrim, "len_trim"); + SET_INTRINSIC_NAME(StringTrim, "trim"); default : { throw LCompilersException("IntrinsicFunction: `" + ASRUtils::get_intrinsic_name(x.m_intrinsic_id) diff --git a/src/libasr/codegen/asr_to_llvm.cpp b/src/libasr/codegen/asr_to_llvm.cpp index ec8a8b0205..0cb11b0d42 100644 --- a/src/libasr/codegen/asr_to_llvm.cpp +++ b/src/libasr/codegen/asr_to_llvm.cpp @@ -1,8 +1,6 @@ #include #include #include -#include -#include #include #include @@ -33,11 +31,13 @@ #include #include #include -#include #include #include #include #include +#if LLVM_VERSION_MAJOR < 18 +# include +#endif #include #include @@ -73,8 +73,8 @@ void string_init(llvm::LLVMContext &context, llvm::Module &module, llvm::FunctionType *function_type = llvm::FunctionType::get( llvm::Type::getVoidTy(context), { llvm::Type::getInt32Ty(context), - llvm::Type::getInt8PtrTy(context) - }, true); + llvm::Type::getInt8Ty(context)->getPointerTo() + }, false); fn = llvm::Function::Create(function_type, llvm::Function::ExternalLinkage, func_name, module); } @@ -143,6 +143,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor bool prototype_only; llvm::StructType *complex_type_4, *complex_type_8; llvm::StructType *complex_type_4_ptr, *complex_type_8_ptr; + llvm::Type* string_descriptor; llvm::PointerType *character_type; llvm::PointerType *list_type; std::vector struct_type_stack; @@ -157,6 +158,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor std::map> name2memidx; std::map llvm_symtab; // llvm_symtab_value + std::map llvm_symtab_deep_copy; std::map llvm_symtab_fn; std::map llvm_symtab_fn_names; std::map llvm_symtab_fn_arg; @@ -189,6 +191,8 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor std::map type2vtabtype; std::map type2vtabid; std::map> vtabtype2procidx; + // Stores the map of pointer and associated type, map, Used by Load or GEP + std::map ptr_type; llvm::Type* current_select_type_block_type; std::string current_select_type_block_der_type; @@ -204,9 +208,18 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor std::vector heap_arrays; std::map strings_to_be_allocated; // (array, size) Vec strings_to_be_deallocated; - - uint32_t global_underscore_hash; // used in interactive mode - + struct to_be_allocated_array{ // struct to hold details for the initializing pointer_to_array_type later inside main function. + llvm::Constant* pointer_to_array_type; + llvm::Type* array_type; + LCompilers::ASR::ttype_t* var_type; + size_t n_dims; + }; + std::vector allocatable_array_details; + struct variable_inital_value { /* Saves information for variables that need to be initialized once. To be initialized in `program`*/ + ASR::Variable_t* v; + llvm::Value* target_var; // Corresponds to variable `v` in llvm IR. + }; + std::vector variable_inital_value_vec; /* Saves information for variables that need to be initialized once. To be initialized in `program`*/ ASRToLLVMVisitor(Allocator &al, llvm::LLVMContext &context, std::string infile, CompilerOptions &compiler_options_, diag::Diagnostics &diagnostics) : diag{diagnostics}, @@ -224,7 +237,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor llvm_utils(std::make_unique(context, builder.get(), current_der_type_name, name2dertype, name2dercontext, struct_type_stack, dertype2parent, name2memidx, compiler_options, arr_arg_type_cache, - fname2arg_type)), + fname2arg_type, ptr_type)), list_api(std::make_unique(context, llvm_utils.get(), builder.get())), tuple_api(std::make_unique(context, llvm_utils.get(), builder.get())), dict_api_lp(std::make_unique(context, llvm_utils.get(), builder.get())), @@ -233,8 +246,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor set_api_sc(std::make_unique(context, llvm_utils.get(), builder.get())), arr_descr(LLVMArrUtils::Descriptor::get_descriptor(context, builder.get(), llvm_utils.get(), - LLVMArrUtils::DESCR_TYPE::_SimpleCMODescriptor, compiler_options_, heap_arrays)), - global_underscore_hash(0) + LLVMArrUtils::DESCR_TYPE::_SimpleCMODescriptor, compiler_options_, heap_arrays)) { llvm_utils->tuple_api = tuple_api.get(); llvm_utils->list_api = list_api.get(); @@ -248,28 +260,13 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor strings_to_be_deallocated.reserve(al, 1); } - llvm::AllocaInst* CreateAlloca(llvm::Type* type, - llvm::Value* size, const std::string& Name) { - llvm::BasicBlock &entry_block = builder->GetInsertBlock()->getParent()->getEntryBlock(); - llvm::IRBuilder<> builder0(context); - builder0.SetInsertPoint(&entry_block, entry_block.getFirstInsertionPt()); - return builder0.CreateAlloca(type, size, Name); - } - - llvm::Value* CreateLoad(llvm::Value *x) { - return LLVM::CreateLoad(*builder, x); - } - - - llvm::Value* CreateGEP(llvm::Value *x, std::vector &idx) { - return LLVM::CreateGEP(*builder, x, idx); - } - #define load_non_array_non_character_pointers(expr, type, llvm_value) if( ASR::is_a(*expr) && \ !ASRUtils::is_array(type) && \ LLVM::is_llvm_pointer(*type) && \ !ASRUtils::is_character(*type) ) { \ - llvm_value = CreateLoad(llvm_value); \ + llvm::Type *llvm_type = llvm_utils->get_type_from_ttype_t_util( \ + ASRUtils::extract_type(type), module.get()); \ + llvm_value = llvm_utils->CreateLoad2(llvm_type, llvm_value); \ } \ // Inserts a new block `bb` using the current builder @@ -448,8 +445,10 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor ptr_loads = 2; for( int r = 0; r < n_dims; r++ ) { ASR::dimension_t m_dim = m_dims[r]; + LCOMPILERS_ASSERT(m_dim.m_start != nullptr); visit_expr(*(m_dim.m_start)); llvm::Value* start = tmp; + LCOMPILERS_ASSERT(m_dim.m_length != nullptr); visit_expr(*(m_dim.m_length)); llvm::Value* end = tmp; llvm_dims.push_back(std::make_pair(start, end)); @@ -475,7 +474,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor arr_first = builder->CreateBitCast( arr_first_i8, llvm_data_type->getPointerTo()); } else { - arr_first = builder->CreateAlloca(llvm_data_type, prod); + arr_first = llvm_utils->CreateAlloca(*builder, llvm_data_type, prod); builder->CreateStore(arr_first, arr); } } @@ -490,7 +489,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor (pointer to the first element, offset and descriptor of each dimension) of the array which are allocated memory in heap. */ - inline void fill_malloc_array_details(llvm::Value* arr, llvm::Type* llvm_data_type, + inline void fill_malloc_array_details(llvm::Value* arr, llvm::Type* arr_type, llvm::Type* llvm_data_type, ASR::dimension_t* m_dims, int n_dims, bool realloc=false) { std::vector> llvm_dims; @@ -505,7 +504,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor llvm_dims.push_back(std::make_pair(start, end)); } ptr_loads = ptr_loads_copy; - arr_descr->fill_malloc_array_details(arr, llvm_data_type, + arr_descr->fill_malloc_array_details(arr, arr_type, llvm_data_type, n_dims, llvm_dims, module.get(), realloc); } @@ -536,7 +535,6 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor std::string runtime_func_name, llvm::Type* complex_type=nullptr) { - get_builder0() if( complex_type == nullptr ) { complex_type = complex_type_4; } @@ -547,30 +545,26 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor complex_type->getPointerTo(), complex_type->getPointerTo(), complex_type->getPointerTo() - }, true); + }, false); fn = llvm::Function::Create(function_type, llvm::Function::ExternalLinkage, runtime_func_name, *module); } - llvm::AllocaInst *pleft_arg = builder0.CreateAlloca(complex_type, - nullptr); + llvm::AllocaInst *pleft_arg = llvm_utils->CreateAlloca(*builder, complex_type); builder->CreateStore(left_arg, pleft_arg); - llvm::AllocaInst *pright_arg = builder0.CreateAlloca(complex_type, - nullptr); + llvm::AllocaInst *pright_arg = llvm_utils->CreateAlloca(*builder, complex_type); builder->CreateStore(right_arg, pright_arg); - llvm::AllocaInst *presult = builder0.CreateAlloca(complex_type, - nullptr); + llvm::AllocaInst *presult = llvm_utils->CreateAlloca(*builder, complex_type); std::vector args = {pleft_arg, pright_arg, presult}; builder->CreateCall(fn, args); - return CreateLoad(presult); + return llvm_utils->CreateLoad(presult); } llvm::Value* lfortran_strop(llvm::Value* left_arg, llvm::Value* right_arg, std::string runtime_func_name) { - get_builder0() llvm::Function *fn = module->getFunction(runtime_func_name); if (!fn) { llvm::FunctionType *function_type = llvm::FunctionType::get( @@ -582,24 +576,20 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor fn = llvm::Function::Create(function_type, llvm::Function::ExternalLinkage, runtime_func_name, *module); } - llvm::AllocaInst *pleft_arg = builder0.CreateAlloca(character_type, - nullptr); + llvm::AllocaInst *pleft_arg = llvm_utils->CreateAlloca(*builder, character_type); builder->CreateStore(left_arg, pleft_arg); - llvm::AllocaInst *pright_arg = builder0.CreateAlloca(character_type, - nullptr); + llvm::AllocaInst *pright_arg = llvm_utils->CreateAlloca(*builder, character_type); builder->CreateStore(right_arg, pright_arg); - llvm::AllocaInst *presult = builder0.CreateAlloca(character_type, - nullptr); + llvm::AllocaInst *presult = llvm_utils->CreateAlloca(*builder, character_type); std::vector args = {pleft_arg, pright_arg, presult}; builder->CreateCall(fn, args); - strings_to_be_deallocated.push_back(al, CreateLoad(presult)); - return CreateLoad(presult); + strings_to_be_deallocated.push_back(al, llvm_utils->CreateLoad(presult)); + return llvm_utils->CreateLoad(presult); } llvm::Value* lfortran_str_cmp(llvm::Value* left_arg, llvm::Value* right_arg, std::string runtime_func_name) { - get_builder0() llvm::Function *fn = module->getFunction(runtime_func_name); if(!fn) { llvm::FunctionType *function_type = llvm::FunctionType::get( @@ -610,11 +600,9 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor fn = llvm::Function::Create(function_type, llvm::Function::ExternalLinkage, runtime_func_name, *module); } - llvm::AllocaInst *pleft_arg = builder0.CreateAlloca(character_type, - nullptr); + llvm::AllocaInst *pleft_arg = llvm_utils->CreateAlloca(*builder, character_type); builder->CreateStore(left_arg, pleft_arg); - llvm::AllocaInst *pright_arg = builder0.CreateAlloca(character_type, - nullptr); + llvm::AllocaInst *pright_arg = llvm_utils->CreateAlloca(*builder, character_type); builder->CreateStore(right_arg, pright_arg); std::vector args = {pleft_arg, pright_arg}; return builder->CreateCall(fn, args); @@ -622,7 +610,6 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor llvm::Value* lfortran_strrepeat(llvm::Value* left_arg, llvm::Value* right_arg) { - get_builder0() std::string runtime_func_name = "_lfortran_strrepeat"; llvm::Function *fn = module->getFunction(runtime_func_name); if (!fn) { @@ -635,20 +622,18 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor fn = llvm::Function::Create(function_type, llvm::Function::ExternalLinkage, runtime_func_name, *module); } - llvm::AllocaInst *pleft_arg = builder0.CreateAlloca(character_type, - nullptr); + llvm::AllocaInst *pleft_arg = llvm_utils->CreateAlloca(*builder, character_type); builder->CreateStore(left_arg, pleft_arg); - llvm::AllocaInst *presult = builder0.CreateAlloca(character_type, - nullptr); + llvm::AllocaInst *presult = llvm_utils->CreateAlloca(*builder, character_type); std::vector args = {pleft_arg, right_arg, presult}; builder->CreateCall(fn, args); - return CreateLoad(presult); + return llvm_utils->CreateLoad(presult); } llvm::Value* lfortran_str_len(llvm::Value* str, bool use_descriptor=false) { if (use_descriptor) { - str = CreateLoad(arr_descr->get_pointer_to_data(str)); + str = llvm_utils->CreateLoad(arr_descr->get_pointer_to_data(str)); } std::string runtime_func_name = "_lfortran_str_len"; llvm::Function *fn = module->getFunction(runtime_func_name); @@ -715,29 +700,15 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor if (!fn) { llvm::FunctionType *function_type = llvm::FunctionType::get( character_type, { - character_type, llvm::Type::getInt32Ty(context) + character_type, llvm::Type::getInt64Ty(context) }, false); fn = llvm::Function::Create(function_type, llvm::Function::ExternalLinkage, runtime_func_name, *module); } + idx1 = builder->CreateSExt(idx1, llvm::Type::getInt64Ty(context)); return builder->CreateCall(fn, {str, idx1}); } - llvm::Value* lfortran_str_contains(llvm::Value* str, llvm::Value* substr) - { - std::string runtime_func_name = "_lfortran_str_contains"; - llvm::Function *fn = module->getFunction(runtime_func_name); - if (!fn) { - llvm::FunctionType *function_type = llvm::FunctionType::get( - llvm::Type::getInt1Ty(context), { - character_type, character_type - }, false); - fn = llvm::Function::Create(function_type, - llvm::Function::ExternalLinkage, runtime_func_name, *module); - } - return builder->CreateCall(fn, {str, substr}); - } - llvm::Value* lfortran_str_copy(llvm::Value* str, llvm::Value* idx1, llvm::Value* idx2) { std::string runtime_func_name = "_lfortran_str_copy"; @@ -771,21 +742,63 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor return builder->CreateCall(fn, {str, idx1, idx2, step, left_present, right_present}); } - llvm::Value* lfortran_str_copy(llvm::Value* dest, llvm::Value *src, bool is_allocatable=false) { - std::string runtime_func_name = "_lfortran_strcpy"; + llvm::Value* lfortran_str_slice8(llvm::Value* str, llvm::Value* idx1, llvm::Value* idx2, + llvm::Value* step, llvm::Value* left_present, llvm::Value* right_present) + { + std::string runtime_func_name = "_lfortran_str_slice"; llvm::Function *fn = module->getFunction(runtime_func_name); if (!fn) { llvm::FunctionType *function_type = llvm::FunctionType::get( - llvm::Type::getVoidTy(context), { - character_type->getPointerTo(), character_type, - llvm::Type::getInt8Ty(context) + character_type, { + character_type, llvm::Type::getInt64Ty(context), + llvm::Type::getInt64Ty(context), llvm::Type::getInt64Ty(context), + llvm::Type::getInt1Ty(context), llvm::Type::getInt1Ty(context) }, false); fn = llvm::Function::Create(function_type, llvm::Function::ExternalLinkage, runtime_func_name, *module); } - llvm::Value* free_string = llvm::ConstantInt::get( - llvm::Type::getInt8Ty(context), llvm::APInt(8, is_allocatable)); - return builder->CreateCall(fn, {dest, src, free_string}); + return builder->CreateCall(fn, {str, idx1, idx2, step, left_present, right_present}); + } + + llvm::Value* lfortran_str_copy(llvm::Value* dest, llvm::Value *src, bool is_allocatable=false) { + // If string is of allocatable (physically a DescriptorString), extract (char*, size, capacity). + if(!is_allocatable) { + std::string runtime_func_name = "_lfortran_strcpy_pointer_string"; + llvm::Function *fn = module->getFunction(runtime_func_name); + if (!fn) { + llvm::FunctionType *function_type = llvm::FunctionType::get( + llvm::Type::getVoidTy(context), + { + llvm::Type::getInt8Ty(context)->getPointerTo()->getPointerTo(), + llvm::Type::getInt8Ty(context)->getPointerTo() + }, false); + fn = llvm::Function::Create(function_type, + llvm::Function::ExternalLinkage, runtime_func_name, *module); + } + return builder->CreateCall(fn, {dest, src}); + } else { + llvm::Value* src_char_ptr, *dest_char_ptr, *string_size, *string_capacity; + std::string runtime_func_name = "_lfortran_strcpy_descriptor_string"; + dest_char_ptr = llvm_utils->create_gep2(string_descriptor, dest, 0); + string_size = llvm_utils->create_gep2(string_descriptor, dest, 1); + string_capacity = llvm_utils->create_gep2(string_descriptor, dest, 2); + src_char_ptr = llvm_utils->CreateLoad2(character_type, + llvm_utils->create_gep2(string_descriptor, src, 0)); + llvm::Function *fn = module->getFunction(runtime_func_name); + if (!fn) { + llvm::FunctionType *function_type = llvm::FunctionType::get( + llvm::Type::getVoidTy(context), + { + llvm::Type::getInt8Ty(context)->getPointerTo()->getPointerTo(), + llvm::Type::getInt8Ty(context)->getPointerTo(), + llvm::Type::getInt64Ty(context)->getPointerTo(), + llvm::Type::getInt64Ty(context)->getPointerTo() + }, false); + fn = llvm::Function::Create(function_type, + llvm::Function::ExternalLinkage, runtime_func_name, *module); + } + return builder->CreateCall(fn, {dest_char_ptr, src_char_ptr, string_size, string_capacity}); + } } llvm::Value* lfortran_type_to_str(llvm::Value* arg, llvm::Type* value_type, std::string type, int value_kind) { @@ -807,61 +820,66 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor // float complex_re(complex a) // And it extracts the real part of the complex number llvm::Value *complex_re(llvm::Value *c, llvm::Type* complex_type=nullptr) { - get_builder0() if( complex_type == nullptr ) { complex_type = complex_type_4; } if( c->getType()->isPointerTy() ) { - c = CreateLoad(c); + c = llvm_utils->CreateLoad(c); } - llvm::AllocaInst *pc = builder0.CreateAlloca(complex_type, nullptr); + llvm::AllocaInst *pc = llvm_utils->CreateAlloca(*builder, complex_type); builder->CreateStore(c, pc); std::vector idx = { llvm::ConstantInt::get(context, llvm::APInt(32, 0)), llvm::ConstantInt::get(context, llvm::APInt(32, 0))}; - llvm::Value *pim = CreateGEP(pc, idx); - return CreateLoad(pim); + llvm::Value *pim = llvm_utils->CreateGEP2(complex_type, pc, idx); + if (complex_type == complex_type_4) { + return llvm_utils->CreateLoad2(llvm::Type::getFloatTy(context), pim); + } else { + return llvm_utils->CreateLoad2(llvm::Type::getDoubleTy(context), pim); + } } llvm::Value *complex_im(llvm::Value *c, llvm::Type* complex_type=nullptr) { - get_builder0() if( complex_type == nullptr ) { complex_type = complex_type_4; } - llvm::AllocaInst *pc = builder0.CreateAlloca(complex_type, nullptr); + llvm::AllocaInst *pc = llvm_utils->CreateAlloca(*builder, complex_type); builder->CreateStore(c, pc); std::vector idx = { llvm::ConstantInt::get(context, llvm::APInt(32, 0)), llvm::ConstantInt::get(context, llvm::APInt(32, 1))}; - llvm::Value *pim = CreateGEP(pc, idx); - return CreateLoad(pim); + llvm::Value *pim = llvm_utils->CreateGEP2(complex_type, pc, idx); + if (complex_type == complex_type_4) { + return llvm_utils->CreateLoad2(llvm::Type::getFloatTy(context), pim); + } else { + return llvm_utils->CreateLoad2(llvm::Type::getDoubleTy(context), pim); + } } llvm::Value *complex_from_floats(llvm::Value *re, llvm::Value *im, llvm::Type* complex_type=nullptr) { - get_builder0() if( complex_type == nullptr ) { complex_type = complex_type_4; } - llvm::AllocaInst *pres = builder0.CreateAlloca(complex_type, nullptr); + llvm::AllocaInst *pres = llvm_utils->CreateAlloca(*builder, complex_type); std::vector idx1 = { llvm::ConstantInt::get(context, llvm::APInt(32, 0)), llvm::ConstantInt::get(context, llvm::APInt(32, 0))}; std::vector idx2 = { llvm::ConstantInt::get(context, llvm::APInt(32, 0)), llvm::ConstantInt::get(context, llvm::APInt(32, 1))}; - llvm::Value *pre = CreateGEP(pres, idx1); - llvm::Value *pim = CreateGEP(pres, idx2); + llvm::Value *pre = llvm_utils->CreateGEP2(complex_type, pres, idx1); + llvm::Value *pim = llvm_utils->CreateGEP2(complex_type, pres, idx2); builder->CreateStore(re, pre); builder->CreateStore(im, pim); - return CreateLoad(pres); + return llvm_utils->CreateLoad2(complex_type, pres); } llvm::Value *nested_struct_rd(std::vector vals, llvm::StructType* rd) { - llvm::AllocaInst *pres = builder->CreateAlloca(rd, nullptr); - llvm::Value *pim = CreateGEP(pres, vals); - return CreateLoad(pim); + llvm::AllocaInst *pres = llvm_utils->CreateAlloca(*builder, rd); + llvm::Value *pim = llvm_utils->CreateGEP(pres, vals); + return llvm_utils->CreateLoad(pim); } /** @@ -877,13 +895,12 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor */ llvm::Value* lfortran_intrinsic(llvm::Function *fn, llvm::Value* pa, int a_kind) { - get_builder0() llvm::Type *presult_type = llvm_utils->getFPType(a_kind); - llvm::AllocaInst *presult = builder0.CreateAlloca(presult_type, nullptr); - llvm::Value *a = CreateLoad(pa); + llvm::AllocaInst *presult = llvm_utils->CreateAlloca(*builder, presult_type); + llvm::Value *a = llvm_utils->CreateLoad(pa); std::vector args = {a, presult}; builder->CreateCall(fn, args); - return CreateLoad(presult); + return llvm_utils->CreateLoad(presult); } void visit_TranslationUnit(const ASR::TranslationUnit_t &x) { @@ -910,7 +927,8 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor complex_type_4_ptr = llvm_utils->complex_type_4_ptr; complex_type_8_ptr = llvm_utils->complex_type_8_ptr; character_type = llvm_utils->character_type; - list_type = llvm::Type::getInt8PtrTy(context); + string_descriptor = llvm_utils->string_descriptor; + list_type = llvm::Type::getInt8Ty(context)->getPointerTo(); llvm::Type* bound_arg = static_cast(arr_descr->get_dimension_descriptor_type(true)); fname2arg_type["lbound"] = std::make_pair(bound_arg, bound_arg->getPointerTo()); @@ -919,7 +937,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor // Process Variables first: for (auto &item : x.m_symtab->get_scope()) { if (is_a(*item.second) || - is_a(*item.second)) { + is_a(*item.second)) { visit_symbol(*item.second); } } @@ -953,6 +971,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor std::vector build_order = determine_module_dependencies(x); for (auto &item : build_order) { + if (!item.compare("_lcompilers_mlir_gpu_offloading")) continue; LCOMPILERS_ASSERT(x.m_symtab->get_symbol(item) != nullptr); ASR::symbol_t *mod = x.m_symtab->get_symbol(item); @@ -992,6 +1011,8 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor if( n_dims == 0 ) { llvm::Function *fn = _Allocate(realloc); if (ASRUtils::is_character(*curr_arg_m_a_type)) { + LCOMPILERS_ASSERT_MSG(ASRUtils::is_descriptorString(expr_type(tmp_expr)), + "string isn't allocatable"); // TODO: Add ASR reference to capture the length of the string // during initialization. int64_t ptr_loads_copy = ptr_loads; @@ -1002,18 +1023,23 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor llvm::Value* m_len = tmp; llvm::Value* const_one = llvm::ConstantInt::get(context, llvm::APInt(32, 1)); llvm::Value* alloc_size = builder->CreateAdd(m_len, const_one); - std::vector args = {x_arr, alloc_size}; + std::vector args; + llvm::Value* ptr_to_init; + llvm::Value* char_ptr_ptr = llvm_utils->create_gep2(string_descriptor, x_arr, 0); // fetch char pointer + llvm::Value* size_ptr = llvm_utils->create_gep2(string_descriptor, x_arr, 1); // fetch size + llvm::Value* capacity_ptr = llvm_utils->create_gep2(string_descriptor, x_arr, 2); // fetch capacity + args = {char_ptr_ptr, alloc_size, size_ptr, capacity_ptr}; builder->CreateCall(fn, args); - builder->CreateMemSet(LLVM::CreateLoad(*builder, x_arr), - llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), llvm::APInt(8, 0)), - alloc_size, llvm::MaybeAlign()); + ptr_to_init = llvm_utils->CreateLoad2(llvm::Type::getInt8Ty(context)->getPointerTo(), char_ptr_ptr); + string_init(context, *module, *builder, alloc_size, ptr_to_init); } else if(ASR::is_a(*curr_arg_m_a_type) || - ASR::is_a(*curr_arg_m_a_type) || + ASR::is_a(*curr_arg_m_a_type) || ASR::is_a(*curr_arg_m_a_type)) { llvm::Value* malloc_size = SizeOfTypeUtil(curr_arg_m_a_type, llvm_utils->getIntType(4), ASRUtils::TYPE(ASR::make_Integer_t(al, x.base.base.loc, 4))); llvm::Value* malloc_ptr = LLVMArrUtils::lfortran_malloc( context, *module, *builder, malloc_size); + builder->CreateMemSet(malloc_ptr, llvm::ConstantInt::get(context, llvm::APInt(8, 0)), malloc_size, llvm::MaybeAlign()); llvm::Type* llvm_arg_type = llvm_utils->get_type_from_ttype_t_util(curr_arg_m_a_type, module.get()); builder->CreateStore(builder->CreateBitCast( malloc_ptr, llvm_arg_type->getPointerTo()), x_arr); @@ -1024,9 +1050,41 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor ASR::ttype_t* asr_data_type = ASRUtils::duplicate_type_without_dims(al, curr_arg_m_a_type, curr_arg_m_a_type->base.loc); llvm::Type* llvm_data_type = llvm_utils->get_type_from_ttype_t_util(asr_data_type, module.get()); - fill_malloc_array_details(x_arr, llvm_data_type, curr_arg.m_dims, curr_arg.n_dims, realloc); + llvm::Type* type = llvm_utils->get_type_from_ttype_t_util( + ASRUtils::type_get_past_pointer(ASRUtils::type_get_past_allocatable( + ASRUtils::expr_type(tmp_expr))), module.get()); + llvm_utils->create_if_else( + builder->CreateICmpEQ( + builder->CreatePtrToInt(llvm_utils->CreateLoad2(type->getPointerTo(), x_arr), llvm::Type::getInt32Ty(context)), + builder->CreatePtrToInt( + llvm::ConstantPointerNull::get(x_arr->getType()->getPointerTo()), + llvm::Type::getInt32Ty(context))), + [&]() { + llvm::Value* ptr_; + if(ASR::is_a(*ASRUtils::expr_type(tmp_expr))){ + //create memory on heap + std::vector idx_vec = { + llvm::ConstantInt::get(context, llvm::APInt(32, 1))}; + llvm::Value* null_array_ptr = llvm::ConstantPointerNull::get(type->getPointerTo()); + llvm::Value* size_of_array_struct = llvm_utils->CreateGEP2(type, null_array_ptr, idx_vec); + llvm::Value* size_of_array_struct_casted = builder->CreatePtrToInt(size_of_array_struct, llvm::Type::getInt32Ty(context)); //cast to int32 + llvm::Value* struct_ptr = LLVMArrUtils::lfortran_malloc( + context, *module, *builder, size_of_array_struct_casted); + ptr_ = builder->CreateBitCast(struct_ptr, type->getPointerTo()); +#if LLVM_VERSION_MAJOR > 16 + ptr_type[ptr_] = type; +#endif + arr_descr->fill_dimension_descriptor(ptr_, n_dims, module.get(), ASRUtils::expr_type(tmp_expr)); + } else { + ptr_ = llvm_utils->CreateAlloca(*builder, type); + arr_descr->fill_dimension_descriptor(ptr_, n_dims,nullptr,nullptr); + } + LLVM::CreateStore(*builder, ptr_, x_arr); + }, + []() {}); + fill_malloc_array_details(x_arr, type, llvm_data_type, curr_arg.m_dims, curr_arg.n_dims, realloc); if( ASR::is_a(*ASRUtils::extract_type(ASRUtils::expr_type(tmp_expr)))) { - allocate_array_members_of_struct_arrays(LLVM::CreateLoad(*builder, x_arr), + allocate_array_members_of_struct_arrays(llvm_utils->CreateLoad(x_arr), ASRUtils::expr_type(tmp_expr)); } } @@ -1077,21 +1135,37 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor void visit_Nullify(const ASR::Nullify_t& x) { for( size_t i = 0; i < x.n_vars; i++ ) { - std::uint32_t h = get_hash((ASR::asr_t*)x.m_vars[i]); + ASR::symbol_t* tmp_sym; + if (ASR::is_a(*x.m_vars[i])) { + tmp_sym = ASR::down_cast(x.m_vars[i])->m_m; + } else if (ASR::is_a(*x.m_vars[i])) { + tmp_sym = ASR::down_cast(x.m_vars[i])->m_v; + } else { + throw CodeGenError("Only StructInstanceMember and Variable are supported Nullify type"); + } + std::uint32_t h = get_hash((ASR::asr_t*)tmp_sym); llvm::Value *target = llvm_symtab[h]; - llvm::Type* tp = target->getType()->getContainedType(0); + llvm::Type* tp = llvm_utils->get_type_from_ttype_t_util( + ASRUtils::type_get_past_pointer( + ASRUtils::type_get_past_allocatable( + ASRUtils::symbol_type(tmp_sym))), module.get()); + + llvm::Type* dest_type = tp->getPointerTo(); + if (ASR::is_a(*ASRUtils::symbol_type(tmp_sym))) { + // functions are pointers in LLVM, so we do not need to get the pointer to it + dest_type = tp; + } llvm::Value* np = builder->CreateIntToPtr( - llvm::ConstantInt::get(context, llvm::APInt(32, 0)), tp); + llvm::ConstantInt::get(context, llvm::APInt(32, 0)), dest_type); builder->CreateStore(np, target); } } inline void call_lfortran_free(llvm::Function* fn, llvm::Type* llvm_data_type) { - get_builder0() - llvm::Value* arr = CreateLoad(arr_descr->get_pointer_to_data(tmp)); - llvm::AllocaInst *arg_arr = builder0.CreateAlloca(character_type, nullptr); + llvm::Value* arr = llvm_utils->CreateLoad2(llvm_data_type->getPointerTo(), arr_descr->get_pointer_to_data(tmp)); + llvm::AllocaInst *arg_arr = llvm_utils->CreateAlloca(*builder, character_type); builder->CreateStore(builder->CreateBitCast(arr, character_type), arg_arr); - std::vector args = {CreateLoad(arg_arr)}; + std::vector args = {llvm_utils->CreateLoad(arg_arr)}; builder->CreateCall(fn, args); arr_descr->reset_is_allocated_flag(tmp, llvm_data_type); } @@ -1103,7 +1177,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor llvm::FunctionType *function_type = llvm::FunctionType::get( llvm::Type::getVoidTy(context), { character_type - }, true); + }, false); free_fn = llvm::Function::Create(function_type, llvm::Function::ExternalLinkage, func_name, *module); } @@ -1130,8 +1204,10 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor llvm::FunctionType *function_type = llvm::FunctionType::get( llvm::Type::getVoidTy(context), { character_type->getPointerTo(), - llvm::Type::getInt32Ty(context) - }, true); + llvm::Type::getInt32Ty(context), + llvm::Type::getInt64Ty(context)->getPointerTo(), + llvm::Type::getInt64Ty(context)->getPointerTo() + }, false); alloc_fun = llvm::Function::Create(function_type, llvm::Function::ExternalLinkage, func_name, *module); } @@ -1140,7 +1216,6 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor template void visit_Deallocate(const T& x) { - get_builder0() llvm::Function* free_fn = _Deallocate(); for( size_t i = 0; i < x.n_vars; i++ ) { const ASR::expr_t* tmp_expr = x.m_vars[i]; @@ -1163,48 +1238,52 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor ASRUtils::expr_type(sm->m_v)); llvm::Value* dt = tmp; ASR::symbol_t *struct_sym = nullptr; + llvm::Type *dt_type = llvm_utils->getStructType(caller_type, module.get()); if (ASR::is_a(*caller_type)) { struct_sym = ASRUtils::symbol_get_past_external( ASR::down_cast(caller_type)->m_derived_type); - } else if (ASR::is_a(*caller_type)) { + } else if (ASR::is_a(*caller_type)) { struct_sym = ASRUtils::symbol_get_past_external( - ASR::down_cast(caller_type)->m_class_type); - dt = LLVM::CreateLoad(*builder, llvm_utils->create_gep(dt, 1)); + ASR::down_cast(caller_type)->m_class_type); + dt = llvm_utils->CreateLoad2(dt_type->getPointerTo(), llvm_utils->create_gep(dt, 1)); } else { LCOMPILERS_ASSERT(false); } int dt_idx = name2memidx[ASRUtils::symbol_name(struct_sym)] [ASRUtils::symbol_name(ASRUtils::symbol_get_past_external(sm->m_m))]; - llvm::Value* dt_1 = llvm_utils->create_gep(dt, dt_idx); + llvm::Value* dt_1 = llvm_utils->create_gep2(dt_type, dt, dt_idx); +#if LLVM_VERSION_MAJOR > 16 + llvm::Type *dt_1_type = llvm_utils->get_type_from_ttype_t_util( + ASRUtils::type_get_past_pointer(ASRUtils::type_get_past_allocatable( + ASRUtils::symbol_type(ASRUtils::symbol_get_past_external(sm->m_m)))), + module.get()); + ptr_type[dt_1] = dt_1_type; +#endif tmp = dt_1; } else { throw CodeGenError("Cannot deallocate variables in expression " + - std::to_string(tmp_expr->type), + ASRUtils::type_to_str_python(ASRUtils::expr_type(tmp_expr)), tmp_expr->base.loc); } ASR::ttype_t *cur_type = ASRUtils::expr_type(tmp_expr); int dims = ASRUtils::extract_n_dims_from_ttype(cur_type); if (dims == 0) { if (ASRUtils::is_character(*cur_type)) { - llvm::Value* tmp_ = tmp; - if( LLVM::is_llvm_pointer(*cur_type) ) { - tmp = LLVM::CreateLoad(*builder, tmp); - } - llvm::Value *cond = builder->CreateICmpNE( - builder->CreatePtrToInt(tmp, llvm::Type::getInt64Ty(context)), - builder->CreatePtrToInt(llvm::ConstantPointerNull::get(character_type), - llvm::Type::getInt64Ty(context)) ); - llvm_utils->create_if_else(cond, [=]() { - builder->CreateCall(free_fn, {tmp}); - builder->CreateStore( - llvm::ConstantPointerNull::get(character_type), tmp_); - }, [](){}); + llvm::Value* char_ptr, *size, *capacity; + char_ptr = llvm_utils->create_gep2(string_descriptor, tmp, 0); + size = llvm_utils->create_gep2(string_descriptor, tmp, 1); + capacity = llvm_utils->create_gep2(string_descriptor, tmp, 2); + + builder->CreateCall(_Deallocate(),{llvm_utils->CreateLoad2(character_type, char_ptr)}); + builder->CreateStore(llvm::ConstantPointerNull::getNullValue(llvm::Type::getInt8Ty(context)->getPointerTo()), char_ptr); + builder->CreateStore(llvm::ConstantInt::get(llvm::Type::getInt64Ty(context),0), size); + builder->CreateStore(llvm::ConstantInt::get(llvm::Type::getInt64Ty(context),0), capacity); continue; } else { llvm::Value* tmp_ = tmp; if( LLVM::is_llvm_pointer(*cur_type) ) { - tmp = LLVM::CreateLoad(*builder, tmp); + tmp = llvm_utils->CreateLoad(tmp); } llvm::Type* llvm_data_type = llvm_utils->get_type_from_ttype_t_util( ASRUtils::type_get_past_array( @@ -1217,9 +1296,9 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor llvm::ConstantPointerNull::get(llvm_data_type->getPointerTo()), llvm::Type::getInt64Ty(context)) ); llvm_utils->create_if_else(cond, [=]() { - llvm::AllocaInst *arg_tmp = builder->CreateAlloca(character_type, nullptr); + llvm::AllocaInst *arg_tmp = llvm_utils->CreateAlloca(*builder, character_type); builder->CreateStore(builder->CreateBitCast(tmp, character_type), arg_tmp); - std::vector args = {CreateLoad(arg_tmp)}; + std::vector args = {llvm_utils->CreateLoad(arg_tmp)}; builder->CreateCall(free_fn, args); builder->CreateStore( llvm::ConstantPointerNull::get(llvm_data_type->getPointerTo()), tmp_); @@ -1227,7 +1306,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } } else { if( LLVM::is_llvm_pointer(*cur_type) ) { - tmp = LLVM::CreateLoad(*builder, tmp); + tmp = llvm_utils->CreateLoad(tmp); } llvm::Type* llvm_data_type = llvm_utils->get_type_from_ttype_t_util( ASRUtils::type_get_past_array( @@ -1251,7 +1330,6 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } void visit_ListConstant(const ASR::ListConstant_t& x) { - get_builder0() ASR::List_t* list_type = ASR::down_cast(x.m_type); bool is_array_type_local = false, is_malloc_array_type_local = false; bool is_list_local = false; @@ -1263,7 +1341,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor n_dims_local, a_kind_local, module.get()); std::string type_code = ASRUtils::get_type_code(list_type->m_type); int32_t type_size = -1; - if( ASR::is_a(*list_type->m_type) || + if( ASR::is_a(*list_type->m_type) || LLVM::is_llvm_struct(list_type->m_type) || ASR::is_a(*list_type->m_type) ) { llvm::DataLayout data_layout(module.get()); @@ -1272,7 +1350,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor type_size = ASRUtils::extract_kind_from_ttype_t(list_type->m_type); } llvm::Type* const_list_type = list_api->get_list_type(llvm_el_type, type_code, type_size); - llvm::Value* const_list = builder0.CreateAlloca(const_list_type, nullptr, "const_list"); + llvm::Value* const_list = llvm_utils->CreateAlloca(*builder, const_list_type, nullptr, "const_list"); list_api->list_init(type_code, const_list, *module, x.n_args, x.n_args); int64_t ptr_loads_copy = ptr_loads; for( size_t i = 0; i < x.n_args; i++ ) { @@ -1292,9 +1370,8 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } void visit_DictConstant(const ASR::DictConstant_t& x) { - get_builder0() llvm::Type* const_dict_type = llvm_utils->get_dict_type(x.m_type, module.get()); - llvm::Value* const_dict = builder0.CreateAlloca(const_dict_type, nullptr, "const_dict"); + llvm::Value* const_dict = llvm_utils->CreateAlloca(*builder, const_dict_type, nullptr, "const_dict"); ASR::Dict_t* x_dict = ASR::down_cast(x.m_type); llvm_utils->set_dict_api(x_dict); std::string key_type_code = ASRUtils::get_type_code(x_dict->m_key_type); @@ -1318,9 +1395,8 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } void visit_SetConstant(const ASR::SetConstant_t& x) { - get_builder0() llvm::Type* const_set_type = llvm_utils->get_set_type(x.m_type, module.get()); - llvm::Value* const_set = builder0.CreateAlloca(const_set_type, nullptr, "const_set"); + llvm::Value* const_set = llvm_utils->CreateAlloca(*builder, const_set_type, nullptr, "const_set"); ASR::Set_t* x_set = ASR::down_cast(x.m_type); llvm_utils->set_set_api(x_set); std::string el_type_code = ASRUtils::get_type_code(x_set->m_type); @@ -1339,7 +1415,6 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } void visit_TupleConstant(const ASR::TupleConstant_t& x) { - get_builder0() ASR::Tuple_t* tuple_type = ASR::down_cast(x.m_type); std::string type_code = ASRUtils::get_type_code(tuple_type->m_type, tuple_type->n_type); @@ -1355,7 +1430,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor is_list, m_dims, n_dims, a_kind, module.get())); } llvm::Type* const_tuple_type = tuple_api->get_tuple_type(type_code, llvm_el_types); - llvm::Value* const_tuple = builder0.CreateAlloca(const_tuple_type, nullptr, "const_tuple"); + llvm::Value* const_tuple = llvm_utils->CreateAlloca(*builder, const_tuple_type, nullptr, "const_tuple"); std::vector init_values; int64_t ptr_loads_copy = ptr_loads; for( size_t i = 0; i < x.n_elements; i++ ) { @@ -1407,7 +1482,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor if (!fn) { llvm::FunctionType *function_type = llvm::FunctionType::get( llvm::Type::getInt32Ty(context), { - llvm::Type::getInt8PtrTy(context) + llvm::Type::getInt8Ty(context)->getPointerTo() }, false); fn = llvm::Function::Create(function_type, llvm::Function::ExternalLinkage, runtime_func_name, *module); @@ -1430,7 +1505,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor if (!fn) { llvm::FunctionType *function_type = llvm::FunctionType::get( llvm::Type::getInt32Ty(context), { - llvm::Type::getInt8PtrTy(context) + llvm::Type::getInt8Ty(context)->getPointerTo() }, false); fn = llvm::Function::Create(function_type, llvm::Function::ExternalLinkage, runtime_func_name, *module); @@ -1441,52 +1516,6 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } } - void visit_ArrayAll(const ASR::ArrayAll_t &x) { - if (x.m_value) { - this->visit_expr_wrapper(x.m_value, true); - return; - } - ASR::ttype_t *type_ = ASRUtils::expr_type(x.m_mask); - int64_t ptr_loads_copy = ptr_loads; - ptr_loads = 1 - !LLVM::is_llvm_pointer(*type_); - this->visit_expr(*x.m_mask); - ptr_loads = ptr_loads_copy; - llvm::Value *mask = tmp; - LCOMPILERS_ASSERT(ASRUtils::is_logical(*type_)); - int32_t n = ASRUtils::extract_n_dims_from_ttype(type_); - llvm::Value *size = llvm::ConstantInt::get(context, llvm::APInt(32, n)); - switch( ASRUtils::extract_physical_type(type_) ) { - case ASR::array_physical_typeType::DescriptorArray: { - mask = LLVM::CreateLoad(*builder, arr_descr->get_pointer_to_data(mask)); - break; - } - case ASR::array_physical_typeType::FixedSizeArray: { - mask = llvm_utils->create_gep(mask, 0); - break; - } - case ASR::array_physical_typeType::PointerToDataArray: { - // do nothing - break; - } - default: { - throw CodeGenError("Array physical type not supported", - x.base.base.loc); - } - } - std::string runtime_func_name = "_lfortran_all"; - llvm::Function *fn = module->getFunction(runtime_func_name); - if (!fn) { - llvm::FunctionType *function_type = llvm::FunctionType::get( - llvm::Type::getInt1Ty(context), { - llvm::Type::getInt1Ty(context)->getPointerTo(), - llvm::Type::getInt32Ty(context) - }, false); - fn = llvm::Function::Create(function_type, - llvm::Function::ExternalLinkage, runtime_func_name, *module); - } - tmp = builder->CreateCall(fn, {mask, size}); - } - void visit_RealSqrt(const ASR::RealSqrt_t &x) { if (x.m_value) { this->visit_expr_wrapper(x.m_value, true); @@ -1494,7 +1523,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } this->visit_expr(*x.m_arg); if (tmp->getType()->isPointerTy()) { - tmp = CreateLoad(tmp); + tmp = llvm_utils->CreateLoad2(x.m_type, tmp); } llvm::Value *c = tmp; int64_t kind_value = ASRUtils::extract_kind_from_ttype_t(ASRUtils::expr_type(x.m_arg)); @@ -1551,7 +1580,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor return ; } if( ptr_loads > 0 ) { - tmp = LLVM::CreateLoad(*builder, tmp); + tmp = llvm_utils->CreateLoad(tmp); } } @@ -1573,7 +1602,6 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } void visit_DictItem(const ASR::DictItem_t& x) { - get_builder0() ASR::Dict_t* dict_type = ASR::down_cast( ASRUtils::expr_type(x.m_a)); int64_t ptr_loads_copy = ptr_loads; @@ -1587,7 +1615,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor llvm::Value *key = tmp; if (x.m_default) { llvm::Type *val_type = llvm_utils->get_type_from_ttype_t_util(dict_type->m_value_type, module.get()); - llvm::Value *def_value_ptr = builder0.CreateAlloca(val_type, nullptr); + llvm::Value *def_value_ptr = llvm_utils->CreateAlloca(*builder, val_type); ptr_loads = !LLVM::is_llvm_struct(dict_type->m_value_type); this->visit_expr_wrapper(x.m_default, true); ptr_loads = ptr_loads_copy; @@ -1621,21 +1649,6 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor LLVM::is_llvm_struct(dict_type->m_value_type)); } - void visit_SetPop(const ASR::SetPop_t& x) { - ASR::Set_t* set_type = ASR::down_cast( - ASRUtils::expr_type(x.m_a)); - int64_t ptr_loads_copy = ptr_loads; - ptr_loads = 0; - this->visit_expr(*x.m_a); - llvm::Value* pset = tmp; - - ptr_loads = ptr_loads_copy; - - llvm_utils->set_set_api(set_type); - tmp = llvm_utils->set_api->pop_item(pset, *module, set_type->m_type); - } - - void visit_ListLen(const ASR::ListLen_t& x) { if (x.m_value) { this->visit_expr(*x.m_value); @@ -1685,90 +1698,6 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } } - void visit_DictClear(const ASR::DictClear_t& x) { - int64_t ptr_loads_copy = ptr_loads; - ptr_loads = 0; - this->visit_expr(*x.m_a); - llvm::Value* pdict = tmp; - ptr_loads = ptr_loads_copy; - ASR::Dict_t* dict_type = ASR::down_cast(ASRUtils::expr_type(x.m_a)); - - llvm_utils->dict_api->dict_clear(pdict, module.get(), dict_type->m_key_type, dict_type->m_value_type); - } - - void visit_SetClear(const ASR::SetClear_t& x) { - int64_t ptr_loads_copy = ptr_loads; - ptr_loads = 0; - this->visit_expr(*x.m_a); - llvm::Value* pset = tmp; - ptr_loads = ptr_loads_copy; - ASR::Set_t *set_type = ASR::down_cast( - ASRUtils::expr_type(x.m_a)); - - llvm_utils->set_api->set_clear(pset, module.get(), set_type->m_type); - } - - void visit_DictContains(const ASR::DictContains_t &x) { - if (x.m_value) { - this->visit_expr(*x.m_value); - return; - } - - int64_t ptr_loads_copy = ptr_loads; - ptr_loads = 0; - this->visit_expr(*x.m_right); - llvm::Value *right = tmp; - ASR::Dict_t *dict_type = ASR::down_cast( - ASRUtils::expr_type(x.m_right)); - ptr_loads = !LLVM::is_llvm_struct(dict_type->m_key_type); - this->visit_expr(*x.m_left); - llvm::Value *left = tmp; - ptr_loads = ptr_loads_copy; - llvm::Value *capacity = LLVM::CreateLoad(*builder, - llvm_utils->dict_api->get_pointer_to_capacity(right)); - get_builder0(); - llvm::AllocaInst *res = builder0.CreateAlloca(llvm::Type::getInt1Ty(context), nullptr); - llvm_utils->create_if_else(builder->CreateICmpEQ( - capacity, llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), llvm::APInt(32, 0))), - [&]() { - LLVM::CreateStore(*builder, llvm::ConstantInt::get(llvm::Type::getInt1Ty(context), llvm::APInt(1, 0)), res); - }, [&]() { - llvm::Value *key_hash = llvm_utils->dict_api->get_key_hash(capacity, left, dict_type->m_key_type, *module); - LLVM::CreateStore(*builder, llvm_utils->dict_api->resolve_collision_for_read_with_bound_check(right, key_hash, left, *module, dict_type->m_key_type, dict_type->m_value_type, true), res); - }); - tmp = LLVM::CreateLoad(*builder, res); - } - - void visit_SetContains(const ASR::SetContains_t &x) { - if (x.m_value) { - this->visit_expr(*x.m_value); - return; - } - - int64_t ptr_loads_copy = ptr_loads; - ptr_loads = 0; - this->visit_expr(*x.m_right); - llvm::Value *right = tmp; - ASR::ttype_t *el_type = ASRUtils::expr_type(x.m_left); - ptr_loads = !LLVM::is_llvm_struct(el_type); - this->visit_expr(*x.m_left); - llvm::Value *left = tmp; - ptr_loads = ptr_loads_copy; - llvm::Value *capacity = LLVM::CreateLoad(*builder, - llvm_utils->set_api->get_pointer_to_capacity(right)); - get_builder0(); - llvm::AllocaInst *res = builder0.CreateAlloca(llvm::Type::getInt1Ty(context), nullptr); - llvm_utils->create_if_else(builder->CreateICmpEQ( - capacity, llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), llvm::APInt(32, 0))), - [&]() { - LLVM::CreateStore(*builder, llvm::ConstantInt::get(llvm::Type::getInt1Ty(context), llvm::APInt(1, 0)), res); - }, [&]() { - llvm::Value *el_hash = llvm_utils->set_api->get_el_hash(capacity, left, el_type, *module); - LLVM::CreateStore(*builder, llvm_utils->set_api->resolve_collision_for_read_with_bound_check(right, el_hash, left, *module, el_type, false, true), res); - }); - tmp = LLVM::CreateLoad(*builder, res); - } - void visit_DictLen(const ASR::DictLen_t& x) { if (x.m_value) { this->visit_expr(*x.m_value); @@ -1978,7 +1907,6 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } void generate_DictElems(ASR::expr_t* m_arg, bool key_or_value) { - get_builder0() ASR::Dict_t* dict_type = ASR::down_cast( ASRUtils::expr_type(m_arg)); ASR::ttype_t* el_type = key_or_value == 0 ? @@ -2001,7 +1929,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor n_dims_local, a_kind_local, module.get()); std::string type_code = ASRUtils::get_type_code(el_type); int32_t type_size = -1; - if( ASR::is_a(*el_type) || + if( ASR::is_a(*el_type) || LLVM::is_llvm_struct(el_type) || ASR::is_a(*el_type) ) { llvm::DataLayout data_layout(module.get()); @@ -2010,7 +1938,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor type_size = ASRUtils::extract_kind_from_ttype_t(el_type); } llvm::Type* el_list_type = list_api->get_list_type(llvm_el_type, type_code, type_size); - llvm::Value* el_list = builder0.CreateAlloca(el_list_type, nullptr, key_or_value == 0 ? + llvm::Value* el_list = llvm_utils->CreateAlloca(*builder, el_list_type, nullptr, key_or_value == 0 ? "keys_list" : "values_list"); list_api->list_init(type_code, el_list, *module, 0, 0); @@ -2038,7 +1966,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor llvm_utils->set_api->write_item(pset, el, module.get(), asr_el_type, name2memidx); } - void generate_SetRemove(ASR::expr_t* m_arg, ASR::expr_t* m_ele, bool throw_key_error) { + void generate_SetRemove(ASR::expr_t* m_arg, ASR::expr_t* m_ele) { ASR::Set_t* set_type = ASR::down_cast( ASRUtils::expr_type(m_arg)); ASR::ttype_t* asr_el_type = ASRUtils::get_contained_type(ASRUtils::expr_type(m_arg)); @@ -2052,7 +1980,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor ptr_loads = ptr_loads_copy; llvm::Value *el = tmp; llvm_utils->set_set_api(set_type); - llvm_utils->set_api->remove_item(pset, el, *module, asr_el_type, throw_key_error); + llvm_utils->set_api->remove_item(pset, el, *module, asr_el_type); } void visit_IntrinsicElementalFunction(const ASR::IntrinsicElementalFunction_t& x) { @@ -2119,11 +2047,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor break; } case ASRUtils::IntrinsicElementalFunctions::SetRemove: { - generate_SetRemove(x.m_args[0], x.m_args[1], true); - break; - } - case ASRUtils::IntrinsicElementalFunctions::SetDiscard: { - generate_SetRemove(x.m_args[0], x.m_args[1], false); + generate_SetRemove(x.m_args[0], x.m_args[1]); break; } case ASRUtils::IntrinsicElementalFunctions::Exp: { @@ -2154,6 +2078,9 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } break ; } + case ASRUtils::IntrinsicElementalFunctions::CommandArgumentCount: { + break; + } case ASRUtils::IntrinsicElementalFunctions::Expm1: { switch (x.m_overload_id) { case 0: { @@ -2239,18 +2166,16 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } void visit_ListClear(const ASR::ListClear_t& x) { - ASR::List_t* asr_list = ASR::down_cast(ASRUtils::expr_type(x.m_a)); int64_t ptr_loads_copy = ptr_loads; ptr_loads = 0; this->visit_expr(*x.m_a); llvm::Value* plist = tmp; ptr_loads = ptr_loads_copy; - list_api->list_clear(plist, asr_list->m_type, module.get()); + list_api->list_clear(plist); } void visit_ListRepeat(const ASR::ListRepeat_t& x) { - get_builder0() this->visit_expr_wrapper(x.m_left, true); llvm::Value *left = tmp; ptr_loads = 2; // right is int always @@ -2268,7 +2193,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor n_dims_local, a_kind_local, module.get()); std::string type_code = ASRUtils::get_type_code(list_type->m_type); int32_t type_size = -1; - if( ASR::is_a(*list_type->m_type) || + if( ASR::is_a(*list_type->m_type) || LLVM::is_llvm_struct(list_type->m_type) || ASR::is_a(*list_type->m_type) ) { llvm::DataLayout data_layout(module.get()); @@ -2277,7 +2202,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor type_size = ASRUtils::extract_kind_from_ttype_t(list_type->m_type); } llvm::Type* repeat_list_type = list_api->get_list_type(llvm_el_type, type_code, type_size); - llvm::Value* repeat_list = builder0.CreateAlloca(repeat_list_type, nullptr, "repeat_list"); + llvm::Value* repeat_list = llvm_utils->CreateAlloca(*builder, repeat_list_type, nullptr, "repeat_list"); llvm::Value* left_len = list_api->len(left); llvm::Value* capacity = builder->CreateMul(left_len, right); list_api->list_init(type_code, repeat_list, *module, @@ -2341,7 +2266,6 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } void visit_TupleConcat(const ASR::TupleConcat_t& x) { - get_builder0() int64_t ptr_loads_copy = ptr_loads; ptr_loads = 0; this->visit_expr(*x.m_left); @@ -2382,7 +2306,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor v_type.push_back(al, tuple_type_right->m_type[i]); } llvm::Type* concat_tuple_type = tuple_api->get_tuple_type(type_code, llvm_el_types); - llvm::Value* concat_tuple = builder0.CreateAlloca(concat_tuple_type, nullptr, "concat_tuple"); + llvm::Value* concat_tuple = llvm_utils->CreateAlloca(*builder, concat_tuple_type, nullptr, "concat_tuple"); ASR::Tuple_t* tuple_type = (ASR::Tuple_t*)(ASR::make_Tuple_t( al, x.base.base.loc, v_type.p, v_type.n)); tuple_api->concat(left, right, tuple_type_left, tuple_type_right, concat_tuple, @@ -2391,7 +2315,6 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } void visit_ArrayItem(const ASR::ArrayItem_t& x) { - get_builder0() if (x.m_value) { this->visit_expr_wrapper(x.m_value, true); return; @@ -2429,11 +2352,11 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor this->visit_expr_wrapper(x.m_args[0].m_right, true); llvm::Value *p = nullptr; llvm::Value *idx = tmp; - llvm::Value *str = CreateLoad(array); + llvm::Value *str = llvm_utils->CreateLoad(array); if( is_assignment_target ) { idx = builder->CreateSub(idx, llvm::ConstantInt::get(context, llvm::APInt(32, 1))); std::vector idx_vec = {idx}; - p = CreateGEP(str, idx_vec); + p = llvm_utils->CreateGEP(str, idx_vec); } else { p = lfortran_str_item(str, idx); strings_to_be_deallocated.push_back(al, p); @@ -2443,7 +2366,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor tmp = p; if( ptr_loads == 0 ) { - tmp = builder->CreateAlloca(character_type, nullptr); + tmp = llvm_utils->CreateAlloca(*builder, character_type); builder->CreateStore(p, tmp); } @@ -2468,7 +2391,11 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor if ( LLVM::is_llvm_pointer(*x_mv_type) || ((is_bindc_array && !ASRUtils::is_fixed_size_array(m_dims, n_dims)) && ASR::is_a(*x.m_v)) ) { - array = CreateLoad(array); + llvm::Type *array_type = llvm_utils->get_type_from_ttype_t_util(x_mv_type_, module.get()); + array = llvm_utils->CreateLoad2(array_type->getPointerTo(), array); +#if LLVM_VERSION_MAJOR > 16 + ptr_type[array] = array_type; +#endif } Vec llvm_diminfo; @@ -2476,7 +2403,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor if( array_t->m_physical_type == ASR::array_physical_typeType::PointerToDataArray || array_t->m_physical_type == ASR::array_physical_typeType::FixedSizeArray || array_t->m_physical_type == ASR::array_physical_typeType::SIMDArray || - (array_t->m_physical_type == ASR::array_physical_typeType::CharacterArraySinglePointer && ASRUtils::is_fixed_size_array(x_mv_type)) ) { + (array_t->m_physical_type == ASR::array_physical_typeType::StringArraySinglePointer && ASRUtils::is_fixed_size_array(x_mv_type)) ) { int ptr_loads_copy = ptr_loads; for( size_t idim = 0; idim < x.n_args; idim++ ) { ptr_loads = 2 - !LLVM::is_llvm_pointer(*ASRUtils::expr_type(m_dims[idim].m_start)); @@ -2502,23 +2429,34 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor LCOMPILERS_ASSERT(ASRUtils::extract_n_dims_from_ttype(x_mv_type) > 0); bool is_polymorphic = current_select_type_block_type != nullptr; if (array_t->m_physical_type == ASR::array_physical_typeType::UnboundedPointerToDataArray) { - tmp = arr_descr->get_single_element(array, indices, x.n_args, + llvm::Type* type = llvm_utils->get_type_from_ttype_t_util(ASRUtils::extract_type(x_mv_type), module.get()); + tmp = arr_descr->get_single_element(type, array, indices, x.n_args, true, false, llvm_diminfo.p, is_polymorphic, current_select_type_block_type, true); } else { - tmp = arr_descr->get_single_element(array, indices, x.n_args, + llvm::Type* type; + bool is_fixed_size = (array_t->m_physical_type == ASR::array_physical_typeType::FixedSizeArray || + array_t->m_physical_type == ASR::array_physical_typeType::SIMDArray || + ( + array_t->m_physical_type == ASR::array_physical_typeType::StringArraySinglePointer && + ASRUtils::is_fixed_size_array(x_mv_type) + ) + ); + if (is_fixed_size) { + type = llvm_utils->get_type_from_ttype_t_util(x_mv_type, module.get()); + } else { + type = llvm_utils->get_type_from_ttype_t_util(ASRUtils::extract_type(x_mv_type), module.get()); + } + tmp = arr_descr->get_single_element(type, array, indices, x.n_args, array_t->m_physical_type == ASR::array_physical_typeType::PointerToDataArray, - array_t->m_physical_type == ASR::array_physical_typeType::FixedSizeArray || array_t->m_physical_type == ASR::array_physical_typeType::SIMDArray - || (array_t->m_physical_type == ASR::array_physical_typeType::CharacterArraySinglePointer && ASRUtils::is_fixed_size_array(x_mv_type)), - llvm_diminfo.p, is_polymorphic, current_select_type_block_type); + is_fixed_size, llvm_diminfo.p, is_polymorphic, current_select_type_block_type); } } } void visit_ArraySection(const ASR::ArraySection_t& x) { - get_builder0() if (x.m_value) { this->visit_expr_wrapper(x.m_value, true); return; @@ -2531,7 +2469,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor ASR::dimension_t* m_dims; [[maybe_unused]] int n_dims = ASRUtils::extract_dimensions_from_ttype( ASRUtils::expr_type(x.m_v), m_dims); - LCOMPILERS_ASSERT(ASR::is_a(*ASRUtils::expr_type(x.m_v)) && + LCOMPILERS_ASSERT(ASR::is_a(*ASRUtils::expr_type(x.m_v)) && n_dims == 0); // String indexing: if (x.n_args == 1) { @@ -2549,15 +2487,14 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor // idx = builder->CreateSub(idx, llvm::ConstantInt::get(context, llvm::APInt(32, 1))); //std::vector idx_vec = {llvm::ConstantInt::get(context, llvm::APInt(32, 0)), idx}; // std::vector idx_vec = {idx}; - llvm::Value *str = CreateLoad(array); + llvm::Value *str = llvm_utils->CreateLoad(array); // llvm::Value *p = CreateGEP(str, idx_vec); // TODO: Currently the string starts at the right location, but goes to the end of the original string. // We have to allocate a new string, copy it and add null termination. llvm::Value *step = llvm::ConstantInt::get(context, llvm::APInt(32, 1)); llvm::Value *present = llvm::ConstantInt::get(context, llvm::APInt(1, 1)); llvm::Value *p = lfortran_str_slice(str, idx1, idx2, step, present, present); - - tmp = builder->CreateAlloca(character_type, nullptr); + tmp = llvm_utils->CreateAlloca(*builder, character_type); builder->CreateStore(p, tmp); } @@ -2578,11 +2515,8 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor break; } case ASR::array_physical_typeType::FixedSizeArray: { - llvm::BasicBlock &entry_block = builder->GetInsertBlock()->getParent()->getEntryBlock(); - llvm::IRBuilder<> builder0(context); - builder0.SetInsertPoint(&entry_block, entry_block.getFirstInsertionPt()); llvm::Type* target_type = llvm_utils->get_type_from_ttype_t_util(x_m_array_type, module.get()); - llvm::Value *target = builder->CreateAlloca( + llvm::Value *target = llvm_utils->CreateAlloca( target_type, nullptr, "fixed_size_reshaped_array"); llvm::Value* target_ = llvm_utils->create_gep(target, 0); ASR::dimension_t* asr_dims = nullptr; @@ -2605,13 +2539,60 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } } + void visit_ArrayIsContiguous(const ASR::ArrayIsContiguous_t& x) { + ASR::ttype_t* x_m_array_type = ASRUtils::expr_type(x.m_array); + llvm::Type* array_type = llvm_utils->get_type_from_ttype_t_util( + ASRUtils::type_get_past_allocatable(ASRUtils::type_get_past_pointer(x_m_array_type)), module.get()); + int64_t ptr_loads_copy = ptr_loads; + ptr_loads = 2 - // Sync: instead of 2 - , should this be ptr_loads_copy - + (LLVM::is_llvm_pointer(*ASRUtils::expr_type(x.m_array))); + visit_expr_wrapper(x.m_array); + ptr_loads = ptr_loads_copy; + if (is_a(*x.m_array)) { + tmp = llvm_utils->CreateLoad2(array_type->getPointerTo(), tmp); + } + llvm::Value* llvm_arg1 = tmp; + ASR::array_physical_typeType physical_type = ASRUtils::extract_physical_type(x_m_array_type); + switch( physical_type ) { + case ASR::array_physical_typeType::DescriptorArray: { + llvm::Value* dim_des_val = arr_descr->get_pointer_to_dimension_descriptor_array(array_type, llvm_arg1); + llvm::Value* is_contiguous = llvm::ConstantInt::get(context, llvm::APInt(1, 1)); + ASR::dimension_t* m_dims = nullptr; + int n_dims = ASRUtils::extract_dimensions_from_ttype(x_m_array_type, m_dims); + llvm::Value* expected_stride = llvm::ConstantInt::get(context, llvm::APInt(32, 1)); + for (int i = 0; i < n_dims; i++) { + llvm::Value* dim_index = llvm::ConstantInt::get(context, llvm::APInt(32, i)); + llvm::Value* dim_desc = arr_descr->get_pointer_to_dimension_descriptor(dim_des_val, dim_index); + llvm::Value* dim_start = arr_descr->get_lower_bound(dim_desc); + llvm::Value* stride = arr_descr->get_stride(dim_desc); + llvm::Value* is_dim_contiguous = builder->CreateICmpEQ(stride, expected_stride); + is_contiguous = builder->CreateAnd(is_contiguous, is_dim_contiguous); + llvm::Value* dim_size = arr_descr->get_upper_bound(dim_desc); + expected_stride = builder->CreateMul(expected_stride, builder->CreateAdd(builder->CreateSub(dim_size, dim_start), llvm::ConstantInt::get(context, llvm::APInt(32, 1)))); + } + tmp = is_contiguous; + break; + } + case ASR::array_physical_typeType::FixedSizeArray: + case ASR::array_physical_typeType::SIMDArray: + tmp = llvm::ConstantInt::get(context, llvm::APInt(1, 1)); + break; + case ASR::array_physical_typeType::PointerToDataArray: + case ASR::array_physical_typeType::StringArraySinglePointer: + tmp = llvm::ConstantInt::get(context, llvm::APInt(1, 0)); + break; + default: + LCOMPILERS_ASSERT(false); + } + } + void lookup_EnumValue(const ASR::EnumValue_t& x) { - ASR::Enum_t* enum_t = ASR::down_cast(x.m_enum_type); - ASR::EnumType_t* enum_type = ASR::down_cast(enum_t->m_enum_type); + ASR::EnumType_t* enum_t = ASR::down_cast(x.m_enum_type); + ASR::Enum_t* enum_type = ASR::down_cast(enum_t->m_enum_type); uint32_t h = get_hash((ASR::asr_t*) enum_type); llvm::Value* array = llvm_symtab[h]; tmp = llvm_utils->create_gep(array, tmp); - tmp = LLVM::CreateLoad(*builder, llvm_utils->create_gep(tmp, 1)); + tmp = llvm_utils->CreateLoad(llvm_utils->create_gep(tmp, 1)); } void visit_EnumValue(const ASR::EnumValue_t& x) { @@ -2621,8 +2602,8 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } else if( ASR::is_a(*x.m_v) ) { ASR::EnumStaticMember_t* x_enum_member = ASR::down_cast(x.m_v); ASR::Variable_t* x_mv = ASR::down_cast(x_enum_member->m_m); - ASR::Enum_t* enum_t = ASR::down_cast(x.m_enum_type); - ASR::EnumType_t* enum_type = ASR::down_cast(enum_t->m_enum_type); + ASR::EnumType_t* enum_t = ASR::down_cast(x.m_enum_type); + ASR::Enum_t* enum_type = ASR::down_cast(enum_t->m_enum_type); for( size_t i = 0; i < enum_type->n_members; i++ ) { if( std::string(enum_type->m_members[i]) == std::string(x_mv->m_name) ) { tmp = llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), llvm::APInt(32, i)); @@ -2638,7 +2619,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor visit_expr(*x.m_v); if( ASR::is_a(*x.m_v) ) { - tmp = LLVM::CreateLoad(*builder, tmp); + tmp = llvm_utils->CreateLoad(tmp); } if( !ASR::is_a(*x.m_type) && lookup_enum_value_for_nonints ) { lookup_EnumValue(x); @@ -2653,10 +2634,10 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor visit_expr(*x.m_v); if( ASR::is_a(*x.m_v) ) { - tmp = LLVM::CreateLoad(*builder, tmp); + tmp = llvm_utils->CreateLoad(tmp); } - ASR::Enum_t* enum_t = ASR::down_cast(x.m_enum_type); - ASR::EnumType_t* enum_type = ASR::down_cast(enum_t->m_enum_type); + ASR::EnumType_t* enum_t = ASR::down_cast(x.m_enum_type); + ASR::Enum_t* enum_type = ASR::down_cast(enum_t->m_enum_type); uint32_t h = get_hash((ASR::asr_t*) enum_type); llvm::Value* array = llvm_symtab[h]; if( ASR::is_a(*enum_type->m_type) ) { @@ -2676,13 +2657,13 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } } - void visit_EnumTypeConstructor(const ASR::EnumTypeConstructor_t& x) { + void visit_EnumConstructor(const ASR::EnumConstructor_t& x) { LCOMPILERS_ASSERT(x.n_args == 1); ASR::expr_t* m_arg = x.m_args[0]; this->visit_expr(*m_arg); } - void visit_UnionTypeConstructor([[maybe_unused]] const ASR::UnionTypeConstructor_t& x) { + void visit_UnionConstructor([[maybe_unused]] const ASR::UnionConstructor_t& x) { LCOMPILERS_ASSERT(x.n_args == 0); } @@ -2709,22 +2690,23 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor ASR::ttype_t* x_m_v_type = ASRUtils::expr_type(x.m_v); int64_t ptr_loads_copy = ptr_loads; if( ASR::is_a(*x.m_v) || - ASR::is_a(*ASRUtils::type_get_past_pointer(x_m_v_type)) ) { + ASR::is_a(*ASRUtils::type_get_past_pointer(x_m_v_type)) ) { ptr_loads = 0; } else { ptr_loads = 2 - LLVM::is_llvm_pointer(*x_m_v_type); } this->visit_expr(*x.m_v); ptr_loads = ptr_loads_copy; - if( ASR::is_a(*ASRUtils::type_get_past_pointer( + if( ASR::is_a(*ASRUtils::type_get_past_pointer( ASRUtils::type_get_past_allocatable(x_m_v_type))) ) { if (ASRUtils::is_allocatable(x_m_v_type)) { - tmp = llvm_utils->create_gep(CreateLoad(tmp), 1); + tmp = llvm_utils->create_gep(llvm_utils->CreateLoad(tmp), 1); } else { - tmp = CreateLoad(llvm_utils->create_gep(tmp, 1)); + tmp = llvm_utils->CreateLoad2( + name2dertype[current_der_type_name]->getPointerTo(), llvm_utils->create_gep(tmp, 1)); } if( current_select_type_block_type ) { - tmp = builder->CreateBitCast(tmp, current_select_type_block_type); + tmp = builder->CreateBitCast(tmp, current_select_type_block_type->getPointerTo()); current_der_type_name = current_select_type_block_der_type; } else { // TODO: Select type by comparing with vtab @@ -2738,14 +2720,19 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor throw CodeGenError(current_der_type_name + " doesn't have any member named " + member_name, x.base.base.loc); } - tmp = llvm_utils->create_gep(tmp, 0); + tmp = llvm_utils->create_gep2(name2dertype[current_der_type_name], tmp, 0); current_der_type_name = dertype2parent[current_der_type_name]; } int member_idx = name2memidx[current_der_type_name][member_name]; - tmp = llvm_utils->create_gep(tmp, member_idx); + llvm::Type *xtype = name2dertype[current_der_type_name]; + tmp = llvm_utils->create_gep2(xtype, tmp, member_idx); ASR::ttype_t* member_type = ASRUtils::type_get_past_pointer( ASRUtils::type_get_past_allocatable(member->m_type)); +#if LLVM_VERSION_MAJOR > 16 + ptr_type[tmp] = llvm_utils->get_type_from_ttype_t_util( + member_type, module.get()); +#endif if( ASR::is_a(*member_type) ) { ASR::symbol_t *s_sym = ASR::down_cast( member_type)->m_derived_type; @@ -2755,29 +2742,100 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor if( llvm_symtab.find(h) != llvm_symtab.end() ) { tmp = llvm_symtab[h]; } - } else if ( ASR::is_a(*member_type) ) { - ASR::symbol_t *s_sym = ASR::down_cast( + } else if ( ASR::is_a(*member_type) ) { + ASR::symbol_t *s_sym = ASR::down_cast( member_type)->m_class_type; current_der_type_name = ASRUtils::symbol_name( ASRUtils::symbol_get_past_external(s_sym)); } } - void visit_Variable(const ASR::Variable_t &x) { - if (compiler_options.interactive && - std::strcmp(x.m_name, "_") == 0 && - x.m_abi == ASR::abiType::Interactive) { - return; + void visit_StructConstant(const ASR::StructConstant_t& x) { + std::vector elements; + llvm::StructType *t = llvm::cast(llvm_utils->getStructType(x.m_type, module.get())); + ASR::Struct_t* struct_ = ASR::down_cast(ASRUtils::symbol_get_past_external(x.m_dt_sym)); + + LCOMPILERS_ASSERT(x.n_args == struct_->n_members); + for (size_t i = 0; i < x.n_args; ++i) { + ASR::expr_t *value = x.m_args[i].m_value; + llvm::Constant* initializer = nullptr; + llvm::Type* type = nullptr; + if (value == nullptr) { + auto member2sym = struct_->m_symtab->get_scope(); + LCOMPILERS_ASSERT(member2sym[struct_->m_members[i]]->type == ASR::symbolType::Variable); + ASR::Variable_t *s = ASR::down_cast(member2sym[struct_->m_members[i]]); + type = llvm_utils->get_type_from_ttype_t_util(s->m_type, module.get()); + if (type->isArrayTy()) { + initializer = llvm::ConstantArray::getNullValue(type); + } else { + initializer = llvm::Constant::getNullValue(type); + } + } else if (ASR::is_a(*value)) { + ASR::ArrayConstant_t *arr_expr = ASR::down_cast(value); + type = llvm_utils->get_type_from_ttype_t_util(arr_expr->m_type, module.get()); + initializer = get_const_array(value, type); + } else { + visit_expr_wrapper(value); + initializer = llvm::dyn_cast(tmp); + if (!initializer) { + throw CodeGenError("Non-constant value found in struct initialization"); + } + } + elements.push_back(initializer); + } + tmp = llvm::ConstantStruct::get(t, elements); + } + + llvm::Constant* get_const_array(ASR::expr_t *value, llvm::Type* type) { + LCOMPILERS_ASSERT(ASR::is_a(*value)); + ASR::ArrayConstant_t* arr_const = ASR::down_cast(value); + std::vector arr_elements; + size_t arr_const_size = (size_t) ASRUtils::get_fixed_size_of_array(arr_const->m_type); + arr_elements.reserve(arr_const_size); + int a_kind; + for (size_t i = 0; i < arr_const_size; i++) { + ASR::expr_t* elem = ASRUtils::fetch_ArrayConstant_value(al, arr_const, i); + a_kind = ASRUtils::extract_kind_from_ttype_t(ASRUtils::expr_type(elem)); + if (ASR::is_a(*elem)) { + ASR::IntegerConstant_t* int_const = ASR::down_cast(elem); + arr_elements.push_back(llvm::ConstantInt::get( + context, llvm::APInt(8 * a_kind, int_const->m_n))); + } else if (ASR::is_a(*elem)) { + ASR::RealConstant_t* real_const = ASR::down_cast(elem); + if (a_kind == 4) { + arr_elements.push_back(llvm::ConstantFP::get( + context, llvm::APFloat((float) real_const->m_r))); + } else if (a_kind == 8) { + arr_elements.push_back(llvm::ConstantFP::get( + context, llvm::APFloat((double) real_const->m_r))); + } + } else if (ASR::is_a(*elem)) { + ASR::LogicalConstant_t* logical_const = ASR::down_cast(elem); + arr_elements.push_back(llvm::ConstantInt::get( + context, llvm::APInt(1, logical_const->m_value))); + } + } + llvm::ArrayType* arr_type = llvm::ArrayType::get(type, arr_const_size); + llvm::Constant* initializer = nullptr; + if (isNullValueArray(arr_elements)) { + initializer = llvm::ConstantArray::getNullValue(type); + } else { + initializer = llvm::ConstantArray::get(arr_type, arr_elements); } + return initializer; + } + + bool isNullValueArray(const std::vector& elements) { + return std::all_of(elements.begin(), elements.end(), + [](llvm::Constant* elem) { return elem->isNullValue(); }); + } + + void visit_Variable(const ASR::Variable_t &x) { if (x.m_value && x.m_storage == ASR::storage_typeType::Parameter) { this->visit_expr_wrapper(x.m_value, true); return; } uint32_t h = get_hash((ASR::asr_t*)&x); - if (compiler_options.interactive && - std::strcmp(x.m_name, compiler_options.po.global_underscore.c_str()) == 0) { - global_underscore_hash = h; - } // This happens at global scope, so the intent can only be either local // (global variable declared/initialized in this translation unit), or // external (global variable not declared/initialized in this @@ -2836,14 +2894,22 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } llvm_symtab[h] = ptr; } else if (x.m_type->type == ASR::ttypeType::Array) { - // Using approach same as ASR::ttypeType::List - llvm::StructType* array_type = static_cast( - llvm_utils->get_type_from_ttype_t_util(x.m_type, module.get())); - llvm::Constant *ptr = module->getOrInsertGlobal(x.m_name, array_type); + llvm::Type* type = llvm_utils->get_type_from_ttype_t_util(x.m_type, module.get()); + llvm::Constant *ptr = module->getOrInsertGlobal(x.m_name, type); if (!external) { - module->getNamedGlobal(x.m_name)->setInitializer( - llvm::ConstantStruct::get(array_type, - llvm::Constant::getNullValue(array_type))); + ASR::expr_t* value = nullptr; + if( x.m_value ) { + value = x.m_value; + } else if( x.m_symbolic_value && + ASRUtils::is_value_constant(x.m_symbolic_value) ) { + value = x.m_symbolic_value; + } + if (value) { + llvm::Constant* initializer = get_const_array(value, type); + module->getNamedGlobal(x.m_name)->setInitializer(initializer); + } else { + module->getNamedGlobal(x.m_name)->setInitializer(llvm::ConstantArray::getNullValue(type)); + } } llvm_symtab[h] = ptr; } else if (x.m_type->type == ASR::ttypeType::Logical) { @@ -2860,7 +2926,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } } llvm_symtab[h] = ptr; - } else if (x.m_type->type == ASR::ttypeType::Character) { + } else if (x.m_type->type == ASR::ttypeType::String) { llvm::Constant *ptr = module->getOrInsertGlobal(x.m_name, character_type); if (!external) { @@ -2871,7 +2937,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor module->getNamedGlobal(x.m_name)->setInitializer( llvm::Constant::getNullValue(character_type) ); - ASR::Character_t *t = down_cast(x.m_type); + ASR::String_t *t = down_cast(x.m_type); if( t->m_len >= 0 ) { strings_to_be_allocated.insert(std::pair(ptr, llvm::ConstantInt::get( context, llvm::APInt(32, t->m_len+1)))); @@ -2929,9 +2995,10 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } llvm_symtab[h] = ptr; } - } else if(x.m_type->type == ASR::ttypeType::Pointer) { + } else if(x.m_type->type == ASR::ttypeType::Pointer || + x.m_type->type == ASR::ttypeType::Allocatable) { ASR::dimension_t* m_dims = nullptr; - int n_dims = -1, a_kind = -1; + int n_dims = 0, a_kind = -1; bool is_array_type = false, is_malloc_array_type = false, is_list = false; llvm::Type* x_ptr = llvm_utils->get_type_from_ttype_t( x.m_type, nullptr, x.m_storage, is_array_type, @@ -2939,6 +3006,29 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor m_dims, n_dims, a_kind, module.get()); llvm::Constant *ptr = module->getOrInsertGlobal(x.m_name, x_ptr); + llvm::Type* type_ = llvm_utils->get_type_from_ttype_t_util( + ASRUtils::type_get_past_pointer( + ASRUtils::type_get_past_allocatable(x.m_type)), + module.get(), x.m_abi); +#if LLVM_VERSION_MAJOR > 16 + if ( LLVM::is_llvm_pointer(*x.m_type) && + ASR::is_a(*ASRUtils::type_get_past_pointer( + ASRUtils::type_get_past_allocatable(x.m_type))) ) { + ptr_type[ptr] = type_->getPointerTo(); + } else { + ptr_type[ptr] = type_; + } +#endif + if (ASRUtils::is_array(x.m_type)) { //memorize arrays only. + allocatable_array_details.push_back({ptr, + type_, + x.m_type, + ASRUtils::extract_dimensions_from_ttype(x.m_type, m_dims)}); + } + else if (ASRUtils::is_character(*x.m_type) && !init_value) { + // set all members of string_descriptor to null and zeroes. + init_value = llvm::ConstantAggregateZero::get(string_descriptor); + } if (!external) { if (init_value) { module->getNamedGlobal(x.m_name)->setInitializer( @@ -2955,56 +3045,107 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor llvm::StructType* list_type = static_cast( llvm_utils->get_type_from_ttype_t_util(x.m_type, module.get())); llvm::Constant *ptr = module->getOrInsertGlobal(x.m_name, list_type); - if (!external) { - module->getNamedGlobal(x.m_name)->setInitializer( - llvm::ConstantStruct::get(list_type, - llvm::Constant::getNullValue(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::Tuple) { llvm::StructType* tuple_type = static_cast( llvm_utils->get_type_from_ttype_t_util(x.m_type, module.get())); llvm::Constant *ptr = module->getOrInsertGlobal(x.m_name, tuple_type); - if (!external) { - module->getNamedGlobal(x.m_name)->setInitializer( - llvm::ConstantStruct::get(tuple_type, - llvm::Constant::getNullValue(tuple_type))); - } + module->getNamedGlobal(x.m_name)->setInitializer( + llvm::ConstantStruct::get(tuple_type, + llvm::Constant::getNullValue(tuple_type))); llvm_symtab[h] = ptr; } else if(x.m_type->type == ASR::ttypeType::Dict) { llvm::StructType* dict_type = static_cast( llvm_utils->get_type_from_ttype_t_util(x.m_type, module.get())); llvm::Constant *ptr = module->getOrInsertGlobal(x.m_name, dict_type); - if (!external) { - module->getNamedGlobal(x.m_name)->setInitializer( - llvm::ConstantStruct::get(dict_type, - llvm::Constant::getNullValue(dict_type))); - } + module->getNamedGlobal(x.m_name)->setInitializer( + llvm::ConstantStruct::get(dict_type, + llvm::Constant::getNullValue(dict_type))); llvm_symtab[h] = ptr; } else if(x.m_type->type == ASR::ttypeType::Set) { llvm::StructType* set_type = static_cast( llvm_utils->get_type_from_ttype_t_util(x.m_type, module.get())); llvm::Constant *ptr = module->getOrInsertGlobal(x.m_name, set_type); - if (!external) { - module->getNamedGlobal(x.m_name)->setInitializer( - llvm::ConstantStruct::get(set_type, - llvm::Constant::getNullValue(set_type))); - } + module->getNamedGlobal(x.m_name)->setInitializer( + llvm::ConstantStruct::get(set_type, + llvm::Constant::getNullValue(set_type))); llvm_symtab[h] = ptr; - } else if (x.m_type->type == ASR::ttypeType::TypeParameter) { - // Ignore type variables - } else { - throw CodeGenError("Variable type not supported " + std::to_string(x.m_type->type), x.base.base.loc); - } - } + } else if (x.m_type->type == ASR::ttypeType::Complex) { + int a_kind = ASRUtils::extract_kind_from_ttype_t(x.m_type); - void visit_PointerNullConstant(const ASR::PointerNullConstant_t& x){ - llvm::Type* value_type = llvm_utils->get_type_from_ttype_t_util(x.m_type, module.get()); - tmp = llvm::ConstantPointerNull::get(static_cast(value_type)); - } + llvm::Constant* re; + llvm::Constant* im; + llvm::Type* type = llvm_utils->get_type_from_ttype_t_util(x.m_type, module.get());; + llvm::Constant* ptr = module->getOrInsertGlobal(x.m_name, type); - void visit_EnumType(const ASR::EnumType_t& x) { - if( x.m_enum_value_type == ASR::enumtypeType::IntegerUnique && + if (!external) { + double x_re = 0.0, x_im = 0.0; + if (x.m_value) { + LCOMPILERS_ASSERT(ASR::is_a(*x.m_value)); + ASR::ComplexConstant_t* x_cc = ASR::down_cast(x.m_value); + x_re = x_cc->m_re; x_im = x_cc->m_im; + } + if (init_value) { + module->getNamedGlobal(x.m_name)->setInitializer(init_value); + } else { + switch (a_kind) { + case 4: { + re = llvm::ConstantFP::get(context, llvm::APFloat((float) x_re)); + im = llvm::ConstantFP::get(context, llvm::APFloat((float) x_im)); + type = complex_type_4; + break; + } + case 8: { + re = llvm::ConstantFP::get(context, llvm::APFloat((double) x_re)); + im = llvm::ConstantFP::get(context, llvm::APFloat((double) x_im)); + type = complex_type_8; + break; + } + default: { + throw CodeGenError("kind type is not supported"); + } + } + // Create a constant structure to represent the complex number + std::vector elements = { re, im }; + llvm::Constant* complex_init = llvm::ConstantStruct::get(static_cast(type), elements); + module->getNamedGlobal(x.m_name)->setInitializer(complex_init); + } + } + llvm_symtab[h] = ptr; + } else if (x.m_type->type == ASR::ttypeType::TypeParameter) { + // Ignore type variables + } else if (x.m_type->type == ASR::ttypeType::FunctionType) { + llvm::Type* type = llvm_utils->get_type_from_ttype_t_util(x.m_type, module.get()); + llvm::Constant *ptr = module->getOrInsertGlobal(x.m_name, type); + if (!external) { + if (init_value) { + module->getNamedGlobal(x.m_name)->setInitializer( + init_value); + } else { + module->getNamedGlobal(x.m_name)->setInitializer( + llvm::Constant::getNullValue(type) + ); + } + } + llvm_symtab[h] = ptr; +#if LLVM_VERSION_MAJOR > 16 + ptr_type[ptr] = type; +#endif + } else { + throw CodeGenError("Variable type not supported " + ASRUtils::type_to_str_python(x.m_type), x.base.base.loc); + } + } + + void visit_PointerNullConstant(const ASR::PointerNullConstant_t& x){ + llvm::Type* value_type = llvm_utils->get_type_from_ttype_t_util(x.m_type, module.get()); + tmp = llvm::ConstantPointerNull::get(static_cast(value_type)); + } + + void visit_Enum(const ASR::Enum_t& x) { + if( x.m_enum_value_type == ASR::enumtypeType::IntegerUnique && x.m_abi == ASR::abiType::BindC ) { throw CodeGenError("C-interoperation support for non-consecutive but uniquely " "valued integer enums isn't available yet."); @@ -3118,30 +3259,6 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } } - void instantiate_methods(const ASR::Struct_t &x) { - SymbolTable *current_scope_copy = current_scope; - current_scope = x.m_symtab; - for ( auto &item : x.m_symtab->get_scope() ) { - if ( is_a(*item.second) ) { - ASR::Function_t *v = down_cast(item.second); - instantiate_function(*v); - } - } - current_scope = current_scope_copy; - } - - void visit_methods (const ASR::Struct_t &x) { - SymbolTable *current_scope_copy = current_scope; - current_scope = x.m_symtab; - for ( auto &item : x.m_symtab->get_scope() ) { - if ( is_a(*item.second) ) { - ASR::Function_t *v = down_cast(item.second); - visit_Function(*v); - } - } - current_scope = current_scope_copy; - } - void start_module_init_function_prototype(const ASR::Module_t &x) { uint32_t h = get_hash((ASR::asr_t*)&x); llvm::FunctionType *function_type = llvm::FunctionType::get( @@ -3180,14 +3297,9 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor ASR::Function_t *v = down_cast( item.second); instantiate_function(*v); - } else if (is_a(*item.second)) { - ASR::EnumType_t *et = down_cast(item.second); - visit_EnumType(*et); - } else if (is_a(*item.second)) { - ASR::Struct_t *st = down_cast(item.second); - mangle_prefix = mangle_prefix + "__class_" + st->m_name + "_"; - instantiate_methods(*st); - mangle_prefix = "__module_" + std::string(x.m_name) + "_"; + } else if (is_a(*item.second)) { + ASR::Enum_t *et = down_cast(item.second); + visit_Enum(*et); } } finish_module_init_function_prototype(x); @@ -3197,6 +3309,22 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor current_scope = current_scope_copy; } +#ifdef HAVE_TARGET_WASM + void add_wasm_start_function() { + llvm::FunctionType *function_type = llvm::FunctionType::get( + llvm::Type::getVoidTy(context), {}, false); + llvm::Function *F = llvm::Function::Create(function_type, + llvm::Function::ExternalLinkage, "_start", module.get()); + llvm::BasicBlock *BB = llvm::BasicBlock::Create(context, ".entry", F); + builder->SetInsertPoint(BB); + std::vector args; + args.push_back(llvm::ConstantInt::get(context, llvm::APInt(32, 0))); + args.push_back(llvm_utils->CreateAlloca(*builder, character_type)); + builder->CreateCall(module->getFunction("main"), args); + builder->CreateRet(nullptr); + } +#endif + void visit_Program(const ASR::Program_t &x) { loop_head.clear(); loop_head_names.clear(); @@ -3215,16 +3343,6 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor set_api_lp->set_is_set_present(false); set_api_sc->set_is_set_present(false); llvm_goto_targets.clear(); - // Generate code for nested subroutines and functions first: - for (auto &item : x.m_symtab->get_scope()) { - if (is_a(*item.second)) { - ASR::Function_t *v = down_cast( - item.second); - instantiate_function(*v); - } - } - visit_procedures(x); - // Generate code for the main program std::vector command_line_args = { llvm::Type::getInt32Ty(context), @@ -3242,7 +3360,31 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor F->setSubprogram(SP); } builder->SetInsertPoint(BB); + // there maybe a possibility that nested function has an array variable + // whose dimension depends on variable present in this program / function + // thereby visit all integer variables and declare those: + for(auto &item: x.m_symtab->get_scope()) { + ASR::symbol_t* sym = item.second; + if ( is_a(*sym) ) { + ASR::Variable_t* v = down_cast(sym); + uint32_t debug_arg_count = 0; + if ( ASR::is_a(*v->m_type) ) { + process_Variable(sym, x, debug_arg_count); + } + } + } + + // Generate code for nested subroutines and functions first: + for (auto &item : x.m_symtab->get_scope()) { + if (is_a(*item.second)) { + ASR::Function_t *v = down_cast( + item.second); + instantiate_function(*v); + } + } + visit_procedures(x); + builder->SetInsertPoint(BB); // Call the `_lpython_call_initial_functions` function to assign command line argument // values to `argc` and `argv`, and set the random seed to the system clock. { @@ -3263,14 +3405,21 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } builder->CreateCall(fn, args); } - + for(to_be_allocated_array array : allocatable_array_details){ + fill_array_details_(array.pointer_to_array_type, array.array_type, nullptr, array.n_dims, + true, true, false, array.var_type); + } declare_vars(x); + for(variable_inital_value var_to_initalize : variable_inital_value_vec){ + set_VariableInital_value(var_to_initalize.v, var_to_initalize.target_var); + } for(auto &value: strings_to_be_allocated) { llvm::Value *init_value = LLVM::lfortran_malloc(context, *module, *builder, value.second); string_init(context, *module, *builder, value.second, init_value); builder->CreateStore(init_value, value.first); } + proc_return = llvm::BasicBlock::Create(context, "return"); for (size_t i=0; ivisit_stmt(*x.m_body[i]); } @@ -3279,6 +3428,18 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } call_lcompilers_free_strings(); + { + llvm::Function *fn = module->getFunction("_lpython_free_argv"); + if(!fn) { + llvm::FunctionType *function_type = llvm::FunctionType::get( + llvm::Type::getVoidTy(context), {}, false); + fn = llvm::Function::Create(function_type, + llvm::Function::ExternalLinkage, "_lpython_free_argv", *module); + } + builder->CreateCall(fn, {}); + } + + start_new_block(proc_return); llvm::Value *ret_val2 = llvm::ConstantInt::get(context, llvm::APInt(32, 0)); builder->CreateRet(ret_val2); @@ -3296,6 +3457,12 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor loop_or_block_end_names.clear(); heap_arrays.clear(); strings_to_be_deallocated.reserve(al, 1); + +#ifdef HAVE_TARGET_WASM + if (startswith(compiler_options.target, "wasm")) { + add_wasm_start_function(); + } +#endif } /* @@ -3325,8 +3492,8 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor llvm::Type* llvm_data_type = llvm_utils->get_type_from_ttype_t_util(asr_data_type, module.get()); llvm::Value* ptr_ = nullptr; if( is_malloc_array_type && !is_list && !is_data_only ) { - ptr_ = builder->CreateAlloca(type_, nullptr, "arr_desc"); - arr_descr->fill_dimension_descriptor(ptr_, n_dims); + ptr_ = llvm_utils->CreateAlloca(*builder, type_, nullptr, "arr_desc"); + arr_descr->fill_dimension_descriptor(ptr_, n_dims, nullptr, nullptr); } if( is_array_type && !is_malloc_array_type && !is_list ) { @@ -3347,10 +3514,20 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor ASR::is_a(*v->m_type)) && \ (v->m_intent == ASRUtils::intent_local || \ v->m_intent == ASRUtils::intent_return_var ) && \ - !ASR::is_a( \ + !ASR::is_a( \ *ASRUtils::type_get_past_allocatable( \ - ASRUtils::type_get_past_pointer(v->m_type))) ) { \ - builder->CreateStore(null_value, ptr); \ + ASRUtils::type_get_past_pointer(v->m_type)))) { \ + if(ASRUtils::is_descriptorString(v->m_type)){ \ + /*set string descriptor to {char* null, int64 0, int 64 0} */ \ + builder->CreateStore(llvm::ConstantPointerNull::getNullValue(llvm::Type::getInt8Ty(context)->getPointerTo()),\ + llvm_utils->create_gep2(string_descriptor, ptr, 0));\ + builder->CreateStore(llvm::ConstantInt::get(llvm::Type::getInt64Ty(context),0),\ + llvm_utils->create_gep2(string_descriptor, ptr, 1));\ + builder->CreateStore(llvm::ConstantInt::get(llvm::Type::getInt64Ty(context),0),\ + llvm_utils->create_gep2(string_descriptor, ptr, 2));\ + } else { \ + builder->CreateStore(null_value, ptr); \ + }\ } \ void allocate_array_members_of_struct(llvm::Value* ptr, ASR::ttype_t* asr_type) { @@ -3366,14 +3543,15 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } if( ASR::is_a(*sym) || ASR::is_a(*sym) || - ASR::is_a(*sym) || + ASR::is_a(*sym) || ASR::is_a(*sym) || ASR::is_a(*sym) ) { continue ; } ASR::ttype_t* symbol_type = ASRUtils::symbol_type(sym); int idx = name2memidx[struct_type_name][item.first]; - llvm::Value* ptr_member = llvm_utils->create_gep(ptr, idx); + llvm::Type* type = name2dertype[struct_type_name]; + llvm::Value* ptr_member = llvm_utils->create_gep2(type, ptr, idx); ASR::Variable_t* v = nullptr; if( ASR::is_a(*sym) ) { v = ASR::down_cast(sym); @@ -3391,10 +3569,10 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor ASR::array_physical_typeType phy_type = ASRUtils::extract_physical_type(symbol_type); bool is_data_only = (phy_type == ASR::array_physical_typeType::PointerToDataArray || phy_type == ASR::array_physical_typeType::FixedSizeArray || - (phy_type == ASR::array_physical_typeType::CharacterArraySinglePointer && + (phy_type == ASR::array_physical_typeType::StringArraySinglePointer && ASRUtils::is_fixed_size_array(symbol_type))); if (phy_type == ASR::array_physical_typeType::DescriptorArray || - (phy_type == ASR::array_physical_typeType::CharacterArraySinglePointer && + (phy_type == ASR::array_physical_typeType::StringArraySinglePointer && ASRUtils::is_dimension_empty(m_dims, n_dims))) { int n_dims = 0, a_kind=4; ASR::dimension_t* m_dims = nullptr; @@ -3421,7 +3599,9 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor void allocate_array_members_of_struct_arrays(llvm::Value* ptr, ASR::ttype_t* v_m_type) { ASR::array_physical_typeType phy_type = ASRUtils::extract_physical_type(v_m_type); - llvm::Value* array_size = CreateAlloca( + llvm::Type* el_type = llvm_utils->get_type_from_ttype_t_util( + ASRUtils::extract_type(v_m_type), module.get()); + llvm::Value* array_size = llvm_utils->CreateAlloca( llvm::Type::getInt32Ty(context), nullptr, "array_size"); switch( phy_type ) { case ASR::array_physical_typeType::FixedSizeArray: { @@ -3454,12 +3634,12 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor LCOMPILERS_ASSERT_MSG(false, std::to_string(phy_type)); } } - llvm::Value* llvmi = CreateAlloca(llvm::Type::getInt32Ty(context), nullptr, "i"); + llvm::Value* llvmi = llvm_utils->CreateAlloca(llvm::Type::getInt32Ty(context), nullptr, "i"); LLVM::CreateStore(*builder, llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), llvm::APInt(32, 0)), llvmi); create_loop(nullptr, [=]() { - llvm::Value* llvmi_loaded = LLVM::CreateLoad(*builder, llvmi); - llvm::Value* array_size_loaded = LLVM::CreateLoad(*builder, array_size); + llvm::Value* llvmi_loaded = llvm_utils->CreateLoad(llvmi); + llvm::Value* array_size_loaded = llvm_utils->CreateLoad(array_size); return builder->CreateICmpSLT( llvmi_loaded, array_size_loaded); }, @@ -3467,17 +3647,17 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor llvm::Value* ptr_i = nullptr; switch (phy_type) { case ASR::array_physical_typeType::FixedSizeArray: { - ptr_i = llvm_utils->create_gep(ptr, LLVM::CreateLoad(*builder, llvmi)); + ptr_i = llvm_utils->create_gep(ptr, llvm_utils->CreateLoad(llvmi)); break; } case ASR::array_physical_typeType::DescriptorArray: { - ptr_i = llvm_utils->create_ptr_gep( - LLVM::CreateLoad(*builder, arr_descr->get_pointer_to_data(ptr)), - LLVM::CreateLoad(*builder, llvmi)); + ptr_i = llvm_utils->create_ptr_gep2(el_type, + llvm_utils->CreateLoad2(el_type->getPointerTo(), arr_descr->get_pointer_to_data(ptr)), + llvm_utils->CreateLoad(llvmi)); break; } case ASR::array_physical_typeType::PointerToDataArray: { - ptr_i = llvm_utils->create_ptr_gep(ptr, LLVM::CreateLoad(*builder, llvmi)); + ptr_i = llvm_utils->create_ptr_gep(ptr, llvm_utils->CreateLoad(llvmi)); break; } default: { @@ -3487,7 +3667,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor allocate_array_members_of_struct( ptr_i, ASRUtils::extract_type(v_m_type)); LLVM::CreateStore(*builder, - builder->CreateAdd(LLVM::CreateLoad(*builder, llvmi), + builder->CreateAdd(llvm_utils->CreateLoad(llvmi), llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), llvm::APInt(32, 1))), llvmi); }); @@ -3508,8 +3688,8 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor std::string(struct_type_t->m_name)); } llvm::Type* vtab_type = type2vtabtype[struct_type_sym]; - llvm::Value* vtab_obj = builder->CreateAlloca(vtab_type); - llvm::Value* struct_type_hash_ptr = llvm_utils->create_gep(vtab_obj, 0); + llvm::Value* vtab_obj = llvm_utils->CreateAlloca(*builder, vtab_type); + llvm::Value* struct_type_hash_ptr = llvm_utils->create_gep2(vtab_type, vtab_obj, 0); llvm::Value* struct_type_hash = llvm::ConstantInt::get(llvm_utils->getIntType(8), llvm::APInt(64, get_class_hash(struct_type_sym))); builder->CreateStore(struct_type_hash, struct_type_hash_ptr); @@ -3543,8 +3723,8 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor if (ASR::is_a(*var_sym)) { ASR::Variable_t *v = ASR:: down_cast(var_sym); ASR::ttype_t* v_type = ASRUtils::type_get_past_pointer(v->m_type); - if( ASR::is_a(*v_type) ) { - ASR::Class_t* v_class_t = ASR::down_cast(v_type); + if( ASR::is_a(*v_type) ) { + ASR::ClassType_t* v_class_t = ASR::down_cast(v_type); class_type_names.insert(ASRUtils::symbol_name(v_class_t->m_class_type)); } } else if (ASR::is_a( @@ -3554,10 +3734,323 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } collect_class_type_names_and_struct_types(class_type_names, struct_types, x_symtab->parent); } + void set_VariableInital_value(ASR::Variable_t* v, llvm::Value* target_var){ + if (v->m_value != nullptr) { + this->visit_expr_wrapper(v->m_value, true); + } else { + this->visit_expr_wrapper(v->m_symbolic_value, true); + } + llvm::Value *init_value = tmp; + if( ASRUtils::is_array(v->m_type) && + ASRUtils::is_array(ASRUtils::expr_type(v->m_symbolic_value)) && + (ASR::is_a(*v->m_symbolic_value) || + (v->m_value && ASR::is_a(*v->m_value)))) { + ASR::array_physical_typeType target_ptype = ASRUtils::extract_physical_type(v->m_type); + if( target_ptype == ASR::array_physical_typeType::DescriptorArray ) { + target_var = arr_descr->get_pointer_to_data(target_var); + builder->CreateStore(init_value, target_var); + } else if( target_ptype == ASR::array_physical_typeType::FixedSizeArray ) { + llvm::Value* arg_size = llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), + llvm::APInt(32, ASRUtils::get_fixed_size_of_array(ASR::down_cast(v->m_value)->m_type))); + llvm::Type* llvm_data_type = llvm_utils->get_type_from_ttype_t_util( + ASRUtils::type_get_past_array(ASRUtils::expr_type(v->m_value)), module.get()); + llvm::DataLayout data_layout(module.get()); + size_t dt_size = data_layout.getTypeAllocSize(llvm_data_type); + arg_size = builder->CreateMul(llvm::ConstantInt::get( + llvm::Type::getInt32Ty(context), llvm::APInt(32, dt_size)), arg_size); + builder->CreateMemCpy(llvm_utils->create_gep(target_var, 0), + llvm::MaybeAlign(), init_value, llvm::MaybeAlign(), arg_size); + } + } else if (ASR::is_a(*v->m_symbolic_value)) { + builder->CreateStore(llvm_utils->CreateLoad(init_value), target_var); + } else if (is_a(*v->m_type)) { + ASR::String_t *t = down_cast(v->m_type); + llvm::Value *arg_size = llvm::ConstantInt::get(context, + llvm::APInt(32, t->m_len+1)); + llvm::Value *s_malloc = LLVM::lfortran_malloc(context, *module, *builder, arg_size); + string_init(context, *module, *builder, arg_size, s_malloc); + builder->CreateStore(s_malloc, target_var); + // target decides if the str_copy is performed on string descriptor or pointer. + tmp = lfortran_str_copy(target_var, init_value, ASRUtils::is_descriptorString(v->m_type)); + if (v->m_intent == intent_local) { + strings_to_be_deallocated.push_back(al, llvm_utils->CreateLoad2(v->m_type, target_var)); + } + } else { + if (v->m_storage == ASR::storage_typeType::Save + && v->m_value + && (ASR::is_a(*v->m_type) + || ASR::is_a(*v->m_type) + || ASR::is_a(*v->m_type))) { + // Do nothing, the value is already initialized + // in the global variable + } else { + builder->CreateStore(init_value, target_var); + } + } + } + + template + void process_Variable(ASR::symbol_t* var_sym, T& x, uint32_t &debug_arg_count) { + llvm::Value *target_var = nullptr; + ASR::Variable_t *v = down_cast(var_sym); + uint32_t h = get_hash((ASR::asr_t*)v); + llvm::Type *type; + int n_dims = 0, a_kind = 4; + ASR::dimension_t* m_dims = nullptr; + bool is_array_type = false; + bool is_malloc_array_type = false; + bool is_list = false; + if (v->m_intent == intent_local || + v->m_intent == intent_return_var || + !v->m_intent) { + type = llvm_utils->get_type_from_ttype_t( + v->m_type, v->m_type_declaration, v->m_storage, is_array_type, + is_malloc_array_type, is_list, m_dims, n_dims, a_kind, module.get()); + llvm::Type* type_ = llvm_utils->get_type_from_ttype_t_util( + ASRUtils::type_get_past_pointer( + ASRUtils::type_get_past_allocatable(v->m_type)), module.get(), v->m_abi); + + /* + * The following if block is used for converting any + * general array descriptor to a pointer type which + * can be passed as an argument in a function call in LLVM IR. + */ + if( x.class_type == ASR::symbolType::Function) { + std::string m_name = std::string(x.m_name); + ASR::Function_t* _func = (ASR::Function_t*)(&(x.base)); + std::uint32_t m_h = get_hash((ASR::asr_t*)_func); + ASR::abiType abi_type = ASRUtils::get_FunctionType(_func)->m_abi; + bool is_v_arg = is_argument(v, _func->m_args, _func->n_args); + if( is_array_type && !is_list ) { + /* The first element in an array descriptor can be either of + * llvm::ArrayType or llvm::PointerType. However, a + * function only accepts llvm::PointerType for arrays. Hence, + * the following if block extracts the pointer to first element + * of an array from its descriptor. Note that this happens only + * for arguments and not for local function variables. + */ + if( abi_type == ASR::abiType::Source && is_v_arg ) { + type = arr_descr->get_argument_type(type, m_h, v->m_name, arr_arg_type_cache); + is_array_type = false; + } else if( abi_type == ASR::abiType::Intrinsic && + fname2arg_type.find(m_name) != fname2arg_type.end() ) { + type = fname2arg_type[m_name].second; + is_array_type = false; + } + } + } + + llvm::Value* array_size = nullptr; + if( ASRUtils::is_array(v->m_type) && + ASRUtils::extract_physical_type(v->m_type) == + ASR::array_physical_typeType::PointerToDataArray && + !LLVM::is_llvm_pointer(*v->m_type) ) { + type = llvm_utils->get_type_from_ttype_t( + ASRUtils::type_get_past_array(v->m_type), + v->m_type_declaration, v->m_storage, is_array_type, + is_malloc_array_type, is_list, m_dims, n_dims, a_kind, module.get()); + ASR::dimension_t* m_dims = nullptr; + size_t n_dims = ASRUtils::extract_dimensions_from_ttype(v->m_type, m_dims); + array_size = llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), llvm::APInt(32, 1)); + int ptr_loads_copy = ptr_loads; + ptr_loads = 2; + for( size_t i = 0; i < n_dims; i++ ) { + this->visit_expr_wrapper(m_dims[i].m_length, true); + + if (m_dims[i].m_length != nullptr && ASR::is_a(*m_dims[i].m_length)) { + ASR::Var_t* m_length_var = ASR::down_cast(m_dims[i].m_length); + ASR::symbol_t* m_length_sym = ASRUtils::symbol_get_past_external(m_length_var->m_v); + if (m_length_sym != nullptr && ASR::is_a(*m_length_sym)) { + ASR::Variable_t* m_length_variable = ASR::down_cast(m_length_sym); + uint32_t m_length_variable_h = get_hash((ASR::asr_t*)m_length_variable); + llvm::Type* deep_type = llvm_utils->get_type_from_ttype_t_util(ASRUtils::expr_type(m_dims[i].m_length),module.get()); + llvm::Value* deep = llvm_utils->CreateAlloca(*builder, deep_type, nullptr, "deep"); + builder->CreateStore(tmp, deep); + tmp = llvm_utils->CreateLoad2(ASRUtils::expr_type(m_dims[i].m_length),deep); + llvm_symtab_deep_copy[m_length_variable_h] = deep; + } + } + + // Make dimension length and return size compatible.(TODO : array_size should be of type int64) + if(ASRUtils::extract_kind_from_ttype_t( + ASRUtils::expr_type(m_dims[i].m_length)) > 4){ + tmp = builder->CreateTrunc(tmp, llvm::IntegerType::get(context, 32)); + } else if (ASRUtils::extract_kind_from_ttype_t( + ASRUtils::expr_type(m_dims[i].m_length)) < 4){ + tmp = builder->CreateSExt(tmp, llvm::IntegerType::get(context, 32)); + } + + array_size = builder->CreateMul(array_size, tmp); + } + ptr_loads = ptr_loads_copy; + } + llvm::Value *ptr = nullptr; + if( !compiler_options.stack_arrays && array_size ) { + llvm::DataLayout data_layout(module.get()); + uint64_t size = data_layout.getTypeAllocSize(type); + array_size = builder->CreateMul(array_size, + llvm::ConstantInt::get(context, llvm::APInt(32, size))); + llvm::Value* ptr_i8 = LLVMArrUtils::lfortran_malloc( + context, *module, *builder, array_size); + heap_arrays.push_back(ptr_i8); + ptr = builder->CreateBitCast(ptr_i8, type->getPointerTo()); + } else { + if (v->m_storage == ASR::storage_typeType::Save) { + std::string parent_function_name = std::string(x.m_name); + std::string global_name = parent_function_name+ "." + v->m_name; + ptr = module->getOrInsertGlobal(global_name, type); + llvm::GlobalVariable *gptr = module->getNamedGlobal(global_name); + gptr->setLinkage(llvm::GlobalValue::InternalLinkage); + llvm::Constant *init_value; + if (v->m_value + && (ASR::is_a(*v->m_type) + || ASR::is_a(*v->m_type) + || ASR::is_a(*v->m_type))) { + this->visit_expr(*v->m_value); + init_value = llvm::dyn_cast(tmp); + } else { + init_value = llvm::Constant::getNullValue(type); + } + gptr->setInitializer(init_value); +#if LLVM_VERSION_MAJOR > 16 + ptr_type[ptr] = type; +#endif + } else { +#if LLVM_VERSION_MAJOR > 16 + bool is_llvm_ptr = false; + if ( LLVM::is_llvm_pointer(*v->m_type) && + !ASR::is_a(*ASRUtils::type_get_past_pointer( + ASRUtils::type_get_past_allocatable(v->m_type))) && + !ASRUtils::is_descriptorString(v->m_type) ) { + is_llvm_ptr = true; + } + ptr = llvm_utils->CreateAlloca(*builder, type_, array_size, + v->m_name, is_llvm_ptr); +#else + ptr = llvm_utils->CreateAlloca(*builder, type, array_size, v->m_name); +#endif + } + } + set_pointer_variable_to_null(llvm::ConstantPointerNull::get( + static_cast(type)), ptr) + if( ASR::is_a( + *ASRUtils::type_get_past_array(v->m_type)) ) { + if( ASRUtils::is_array(v->m_type) ) { + allocate_array_members_of_struct_arrays(ptr, v->m_type); + } else { + allocate_array_members_of_struct(ptr, v->m_type); + } + } + if (compiler_options.emit_debug_info) { + // Reset the debug location + builder->SetCurrentDebugLocation(nullptr); + uint32_t line, column; + if (compiler_options.emit_debug_line_column) { + debug_get_line_column(v->base.base.loc.first, line, column); + } else { + line = v->base.base.loc.first; + column = 0; + } + std::string type_name; + uint32_t type_size, type_encoding; + get_type_debug_info(v->m_type, type_name, type_size, + type_encoding); + llvm::DILocalVariable *debug_var = DBuilder->createParameterVariable( + debug_current_scope, v->m_name, ++debug_arg_count, debug_Unit, line, + DBuilder->createBasicType(type_name, type_size, type_encoding), true); + DBuilder->insertDeclare(ptr, debug_var, DBuilder->createExpression(), + llvm::DILocation::get(debug_current_scope->getContext(), + line, 0, debug_current_scope), builder->GetInsertBlock()); + } + + if( ASR::is_a(*v->m_type) ) { + ASR::StructType_t* struct_t = ASR::down_cast(v->m_type); + ASR::Struct_t* struct_type = ASR::down_cast( + ASRUtils::symbol_get_past_external(struct_t->m_derived_type)); + int64_t alignment_value = -1; + if( ASRUtils::extract_value(struct_type->m_alignment, alignment_value) ) { + llvm::Align align(alignment_value); + reinterpret_cast(ptr)->setAlignment(align); + } + } + llvm_symtab[h] = ptr; + if( (ASRUtils::is_array(v->m_type) && + ((ASRUtils::extract_physical_type(v->m_type) == ASR::array_physical_typeType::DescriptorArray) || + (ASRUtils::extract_physical_type(v->m_type) == ASR::array_physical_typeType::StringArraySinglePointer && + ASRUtils::is_dimension_empty(m_dims,n_dims)))) + ) { + fill_array_details_(ptr, type_, m_dims, n_dims, + is_malloc_array_type, is_array_type, is_list, v->m_type); + } + ASR::expr_t* init_expr = v->m_symbolic_value; + if( v->m_storage != ASR::storage_typeType::Parameter ) { + for( size_t i = 0; i < v->n_dependencies; i++ ) { + std::string variable_name = v->m_dependencies[i]; + ASR::symbol_t* dep_sym = x.m_symtab->resolve_symbol(variable_name); + if (dep_sym) { + if (ASR::is_a(*dep_sym)) { + ASR::Variable_t* dep_v = ASR::down_cast(dep_sym); + if ( dep_v->m_symbolic_value == nullptr && + !(ASRUtils::is_array(dep_v->m_type) && ASRUtils::extract_physical_type(dep_v->m_type) == + ASR::array_physical_typeType::FixedSizeArray)) { + init_expr = nullptr; + break; + } + } + } + } + } + if( init_expr != nullptr && !is_list) { + target_var = ptr; + if(v->m_storage == ASR::storage_typeType::Save && + ASR::is_a( + *ASR::down_cast(v->m_parent_symtab->asr_owner))){ + variable_inital_value_vec.push_back({v, target_var}); + } else { + set_VariableInital_value(v, target_var); + } + } else { + if (is_a(*v->m_type) && !is_array_type && !is_list) { + ASR::String_t *t = down_cast(v->m_type); + target_var = ptr; + int strlen = t->m_len; + if (strlen >= 0 || strlen == -3) { + llvm::Value *arg_size; + if (strlen == -3) { + LCOMPILERS_ASSERT(t->m_len_expr) + this->visit_expr(*t->m_len_expr); + arg_size = builder->CreateAdd(builder->CreateSExtOrTrunc(tmp, + llvm::Type::getInt32Ty(context)), + llvm::ConstantInt::get(context, llvm::APInt(32, 1)) ); + } else { + // Compile time length + arg_size = llvm::ConstantInt::get(context, + llvm::APInt(32, strlen+1)); + } + llvm::Value *init_value = LLVM::lfortran_malloc(context, *module, *builder, arg_size); + string_init(context, *module, *builder, arg_size, init_value); + builder->CreateStore(init_value, target_var); + if (v->m_intent == intent_local) { + strings_to_be_deallocated.push_back(al, llvm_utils->CreateLoad2(v->m_type, target_var)); + } + } else if (strlen == -2) { + // Allocatable string. Initialize to `nullptr` (unallocated) + llvm::Value *init_value = llvm::Constant::getNullValue(type); + builder->CreateStore(init_value, target_var); + } else { + throw CodeGenError("Unsupported len value in ASR " + std::to_string(strlen)); + } + } else if (is_list) { + ASR::List_t* asr_list = ASR::down_cast(v->m_type); + std::string type_code = ASRUtils::get_type_code(asr_list->m_type); + list_api->list_init(type_code, ptr, *module); + } + } + } + } template void declare_vars(const T &x, bool create_vtabs=true) { - llvm::Value *target_var; uint32_t debug_arg_count = 0; std::vector var_order = ASRUtils::determine_variable_declaration_order(x.m_symtab); if( create_vtabs ) { @@ -3593,316 +4086,14 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor for (auto &item : var_order) { ASR::symbol_t* var_sym = x.m_symtab->get_symbol(item); if (is_a(*var_sym)) { - ASR::Variable_t *v = down_cast(var_sym); - uint32_t h = get_hash((ASR::asr_t*)v); - llvm::Type *type; - int n_dims = 0, a_kind = 4; - ASR::dimension_t* m_dims = nullptr; - bool is_array_type = false; - bool is_malloc_array_type = false; - bool is_list = false; - if (v->m_intent == intent_local || - v->m_intent == intent_return_var || - !v->m_intent) { - type = llvm_utils->get_type_from_ttype_t( - v->m_type, v->m_type_declaration, v->m_storage, is_array_type, - is_malloc_array_type, is_list, m_dims, n_dims, a_kind, module.get()); - llvm::Type* type_ = llvm_utils->get_type_from_ttype_t_util( - ASRUtils::type_get_past_pointer( - ASRUtils::type_get_past_allocatable(v->m_type)), module.get(), v->m_abi); - - /* - * The following if block is used for converting any - * general array descriptor to a pointer type which - * can be passed as an argument in a function call in LLVM IR. - */ - if( x.class_type == ASR::symbolType::Function) { - std::string m_name = std::string(x.m_name); - ASR::Function_t* _func = (ASR::Function_t*)(&(x.base)); - std::uint32_t m_h = get_hash((ASR::asr_t*)_func); - ASR::abiType abi_type = ASRUtils::get_FunctionType(_func)->m_abi; - bool is_v_arg = is_argument(v, _func->m_args, _func->n_args); - if( is_array_type && !is_list ) { - /* The first element in an array descriptor can be either of - * llvm::ArrayType or llvm::PointerType. However, a - * function only accepts llvm::PointerType for arrays. Hence, - * the following if block extracts the pointer to first element - * of an array from its descriptor. Note that this happens only - * for arguments and not for local function variables. - */ - if( abi_type == ASR::abiType::Source && is_v_arg ) { - type = arr_descr->get_argument_type(type, m_h, v->m_name, arr_arg_type_cache); - is_array_type = false; - } else if( abi_type == ASR::abiType::Intrinsic && - fname2arg_type.find(m_name) != fname2arg_type.end() ) { - type = fname2arg_type[m_name].second; - is_array_type = false; - } - } - } - - llvm::Value* array_size = nullptr; - if( ASRUtils::is_array(v->m_type) && - ASRUtils::extract_physical_type(v->m_type) == - ASR::array_physical_typeType::PointerToDataArray && - !LLVM::is_llvm_pointer(*v->m_type) ) { - type = llvm_utils->get_type_from_ttype_t( - ASRUtils::type_get_past_array(v->m_type), - v->m_type_declaration, v->m_storage, is_array_type, - is_malloc_array_type, is_list, m_dims, n_dims, a_kind, module.get()); - ASR::dimension_t* m_dims = nullptr; - size_t n_dims = ASRUtils::extract_dimensions_from_ttype(v->m_type, m_dims); - array_size = llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), llvm::APInt(32, 1)); - int ptr_loads_copy = ptr_loads; - ptr_loads = 2; - for( size_t i = 0; i < n_dims; i++ ) { - this->visit_expr_wrapper(m_dims[i].m_length, true); - array_size = builder->CreateMul(array_size, tmp); - } - ptr_loads = ptr_loads_copy; - } - llvm::Value *ptr = nullptr; - if( !compiler_options.stack_arrays && array_size ) { - llvm::DataLayout data_layout(module.get()); - uint64_t size = data_layout.getTypeAllocSize(type); - array_size = builder->CreateMul(array_size, - llvm::ConstantInt::get(context, llvm::APInt(32, size))); - llvm::Value* ptr_i8 = LLVMArrUtils::lfortran_malloc( - context, *module, *builder, array_size); - heap_arrays.push_back(ptr_i8); - ptr = builder->CreateBitCast(ptr_i8, type->getPointerTo()); - } else { - if (v->m_storage == ASR::storage_typeType::Save) { - std::string parent_function_name = std::string(x.m_name); - std::string global_name = parent_function_name+ "." + v->m_name; - ptr = module->getOrInsertGlobal(global_name, type); - llvm::GlobalVariable *gptr = module->getNamedGlobal(global_name); - gptr->setLinkage(llvm::GlobalValue::InternalLinkage); - llvm::Constant *init_value = llvm::Constant::getNullValue(type); - gptr->setInitializer(init_value); - } else { - get_builder0() - ptr = builder0.CreateAlloca(type, array_size, v->m_name); - } - } - set_pointer_variable_to_null(llvm::ConstantPointerNull::get( - static_cast(type)), ptr) - if( ASR::is_a( - *ASRUtils::type_get_past_array(v->m_type)) ) { - if( ASRUtils::is_array(v->m_type) ) { - allocate_array_members_of_struct_arrays(ptr, v->m_type); - } else { - allocate_array_members_of_struct(ptr, v->m_type); - } - } - if (compiler_options.emit_debug_info) { - // Reset the debug location - builder->SetCurrentDebugLocation(nullptr); - uint32_t line, column; - if (compiler_options.emit_debug_line_column) { - debug_get_line_column(v->base.base.loc.first, line, column); - } else { - line = v->base.base.loc.first; - column = 0; - } - - if (ASR::is_a(*v->m_type)) { - std::string member_type_name; - uint32_t member_type_size, member_type_encoding; - - llvm::DIType *int_type = DBuilder->createBasicType("integer", 32, llvm::dwarf::DW_ATE_signed); - ASR::ttype_t *asr_member_type = ASRUtils::get_contained_type(v->m_type); - - get_type_debug_info(asr_member_type, member_type_name, - member_type_size, member_type_encoding); - llvm::DIType *member_type = DBuilder->createBasicType(member_type_name, member_type_size, member_type_encoding); - - llvm::DIType *member_pointer_type = DBuilder->createPointerType(member_type, 64, 0, 0, member_type_name+"*"); - llvm::DIType *list_type = DBuilder->createStructType( - debug_current_scope, "list", debug_Unit, line, 64+member_type_size, 0, llvm::DINode::FlagZero, nullptr, DBuilder->getOrCreateArray({ - DBuilder->createMemberType(debug_Unit, "i32", debug_Unit, line, 32, 0, 0, llvm::DINode::FlagZero, int_type), - DBuilder->createMemberType(debug_Unit, "i32", debug_Unit, line, 32, 32, 0, llvm::DINode::FlagZero, int_type), - DBuilder->createMemberType(debug_Unit, "member", debug_Unit, line, 64, 64, 0, llvm::DINode::FlagZero, member_pointer_type) - })); - llvm::DILocalVariable *debug_var = DBuilder->createParameterVariable(debug_current_scope, - v->m_name, ++debug_arg_count, debug_Unit, line, list_type, true); - DBuilder->insertDeclare(ptr, debug_var, DBuilder->createExpression(), - llvm::DILocation::get(debug_current_scope->getContext(), - line, 0, debug_current_scope), builder->GetInsertBlock()); - } else if (ASR::is_a(*v->m_type)) { - std::string member_type_name; - uint32_t member_type_size, member_type_encoding; - - llvm::DIType *int_type = DBuilder->createBasicType("integer", 32, llvm::dwarf::DW_ATE_signed); - llvm::DIType *int_8_ptr_type = DBuilder->createPointerType( - DBuilder->createBasicType("char", 8, llvm::dwarf::DW_ATE_unsigned_char), 64, 0, 0, "i8*"); - ASR::ttype_t *asr_member_type = ASRUtils::get_contained_type(v->m_type); - - get_type_debug_info(asr_member_type, member_type_name, - member_type_size, member_type_encoding); - llvm::DIType *member_type = DBuilder->createBasicType(member_type_name, member_type_size, member_type_encoding); - - llvm::DIType *member_pointer_type = DBuilder->createPointerType(member_type, 64, 0, 0, member_type_name+"*"); - llvm::DIType *list_type = DBuilder->createStructType( - debug_current_scope, "list", debug_Unit, line, 64+member_type_size, 0, llvm::DINode::FlagZero, nullptr, DBuilder->getOrCreateArray({ - DBuilder->createMemberType(debug_Unit, "i32", debug_Unit, line, 32, 0, 0, llvm::DINode::FlagZero, int_type), - DBuilder->createMemberType(debug_Unit, "i32", debug_Unit, line, 32, 32, 0, llvm::DINode::FlagZero, int_type), - DBuilder->createMemberType(debug_Unit, "member", debug_Unit, line, 64, 64, 0, llvm::DINode::FlagZero, member_pointer_type) - })); - llvm::DIType *set_type = DBuilder->createStructType( - debug_current_scope, "list", debug_Unit, line, 64+member_type_size+32+64, 0, llvm::DINode::FlagZero, nullptr, DBuilder->getOrCreateArray({ - DBuilder->createMemberType(debug_Unit, "i32", debug_Unit, line, 32, 0, 0, llvm::DINode::FlagZero, int_type), - DBuilder->createMemberType(debug_Unit, "list", debug_Unit, line, 128, 32, 0, llvm::DINode::FlagZero, list_type), - DBuilder->createMemberType(debug_Unit, "i8*", debug_Unit, line, 64, 160, 0, llvm::DINode::FlagZero, int_8_ptr_type)})); - llvm::DILocalVariable *debug_var = DBuilder->createParameterVariable(debug_current_scope, - v->m_name, ++debug_arg_count, debug_Unit, line, set_type, true); - DBuilder->insertDeclare(ptr, debug_var, DBuilder->createExpression(), - llvm::DILocation::get(debug_current_scope->getContext(), - line, 0, debug_current_scope), builder->GetInsertBlock()); - } else { - - std::string type_name; - uint32_t type_size, type_encoding; - get_type_debug_info(v->m_type, type_name, type_size, - type_encoding); - llvm::DILocalVariable *debug_var = DBuilder->createParameterVariable( - debug_current_scope, v->m_name, ++debug_arg_count, debug_Unit, line, - DBuilder->createBasicType(type_name, type_size, type_encoding), true); - DBuilder->insertDeclare(ptr, debug_var, DBuilder->createExpression(), - llvm::DILocation::get(debug_current_scope->getContext(), - line, 0, debug_current_scope), builder->GetInsertBlock()); - } - } - - if( ASR::is_a(*v->m_type) ) { - ASR::StructType_t* struct_t = ASR::down_cast(v->m_type); - ASR::Struct_t* struct_type = ASR::down_cast( - ASRUtils::symbol_get_past_external(struct_t->m_derived_type)); - int64_t alignment_value = -1; - if( ASRUtils::extract_value(struct_type->m_alignment, alignment_value) ) { - llvm::Align align(alignment_value); - reinterpret_cast(ptr)->setAlignment(align); - } - } - - llvm_symtab[h] = ptr; - if( (ASRUtils::is_array(v->m_type) && - ((ASRUtils::extract_physical_type(v->m_type) == ASR::array_physical_typeType::DescriptorArray) || - (ASRUtils::extract_physical_type(v->m_type) == ASR::array_physical_typeType::CharacterArraySinglePointer && - ASRUtils::is_dimension_empty(m_dims,n_dims)))) - ) { - fill_array_details_(ptr, type_, m_dims, n_dims, - is_malloc_array_type, is_array_type, is_list, v->m_type); - } - ASR::expr_t* init_expr = v->m_symbolic_value; - if( v->m_storage != ASR::storage_typeType::Parameter ) { - for( size_t i = 0; i < v->n_dependencies; i++ ) { - std::string variable_name = v->m_dependencies[i]; - ASR::symbol_t* dep_sym = x.m_symtab->resolve_symbol(variable_name); - if (dep_sym) { - if (ASR::is_a(*dep_sym)) { - ASR::Variable_t* dep_v = ASR::down_cast(dep_sym); - if ( dep_v->m_symbolic_value == nullptr && - !(ASRUtils::is_array(dep_v->m_type) && ASRUtils::extract_physical_type(dep_v->m_type) == - ASR::array_physical_typeType::FixedSizeArray)) { - init_expr = nullptr; - break; - } - } - } - } - } - if( init_expr != nullptr && - !is_list) { - target_var = ptr; - tmp = nullptr; - if (v->m_value != nullptr) { - this->visit_expr_wrapper(v->m_value, true); - } else { - this->visit_expr_wrapper(v->m_symbolic_value, true); - } - llvm::Value *init_value = tmp; - if( ASRUtils::is_array(v->m_type) && - ASRUtils::is_array(ASRUtils::expr_type(v->m_symbolic_value)) && - (ASR::is_a(*v->m_symbolic_value) || - (v->m_value && ASR::is_a(*v->m_value))) ) { - ASR::array_physical_typeType target_ptype = ASRUtils::extract_physical_type(v->m_type); - if( target_ptype == ASR::array_physical_typeType::DescriptorArray ) { - target_var = arr_descr->get_pointer_to_data(target_var); - builder->CreateStore(init_value, target_var); - } else if( target_ptype == ASR::array_physical_typeType::FixedSizeArray ) { - llvm::Value* arg_size = llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), - llvm::APInt(32, ASR::down_cast(v->m_value)->n_args)); - llvm::Type* llvm_data_type = llvm_utils->get_type_from_ttype_t_util( - ASRUtils::type_get_past_array(ASRUtils::expr_type(v->m_value)), module.get()); - llvm::DataLayout data_layout(module.get()); - size_t dt_size = data_layout.getTypeAllocSize(llvm_data_type); - arg_size = builder->CreateMul(llvm::ConstantInt::get( - llvm::Type::getInt32Ty(context), llvm::APInt(32, dt_size)), arg_size); - builder->CreateMemCpy(llvm_utils->create_gep(target_var, 0), - llvm::MaybeAlign(), init_value, llvm::MaybeAlign(), arg_size); - } - } else if (ASR::is_a(*v->m_symbolic_value)) { - builder->CreateStore(LLVM::CreateLoad(*builder, init_value), target_var); - } else if (is_a(*v->m_type) && !is_array_type) { - ASR::Character_t *t = down_cast(v->m_type); - llvm::Value *arg_size = llvm::ConstantInt::get(context, - llvm::APInt(32, t->m_len+1)); - llvm::Value *s_malloc = LLVM::lfortran_malloc(context, *module, *builder, arg_size); - string_init(context, *module, *builder, arg_size, s_malloc); - builder->CreateStore(s_malloc, target_var); - tmp = lfortran_str_copy(target_var, init_value); - if (v->m_intent == intent_local) { - strings_to_be_deallocated.push_back(al, CreateLoad(target_var)); - } - } else { - builder->CreateStore(init_value, target_var); - } - } else { - if (is_a(*v->m_type) && !is_array_type && !is_list) { - ASR::Character_t *t = down_cast(v->m_type); - target_var = ptr; - int strlen = t->m_len; - if (strlen >= 0 || strlen == -3) { - llvm::Value *arg_size; - if (strlen == -3) { - LCOMPILERS_ASSERT(t->m_len_expr) - this->visit_expr(*t->m_len_expr); - arg_size = builder->CreateAdd(builder->CreateSExtOrTrunc(tmp, - llvm::Type::getInt32Ty(context)), - llvm::ConstantInt::get(context, llvm::APInt(32, 1)) ); - } else { - // Compile time length - arg_size = llvm::ConstantInt::get(context, - llvm::APInt(32, strlen+1)); - } - llvm::Value *init_value = LLVM::lfortran_malloc(context, *module, *builder, arg_size); - string_init(context, *module, *builder, arg_size, init_value); - builder->CreateStore(init_value, target_var); - if (v->m_intent == intent_local) { - strings_to_be_deallocated.push_back(al, CreateLoad(target_var)); - } - } else if (strlen == -2) { - // Allocatable string. Initialize to `nullptr` (unallocated) - llvm::Value *init_value = llvm::Constant::getNullValue(type); - builder->CreateStore(init_value, target_var); - } else { - throw CodeGenError("Unsupported len value in ASR " + std::to_string(strlen)); - } - } else if (is_list) { - ASR::List_t* asr_list = ASR::down_cast(v->m_type); - std::string type_code = ASRUtils::get_type_code(asr_list->m_type); - list_api->list_init(type_code, ptr, *module); - } - } - } + process_Variable(var_sym, x, debug_arg_count); } } } bool is_function_variable(const ASR::Variable_t &v) { if (v.m_type_declaration) { - return ASR::is_a(*v.m_type_declaration); + return ASR::is_a(*ASRUtils::symbol_get_past_external(v.m_type_declaration)); } else { return false; } @@ -3930,15 +4121,39 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor ASR::Variable_t *v = ASR::down_cast(s); if (is_function_variable(*v)) { // * Function (callback) Variable (`procedure(fn) :: x`) - s = v->m_type_declaration; + s = ASRUtils::symbol_get_past_external(v->m_type_declaration); } else { // * Variable (`integer :: x`) ASR::Variable_t *arg = EXPR2VAR(x.m_args[i]); LCOMPILERS_ASSERT(is_arg_dummy(arg->m_intent)); + + llvm::Value* llvm_sym = &llvm_arg; + + // Under BindC convention, characters are passed as i8*, + // but they are passed as i8** otherwise. Handle conversion + // from bindC convention back to regular convention here. + if (ASRUtils::get_FunctionType(x)->m_abi == ASR::abiType::BindC) { + if (ASR::is_a(*arg->m_type)) { + llvm_sym = llvm_utils->CreateAlloca(*builder, llvm_arg.getType()); + builder->CreateStore(&llvm_arg, llvm_sym); + } + } uint32_t h = get_hash((ASR::asr_t*)arg); std::string arg_s = arg->m_name; llvm_arg.setName(arg_s); - llvm_symtab[h] = &llvm_arg; + llvm_symtab[h] = llvm_sym; +#if LLVM_VERSION_MAJOR > 16 + llvm::Type *arg_type = llvm_utils->get_type_from_ttype_t_util( + ASRUtils::type_get_past_allocatable( + ASRUtils::type_get_past_pointer(arg->m_type)), module.get()); + if ( !ASRUtils::is_array(arg->m_type) && + LLVM::is_llvm_pointer(*arg->m_type) && + !is_a(*ASRUtils::type_get_past_allocatable( + ASRUtils::type_get_past_pointer(arg->m_type))) ) { + arg_type = arg_type->getPointerTo(); + } + ptr_type[llvm_sym] = arg_type; +#endif } } if (is_a(*s)) { @@ -4013,7 +4228,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor void instantiate_function(const ASR::Function_t &x){ uint32_t h = get_hash((ASR::asr_t*)&x); llvm::Function *F = nullptr; - llvm::DISubprogram *SP; + llvm::DISubprogram *SP = nullptr; std::string sym_name = x.m_name; if (sym_name == "main") { sym_name = "_xx_lcompilers_changed_main_xx"; @@ -4029,15 +4244,13 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor if( ASRUtils::get_FunctionType(x)->m_deftype == ASR::deftypeType::Interface ) { ASR::FunctionType_t* asr_function_type = ASRUtils::get_FunctionType(x); for( size_t i = 0; i < asr_function_type->n_arg_types; i++ ) { - if( ASR::is_a(*asr_function_type->m_arg_types[i]) ) { + if( ASR::is_a(*asr_function_type->m_arg_types[i]) ) { return ; } } } std::string fn_name; - if (compiler_options.interactive && startswith(sym_name, "__main__global_stmts")) { - fn_name = sym_name; - } else if (ASRUtils::get_FunctionType(x)->m_abi == ASR::abiType::BindC) { + if (ASRUtils::get_FunctionType(x)->m_abi == ASR::abiType::BindC) { if (ASRUtils::get_FunctionType(x)->m_bindc_name) { fn_name = ASRUtils::get_FunctionType(x)->m_bindc_name; } else { @@ -4091,6 +4304,50 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor if (!interface_as_arg) { instantiate_function(*v); } + } else if ( ASR::is_a(*ASRUtils::symbol_get_past_external(item.second)) && is_function_variable(ASRUtils::symbol_get_past_external(item.second)) ) { + ASR::Variable_t *v = down_cast(ASRUtils::symbol_get_past_external(item.second)); + bool interface_as_arg = false; + for (size_t i=0; i(*x.m_args[i])) { + ASR::Var_t *arg = down_cast(x.m_args[i]); + if ( arg->m_v == item.second ) { + interface_as_arg = true; + } + } + } + if ( interface_as_arg ) { + continue; + } + ASR::Function_t *var = ASR::down_cast( + ASRUtils::symbol_get_past_external(v->m_type_declaration)); + uint32_t h = get_hash((ASR::asr_t*)v); + if (llvm_symtab_fn.find(h) != llvm_symtab_fn.end()) { + continue; + } + llvm::FunctionType* function_type = llvm_utils->get_function_type(*var, module.get()); + std::string fn_name; + std::string sym_name = v->m_name; + if (ASRUtils::get_FunctionType(*var)->m_abi == ASR::abiType::BindC) { + if (ASRUtils::get_FunctionType(*var)->m_bindc_name) { + fn_name = ASRUtils::get_FunctionType(*var)->m_bindc_name; + } else { + fn_name = sym_name; + } + } else if (ASRUtils::get_FunctionType(*var)->m_deftype == ASR::deftypeType::Interface && + ASRUtils::get_FunctionType(*var)->m_abi != ASR::abiType::Intrinsic) { + fn_name = sym_name; + } else { + fn_name = mangle_prefix + sym_name; + } + if (llvm_symtab_fn_names.find(fn_name) == llvm_symtab_fn_names.end()) { + llvm_symtab_fn_names[fn_name] = h; + llvm::Function* F = llvm::Function::Create(function_type, + llvm::Function::ExternalLinkage, fn_name, module.get()); + llvm_symtab_fn[h] = F; + } else { + uint32_t old_h = llvm_symtab_fn_names[fn_name]; + llvm_symtab_fn[h] = llvm_symtab_fn[old_h]; + } } } } @@ -4117,7 +4374,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor ASR::Variable_t *asr_retval = EXPR2VAR(x.m_return_var); uint32_t h = get_hash((ASR::asr_t*)asr_retval); llvm::Value *ret_val = llvm_symtab[h]; - llvm::Value *ret_val2 = CreateLoad(ret_val); + llvm::Value *ret_val2 = llvm_utils->CreateLoad2(asr_retval->m_type, ret_val); // Handle Complex type return value for BindC: if (ASRUtils::get_FunctionType(x)->m_abi == ASR::abiType::BindC) { ASR::ttype_t* arg_type = asr_retval->m_type; @@ -4128,22 +4385,22 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor if (compiler_options.platform == Platform::Windows) { // tmp is {float, float}* // type_fx2p is i64* - llvm::Type* type_fx2p = llvm::Type::getInt64PtrTy(context); + llvm::Type* type_fx2p = llvm::Type::getInt64Ty(context)->getPointerTo(); // Convert {float,float}* to i64* using bitcast tmp = builder->CreateBitCast(tmp, type_fx2p); // Then convert i64* -> i64 - tmp = CreateLoad(tmp); + tmp = llvm_utils->CreateLoad(tmp); } else if (compiler_options.platform == Platform::macOS_ARM) { // Pass by value - tmp = CreateLoad(tmp); + tmp = llvm_utils->CreateLoad(tmp); } else { // tmp is {float, float}* - // type_fx2p is <2 x float>* - llvm::Type* type_fx2p = FIXED_VECTOR_TYPE::get(llvm::Type::getFloatTy(context), 2)->getPointerTo(); + // type_fx2 is <2 x float> + llvm::Type* type_fx2 = FIXED_VECTOR_TYPE::get(llvm::Type::getFloatTy(context), 2); // Convert {float,float}* to <2 x float>* using bitcast - tmp = builder->CreateBitCast(tmp, type_fx2p); + tmp = builder->CreateBitCast(tmp, type_fx2->getPointerTo()); // Then convert <2 x float>* -> <2 x float> - tmp = CreateLoad(tmp); + tmp = llvm_utils->CreateLoad2(type_fx2, tmp); } } else { LCOMPILERS_ASSERT(c_kind == 8) @@ -4151,7 +4408,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor // 128 bit aggregate type is passed by reference } else { // Pass by value - tmp = CreateLoad(tmp); + tmp = llvm_utils->CreateLoad(tmp); } } ret_val2 = tmp; @@ -4214,8 +4471,8 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor h = get_hash((ASR::asr_t*)ret); llvm::Value* llvm_ret_ptr = llvm_symtab[h]; - llvm::Value* dim_des_val = CreateLoad(llvm_arg1); - llvm::Value* dim_val = CreateLoad(llvm_arg2); + llvm::Value* dim_des_val = llvm_utils->CreateLoad(llvm_arg1); + llvm::Value* dim_val = llvm_utils->CreateLoad(llvm_arg2); llvm::Value* const_1 = llvm::ConstantInt::get(context, llvm::APInt(32, 1)); dim_val = builder->CreateSub(dim_val, const_1); llvm::Value* dim_struct = arr_descr->get_pointer_to_dimension_descriptor(dim_des_val, dim_val); @@ -4239,9 +4496,6 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor if (is_a(*item.second)) { ASR::Function_t *s = ASR::down_cast(item.second); visit_Function(*s); - } else if ( is_a(*item.second) ) { - ASR::Struct_t *st = down_cast(item.second); - visit_methods(*st); } } } @@ -4259,35 +4513,40 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor this->visit_expr(*x.m_arg); ptr_loads = ptr_loads_copy; if( is_nested_pointer(tmp) ) { - tmp = CreateLoad(tmp); + tmp = llvm_utils->CreateLoad(tmp); } ASR::ttype_t* arg_type = ASRUtils::get_contained_type(ASRUtils::expr_type(x.m_arg)); if( ASRUtils::is_array(arg_type) ) { - tmp = CreateLoad(arr_descr->get_pointer_to_data(tmp)); + tmp = llvm_utils->CreateLoad(arr_descr->get_pointer_to_data(tmp)); } tmp = builder->CreateBitCast(tmp, llvm::Type::getVoidTy(context)->getPointerTo()); } - llvm::Value* GetPointerCPtrUtil(llvm::Value* llvm_tmp, ASR::ttype_t* asr_type) { + llvm::Value* GetPointerCPtrUtil(llvm::Value* llvm_tmp, ASR::expr_t* asr_expr) { // If the input is a simple variable and not a pointer // then this check will fail and load will not happen // (which is what we want for simple variables). // For pointers, the actual LLVM variable will be a // double pointer, so we need to load one time and then // use it later on. - if( is_nested_pointer(llvm_tmp) && - !ASR::is_a(*asr_type)) { - llvm_tmp = CreateLoad(llvm_tmp); + ASR::ttype_t* asr_type = ASRUtils::expr_type(asr_expr); + if(ASR::is_a(*asr_type) && + (LLVM::is_llvm_pointer(*ASRUtils::type_get_past_pointer(asr_type)) + || ASR::is_a(*ASRUtils::type_get_past_pointer(asr_type)) + || llvm::isa(llvm_tmp))) { + llvm_tmp = llvm_utils->CreateLoad(llvm_tmp); } + asr_type = ASRUtils::get_contained_type(asr_type); if( ASRUtils::is_array(asr_type) && !ASR::is_a(*asr_type) ) { ASR::array_physical_typeType physical_type = ASRUtils::extract_physical_type(asr_type); + llvm::Type *el_type = llvm_utils->get_type_from_ttype_t_util(ASRUtils::extract_type(asr_type), module.get()); switch( physical_type ) { case ASR::array_physical_typeType::DescriptorArray: { - llvm_tmp = CreateLoad(arr_descr->get_pointer_to_data(llvm_tmp)); + llvm_tmp = llvm_utils->CreateLoad2(el_type->getPointerTo(), arr_descr->get_pointer_to_data(llvm_tmp)); break; } case ASR::array_physical_typeType::FixedSizeArray: { @@ -4321,8 +4580,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor ptr_loads = 0; this->visit_expr(*x.m_arg); ptr_loads = ptr_loads_copy; - ASR::ttype_t* arg_type = ASRUtils::get_contained_type(ASRUtils::expr_type(x.m_arg)); - tmp = GetPointerCPtrUtil(tmp, arg_type); + tmp = GetPointerCPtrUtil(tmp, x.m_arg); } void visit_PointerToCPtr(const ASR::PointerToCPtr_t& x) { @@ -4331,9 +4589,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor this->visit_expr(*x.m_arg); ptr_loads = ptr_loads_copy; if( !ASR::is_a(*x.m_arg) ) { - ASR::ttype_t* arg_type = ASRUtils::get_contained_type( - ASRUtils::expr_type(x.m_arg)); - tmp = GetPointerCPtrUtil(tmp, arg_type); + tmp = GetPointerCPtrUtil(tmp, x.m_arg); } tmp = builder->CreateBitCast(tmp, llvm::Type::getVoidTy(context)->getPointerTo()); @@ -4341,7 +4597,6 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor void visit_CPtrToPointer(const ASR::CPtrToPointer_t& x) { - get_builder0() ASR::expr_t *cptr = x.m_cptr, *fptr = x.m_ptr, *shape = x.m_shape; int reduce_loads = 0; if( ASR::is_a(*cptr) ) { @@ -4353,6 +4608,11 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor ptr_loads = 1 - reduce_loads; this->visit_expr(*cptr); llvm::Value* llvm_cptr = tmp; + if (ASR::is_a(*cptr)) { + // `type(c_ptr)` requires an extra load here + // TODO: be more explicit about ptr_loads: https://github.com/lfortran/lfortran/issues/4245 + llvm_cptr = llvm_utils->CreateLoad(llvm_cptr); + } ptr_loads = 0; this->visit_expr(*fptr); llvm::Value* llvm_fptr = tmp; @@ -4367,7 +4627,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor ASR::ttype_t* fptr_type = ASRUtils::expr_type(fptr); llvm::Type* llvm_fptr_type = llvm_utils->get_type_from_ttype_t_util( ASRUtils::get_contained_type(fptr_type), module.get()); - llvm::Value* fptr_array = builder0.CreateAlloca(llvm_fptr_type); + llvm::Value* fptr_array = llvm_utils->CreateAlloca(*builder, llvm_fptr_type); builder->CreateStore(llvm::ConstantInt::get(context, llvm::APInt(32, 0)), arr_descr->get_offset(fptr_array, false)); ASR::dimension_t* fptr_dims; @@ -4375,7 +4635,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor ASRUtils::expr_type(fptr), fptr_dims); llvm::Value* llvm_rank = llvm::ConstantInt::get(context, llvm::APInt(32, fptr_rank)); - llvm::Value* dim_des = builder0.CreateAlloca(arr_descr->get_dimension_descriptor_type(), llvm_rank); + llvm::Value* dim_des = llvm_utils->CreateAlloca(*builder, arr_descr->get_dimension_descriptor_type(), llvm_rank); builder->CreateStore(dim_des, arr_descr->get_pointer_to_dimension_descriptor_array(fptr_array, false)); arr_descr->set_rank(fptr_array, llvm_rank); builder->CreateStore(fptr_array, llvm_fptr); @@ -4387,7 +4647,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor llvm::Value* shape_data = llvm_shape; if( llvm_shape && (ASRUtils::extract_physical_type(asr_shape_type) == ASR::array_physical_typeType::DescriptorArray) ) { - shape_data = CreateLoad(arr_descr->get_pointer_to_data(llvm_shape)); + shape_data = llvm_utils->CreateLoad(arr_descr->get_pointer_to_data(llvm_shape)); } llvm_cptr = builder->CreateBitCast(llvm_cptr, llvm_fptr_data_type->getPointerTo()); builder->CreateStore(llvm_cptr, fptr_data); @@ -4396,7 +4656,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor if( x.m_lower_bounds ) { LCOMPILERS_ASSERT(ASR::is_a(*x.m_lower_bounds)); lower_bounds = ASR::down_cast(x.m_lower_bounds); - LCOMPILERS_ASSERT(fptr_rank == (int) lower_bounds->n_args); + LCOMPILERS_ASSERT(fptr_rank == ASRUtils::get_fixed_size_of_array(lower_bounds->m_type)); } for( int i = 0; i < fptr_rank; i++ ) { llvm::Value* curr_dim = llvm::ConstantInt::get(context, llvm::APInt(32, i)); @@ -4410,16 +4670,18 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor if( lower_bounds ) { int ptr_loads_copy = ptr_loads; ptr_loads = 2; - this->visit_expr_wrapper(lower_bounds->m_args[i], true); + this->visit_expr_wrapper(ASRUtils::fetch_ArrayConstant_value(al, lower_bounds, i), true); ptr_loads = ptr_loads_copy; new_lb = tmp; } llvm::Value* new_ub = nullptr; if( ASRUtils::extract_physical_type(asr_shape_type) == ASR::array_physical_typeType::DescriptorArray || ASRUtils::extract_physical_type(asr_shape_type) == ASR::array_physical_typeType::PointerToDataArray ) { - new_ub = shape_data ? CreateLoad(llvm_utils->create_ptr_gep(shape_data, i)) : i32_one; + new_ub = shape_data ? llvm_utils->CreateLoad2( + llvm::Type::getInt32Ty(context), llvm_utils->create_ptr_gep(shape_data, i)) : i32_one; } else if( ASRUtils::extract_physical_type(asr_shape_type) == ASR::array_physical_typeType::FixedSizeArray ) { - new_ub = shape_data ? CreateLoad(llvm_utils->create_gep(shape_data, i)) : i32_one; + new_ub = shape_data ? llvm_utils->CreateLoad2( + llvm::Type::getInt32Ty(context), llvm_utils->create_gep(shape_data, i)) : i32_one; } builder->CreateStore(new_lb, desi_lb); llvm::Value* new_size = builder->CreateAdd(builder->CreateSub(new_ub, new_lb), i32_one); @@ -4447,17 +4709,19 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor this->visit_expr_wrapper(x.m_value, true); return; } - llvm::BasicBlock &entry_block = builder->GetInsertBlock()->getParent()->getEntryBlock(); - llvm::IRBuilder<> builder0(context); - builder0.SetInsertPoint(&entry_block, entry_block.getFirstInsertionPt()); - llvm::AllocaInst *res = builder0.CreateAlloca( + llvm::AllocaInst *res = llvm_utils->CreateAlloca( llvm::Type::getInt1Ty(context), nullptr, "is_associated"); ASR::ttype_t* p_type = ASRUtils::expr_type(x.m_ptr); llvm::Value *ptr, *nptr; int64_t ptr_loads_copy = ptr_loads; - ptr_loads = 1; + ptr_loads = 0; visit_expr_wrapper(x.m_ptr, true); ptr = tmp; + llvm::Type *ptr_arr_type = llvm_utils->get_type_from_ttype_t_util( + ASRUtils::type_get_past_allocatable( + ASRUtils::type_get_past_pointer(p_type)), module.get()); + ptr = llvm_utils->CreateLoad2(p_type, ptr); + ptr_type[ptr] = ptr_arr_type; ptr_loads = ptr_loads_copy; if( ASR::is_a(*ASRUtils::expr_type(x.m_ptr)) && x.m_tgt && ASR::is_a(*ASRUtils::expr_type(x.m_tgt)) ) { @@ -4495,7 +4759,9 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor nptr = llvm_utils->create_gep(nptr, 0); } if( tgt_ptype != ASR::array_physical_typeType::DescriptorArray ) { - ptr = LLVM::CreateLoad(*builder, arr_descr->get_pointer_to_data(ptr)); + llvm::Type *value_type = llvm_utils->get_type_from_ttype_t_util( + ASRUtils::extract_type(p_type), module.get()); + ptr = llvm_utils->CreateLoad2(value_type->getPointerTo(), arr_descr->get_pointer_to_data(ptr)); } } nptr = builder->CreatePtrToInt(nptr, llvm_utils->getIntType(8, false)); @@ -4509,7 +4775,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor builder->CreateStore(builder->CreateICmpNE(ptr, nptr), res); } }); - tmp = LLVM::CreateLoad(*builder, res); + tmp = llvm_utils->CreateLoad(res); } void handle_array_section_association_to_pointer(const ASR::Associate_t& x) { @@ -4523,22 +4789,21 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor if( ASR::is_a(*array_section->m_v) && ASRUtils::extract_physical_type(value_array_type) != ASR::array_physical_typeType::FixedSizeArray ) { - value_desc = LLVM::CreateLoad(*builder, value_desc); + value_desc = llvm_utils->CreateLoad(value_desc); } + llvm::Type *value_el_type = llvm_utils->get_type_from_ttype_t_util( + ASRUtils::extract_type(value_array_type), module.get()); ptr_loads = 0; visit_expr(*x.m_target); llvm::Value* target_desc = tmp; ptr_loads = ptr_loads_copy; - llvm::BasicBlock &entry_block = builder->GetInsertBlock()->getParent()->getEntryBlock(); - llvm::IRBuilder<> builder0(context); - builder0.SetInsertPoint(&entry_block, entry_block.getFirstInsertionPt()); ASR::ttype_t* target_desc_type = ASRUtils::duplicate_type_with_empty_dims(al, ASRUtils::type_get_past_allocatable( ASRUtils::type_get_past_pointer(value_array_type)), ASR::array_physical_typeType::DescriptorArray, true); llvm::Type* target_type = llvm_utils->get_type_from_ttype_t_util(target_desc_type, module.get()); - llvm::AllocaInst *target = builder0.CreateAlloca( + llvm::AllocaInst *target = llvm_utils->CreateAlloca( target_type, nullptr, "array_section_descriptor"); int value_rank = array_section->n_args, target_rank = 0; Vec lbs; lbs.reserve(al, value_rank); @@ -4563,14 +4828,21 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } LCOMPILERS_ASSERT(target_rank > 0); llvm::Value* target_dim_des_ptr = arr_descr->get_pointer_to_dimension_descriptor_array(target, false); - llvm::Value* target_dim_des_val = builder0.CreateAlloca(arr_descr->get_dimension_descriptor_type(false), + llvm::Value* target_dim_des_val = llvm_utils->CreateAlloca(arr_descr->get_dimension_descriptor_type(false), llvm::ConstantInt::get(llvm_utils->getIntType(4), llvm::APInt(32, target_rank))); builder->CreateStore(target_dim_des_val, target_dim_des_ptr); ASR::ttype_t* array_type = ASRUtils::expr_type(array_section->m_v); - if( ASRUtils::extract_physical_type(array_type) == ASR::array_physical_typeType::PointerToDataArray || - ASRUtils::extract_physical_type(array_type) == ASR::array_physical_typeType::FixedSizeArray ) { - if( ASRUtils::extract_physical_type(array_type) == ASR::array_physical_typeType::FixedSizeArray ) { - value_desc = llvm_utils->create_gep(value_desc, 0); + ASR::array_physical_typeType arr_physical_type = ASRUtils::extract_physical_type(array_type); + if( arr_physical_type == ASR::array_physical_typeType::PointerToDataArray || + arr_physical_type == ASR::array_physical_typeType::FixedSizeArray || + arr_physical_type == ASR::array_physical_typeType::StringArraySinglePointer) { + if( arr_physical_type == ASR::array_physical_typeType::FixedSizeArray || + arr_physical_type == ASR::array_physical_typeType::StringArraySinglePointer) { + llvm::Type *val_type = llvm_utils->get_type_from_ttype_t_util( + ASRUtils::type_get_past_allocatable( + ASRUtils::type_get_past_pointer(value_array_type)), + module.get()); + value_desc = llvm_utils->create_gep2(val_type, value_desc, 0); } ASR::dimension_t* m_dims = nullptr; // Fill in m_dims: @@ -4584,11 +4856,11 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor visit_expr_wrapper(m_dims[i].m_length, true); llvm_diminfo.push_back(al, tmp); } - arr_descr->fill_descriptor_for_array_section_data_only(value_desc, target, + arr_descr->fill_descriptor_for_array_section_data_only(value_desc, value_el_type, target, lbs.p, ubs.p, ds.p, non_sliced_indices.p, llvm_diminfo.p, value_rank, target_rank); } else { - arr_descr->fill_descriptor_for_array_section(value_desc, target, + arr_descr->fill_descriptor_for_array_section(value_desc, value_el_type, target, lbs.p, ubs.p, ds.p, non_sliced_indices.p, array_section->n_args, target_rank); } @@ -4596,7 +4868,6 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } void visit_Associate(const ASR::Associate_t& x) { - get_builder0() if( ASR::is_a(*x.m_value) ) { handle_array_section_association_to_pointer(x); } else { @@ -4609,24 +4880,32 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor ptr_loads = ptr_loads_copy; ASR::dimension_t* m_dims = nullptr; ASR::ttype_t* target_type = ASRUtils::expr_type(x.m_target); + ASR::ttype_t* value_type = ASRUtils::expr_type(x.m_value); int n_dims = ASRUtils::extract_dimensions_from_ttype(target_type, m_dims); ASR::ttype_t *type = ASRUtils::get_contained_type(target_type); type = ASRUtils::type_get_past_allocatable(type); - if (ASR::is_a(*type)) { + if (ASR::is_a(*type)) { int dims = n_dims; if (dims == 0) { - builder->CreateStore(CreateLoad(llvm_value), + builder->CreateStore(llvm_utils->CreateLoad2(value_type, llvm_value), llvm_target); return; } } - bool is_target_class = ASR::is_a( + [[maybe_unused]] bool is_target_class = ASR::is_a( *ASRUtils::type_get_past_pointer(target_type)); - bool is_value_class = ASR::is_a( + [[maybe_unused]] bool is_value_class = ASR::is_a( *ASRUtils::type_get_past_pointer( ASRUtils::type_get_past_allocatable(value_type))); - if( is_target_class && !is_value_class ) { + llvm::Type *i64 = llvm::Type::getInt64Ty(context); + if (ASR::is_a(*x.m_value)) { + builder->CreateStore(llvm_value, llvm_target); + } else if (ASR::is_a(*x.m_value) && + ASR::is_a(*value_type)) { + llvm_value = llvm_utils->CreateLoad(llvm_value); + builder->CreateStore(llvm_value, llvm_target); + } else if (is_target_class && !is_value_class) { llvm::Value* vtab_address_ptr = llvm_utils->create_gep(llvm_target, 0); llvm_target = llvm_utils->create_gep(llvm_target, 1); ASR::StructType_t* struct_t = ASR::down_cast( @@ -4637,23 +4916,25 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor create_vtab_for_struct_type(struct_sym, current_scope); } llvm::Value* vtab_obj = type2vtab[struct_sym][current_scope]; - llvm::Value* struct_type_hash = CreateLoad(llvm_utils->create_gep(vtab_obj, 0)); + llvm::Value* struct_type_hash = llvm_utils->CreateLoad2(i64, llvm_utils->create_gep(vtab_obj, 0)); builder->CreateStore(struct_type_hash, vtab_address_ptr); - ASR::Class_t* class_t = ASR::down_cast( + ASR::ClassType_t* class_t = ASR::down_cast( ASRUtils::type_get_past_pointer(target_type)); ASR::Struct_t* struct_type_t = ASR::down_cast( ASRUtils::symbol_get_past_external(class_t->m_class_type)); llvm_value = builder->CreateBitCast(llvm_value, llvm_utils->getStructType(struct_type_t, module.get(), true)); builder->CreateStore(llvm_value, llvm_target); } else if( is_target_class && is_value_class ) { - [[maybe_unused]] ASR::Class_t* target_class_t = ASR::down_cast( + [[maybe_unused]] ASR::ClassType_t* target_class_t = ASR::down_cast( ASRUtils::type_get_past_pointer(target_type)); - [[maybe_unused]] ASR::Class_t* value_class_t = ASR::down_cast( + [[maybe_unused]] ASR::ClassType_t* value_class_t = ASR::down_cast( ASRUtils::type_get_past_pointer(ASRUtils::type_get_past_allocatable(value_type))); LCOMPILERS_ASSERT(target_class_t->m_class_type == value_class_t->m_class_type); - llvm::Value* value_vtabid = CreateLoad(llvm_utils->create_gep(llvm_value, 0)); - llvm::Value* value_class = CreateLoad(llvm_utils->create_gep(llvm_value, 1)); + llvm::Type *value_llvm_type = llvm_utils->getStructType( + ASRUtils::extract_type(value_type), module.get(), true); + llvm::Value* value_vtabid = llvm_utils->CreateLoad2(i64, llvm_utils->create_gep(llvm_value, 0)); + llvm::Value* value_class = llvm_utils->CreateLoad2(value_llvm_type, llvm_utils->create_gep(llvm_value, 1)); builder->CreateStore(value_vtabid, llvm_utils->create_gep(llvm_target, 0)); builder->CreateStore(value_class, llvm_utils->create_gep(llvm_target, 1)); } else { @@ -4661,7 +4942,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor ASRUtils::extract_physical_type(value_type) == ASR::array_physical_typeType::PointerToDataArray || ASRUtils::extract_physical_type(value_type) == ASR::array_physical_typeType::FixedSizeArray)); if( LLVM::is_llvm_pointer(*value_type) ) { - llvm_value = LLVM::CreateLoad(*builder, llvm_value); + llvm_value = llvm_utils->CreateLoad(llvm_value); } if( is_value_data_only_array ) { ASR::ttype_t* target_type_ = ASRUtils::type_get_past_pointer(target_type); @@ -4671,7 +4952,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor llvm_value = llvm_utils->create_gep(llvm_value, 0); } llvm::Type* llvm_target_type = llvm_utils->get_type_from_ttype_t_util(target_type_, module.get()); - llvm::Value* llvm_target_ = builder0.CreateAlloca(llvm_target_type); + llvm::Value* llvm_target_ = llvm_utils->CreateAlloca(*builder, llvm_target_type); ASR::dimension_t* m_dims = nullptr; size_t n_dims = ASRUtils::extract_dimensions_from_ttype(value_type, m_dims); ASR::ttype_t* data_type = ASRUtils::duplicate_type_without_dims( @@ -4683,7 +4964,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor break; } case ASR::array_physical_typeType::FixedSizeArray: { - llvm_value = LLVM::CreateLoad(*builder, llvm_value); + llvm_value = llvm_utils->CreateLoad(llvm_value); break; } case ASR::array_physical_typeType::PointerToDataArray: { @@ -4727,7 +5008,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor if (ASR::is_a(*ss->m_arg)) { ASR::Variable_t *asr_target = EXPR2VAR(ss->m_arg); if (ASR::is_a(*asr_target->m_type)) { - tmp = lfortran_str_copy(str, str_val); + tmp = lfortran_str_copy(str, str_val, true); return; } } @@ -4761,24 +5042,14 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor step = llvm::ConstantInt::get(context, llvm::APInt(32, 0)); } - bool flag = str->getType()->getContainedType(0)->isPointerTy(); + bool is_struct_instance_member = is_a(*ss->m_arg); llvm::Value *str2 = str; - if (flag) { - str2 = CreateLoad(str2); + if (!is_struct_instance_member) { + str2 = llvm_utils->CreateLoad2(character_type, str2); } tmp = builder->CreateCall(fn, {str2, str_val, idx1, idx2, step, lp, rp}); - if (ASR::is_a(*ss->m_arg)) { - ASR::Variable_t *asr_target = EXPR2VAR(ss->m_arg); - if (ASR::is_a(*asr_target->m_type)) { - tmp = lfortran_str_copy(str, tmp); - return; - } - } - if (!flag) { - tmp = CreateLoad(tmp); - } - builder->CreateStore(tmp, str); - strings_to_be_deallocated.push_back(al, tmp); + strings_to_be_deallocated.push_back(al, tmp); // char* returing from this call is dead after making the next str_copy call. + tmp = lfortran_str_copy(str, tmp, ASRUtils::is_descriptorString(expr_type(ss->m_arg))); } void visit_OverloadedStringConcat(const ASR::OverloadedStringConcat_t &x) { @@ -4787,7 +5058,6 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } void visit_Assignment(const ASR::Assignment_t &x) { - get_builder0() if (compiler_options.emit_debug_info) debug_emit_loc(x); if( x.m_overloaded ) { this->visit_stmt(*x.m_overloaded); @@ -4854,7 +5124,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor for( size_t i = 0; i < asr_value_tuple->n_elements; i++ ) { ASR::ttype_t* asr_tuple_i_type = ASRUtils::expr_type(asr_value_tuple->m_elements[i]); llvm::Type* llvm_tuple_i_type = llvm_utils->get_type_from_ttype_t_util(asr_tuple_i_type, module.get()); - llvm::Value* llvm_tuple_i = builder0.CreateAlloca(llvm_tuple_i_type, nullptr); + llvm::Value* llvm_tuple_i = llvm_utils->CreateAlloca(*builder, llvm_tuple_i_type); ptr_loads = !LLVM::is_llvm_struct(asr_tuple_i_type); visit_expr(*asr_value_tuple->m_elements[i]); llvm_utils->deepcopy(tmp, llvm_tuple_i, asr_tuple_i_type, module.get(), name2memidx); @@ -4865,7 +5135,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor ptr_loads = 0; visit_expr(*asr_target_tuple->m_elements[i]); LLVM::CreateStore(*builder, - LLVM::CreateLoad(*builder, src_deepcopies[i]), + llvm_utils->CreateLoad(src_deepcopies[i]), tmp ); } @@ -4968,9 +5238,9 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor if (is_a(*asr_target0->m_v)) { ASR::Variable_t *asr_target = ASRUtils::EXPR2VAR(asr_target0->m_v); int n_dims = ASRUtils::extract_n_dims_from_ttype(asr_target->m_type); - if ( is_a(*ASRUtils::type_get_past_array(asr_target->m_type)) ) { + if ( is_a(*ASRUtils::type_get_past_array(asr_target->m_type)) ) { if (n_dims == 0) { - target = CreateLoad(target); + target = llvm_utils->CreateLoad(target); lhs_is_string_arrayref = true; } } @@ -4978,7 +5248,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } else if (is_a(*x.m_target)) { if( ASRUtils::is_allocatable(x.m_target) && !ASRUtils::is_character(*ASRUtils::expr_type(x.m_target)) ) { - target = CreateLoad(target); + target = llvm_utils->CreateLoad(target); } } else if( ASR::is_a(*x.m_target) ) { ASR::StringItem_t *asr_target0 = ASR::down_cast(x.m_target); @@ -4990,15 +5260,17 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor lhs_is_string_arrayref = true; } } + } else if(is_a(*asr_target0->m_arg)){ // implies that target is character + n_dim = 0. + lhs_is_string_arrayref = true; } } else if (is_a(*x.m_target)) { ASR::ArraySection_t *asr_target0 = ASR::down_cast(x.m_target); if (is_a(*asr_target0->m_v)) { ASR::Variable_t *asr_target = ASRUtils::EXPR2VAR(asr_target0->m_v); - if ( is_a(*ASRUtils::type_get_past_array(asr_target->m_type)) ) { + if ( is_a(*ASRUtils::type_get_past_array(asr_target->m_type)) ) { int n_dims = ASRUtils::extract_n_dims_from_ttype(asr_target->m_type); if (n_dims == 0) { - target = CreateLoad(target); + target = llvm_utils->CreateLoad(target); lhs_is_string_arrayref = true; } } @@ -5023,7 +5295,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor if (ASR::is_a(*asr_target->m_type) && !ASR::is_a( *ASRUtils::get_contained_type(asr_target->m_type))) { - target = CreateLoad(target); + target = llvm_utils->CreateLoad(target); } ASR::ttype_t *cont_type = ASRUtils::get_contained_type(asr_target_type); if ( ASRUtils::is_array(cont_type) ) { @@ -5038,8 +5310,8 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor llvm::Value* array_data = nullptr; if( ASRUtils::extract_physical_type(asr_target_type) == ASR::array_physical_typeType::DescriptorArray ) { - array_data = LLVM::CreateLoad(*builder, - arr_descr->get_pointer_to_data(LLVM::CreateLoad(*builder, target))); + array_data = llvm_utils->CreateLoad( + arr_descr->get_pointer_to_data(llvm_utils->CreateLoad(target))); } else if( ASRUtils::extract_physical_type(asr_target_type) == ASR::array_physical_typeType::FixedSizeArray ) { array_data = llvm_utils->create_gep(target, 0); @@ -5057,12 +5329,12 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor list_data, llvm::MaybeAlign(), size); return ; } - if( asr_target->m_type->type == ASR::ttypeType::Character) { - target = CreateLoad(arr_descr->get_pointer_to_data(target)); + if( asr_target->m_type->type == ASR::ttypeType::String) { + target = llvm_utils->CreateLoad(arr_descr->get_pointer_to_data(target)); } } } - if( ASR::is_a(*x.m_value) ) { + if( ASR::is_a(*x.m_value) ) { return ; } ASR::ttype_t* target_type = ASRUtils::expr_type(x.m_target); @@ -5077,20 +5349,20 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor this->visit_expr_wrapper(m_value, true); ptr_loads = ptr_loads_copy; if( ASR::is_a(*x.m_value) && - ASR::is_a(*value_type) ) { - tmp = LLVM::CreateLoad(*builder, tmp); + ASR::is_a(*value_type) ) { + tmp = llvm_utils->CreateLoad(tmp); } value = tmp; if (ASR::is_a(*target_type)) { if (value->getType()->isPointerTy()) { - value = LLVM::CreateLoad(*builder, value); + value = llvm_utils->CreateLoad(value); } } if ( ASRUtils::is_character(*(ASRUtils::expr_type(x.m_value))) ) { int n_dims = ASRUtils::extract_n_dims_from_ttype(expr_type(x.m_value)); if (n_dims == 0) { if (lhs_is_string_arrayref && value->getType()->isPointerTy()) { - value = CreateLoad(value); + value = llvm_utils->CreateLoad2(llvm::Type::getInt8Ty(context), value); } if ( (ASR::is_a(*x.m_value) || ASR::is_a(*x.m_value) || @@ -5107,7 +5379,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } else if (ASR::is_a(*x.m_target)) { ASR::Variable_t *asr_target = EXPR2VAR(x.m_target); tmp = lfortran_str_copy(target, value, - ASR::is_a(*asr_target->m_type)); + ASRUtils::is_descriptorString(asr_target->m_type)); return; } } @@ -5125,45 +5397,41 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor bool is_target_simd_array = (target_ptype == ASR::array_physical_typeType::SIMDArray); bool is_target_descriptor_based_array = (target_ptype == ASR::array_physical_typeType::DescriptorArray); bool is_value_descriptor_based_array = (value_ptype == ASR::array_physical_typeType::DescriptorArray); + llvm::Type* target_el_type = llvm_utils->get_type_from_ttype_t_util(ASRUtils::extract_type(target_type), module.get()); + llvm::Type* value_el_type = llvm_utils->get_type_from_ttype_t_util(ASRUtils::extract_type(value_type), module.get()); if( is_value_fixed_sized_array && is_target_fixed_sized_array ) { value = llvm_utils->create_gep(value, 0); target = llvm_utils->create_gep(target, 0); ASR::dimension_t* asr_dims = nullptr; size_t asr_n_dims = ASRUtils::extract_dimensions_from_ttype(target_type, asr_dims); int64_t size = ASRUtils::get_fixed_size_of_array(asr_dims, asr_n_dims); - llvm::Type* llvm_data_type = llvm_utils->get_type_from_ttype_t_util(ASRUtils::type_get_past_array( - ASRUtils::type_get_past_allocatable(ASRUtils::type_get_past_pointer(target_type))), module.get()); llvm::DataLayout data_layout(module.get()); - uint64_t data_size = data_layout.getTypeAllocSize(llvm_data_type); + uint64_t data_size = data_layout.getTypeAllocSize(target_el_type); llvm::Value* llvm_size = llvm::ConstantInt::get(context, llvm::APInt(32, size)); llvm_size = builder->CreateMul(llvm_size, llvm::ConstantInt::get(context, llvm::APInt(32, data_size))); builder->CreateMemCpy(target, llvm::MaybeAlign(), value, llvm::MaybeAlign(), llvm_size); } else if( is_value_descriptor_based_array && is_target_fixed_sized_array ) { - value = LLVM::CreateLoad(*builder, arr_descr->get_pointer_to_data(value)); + value = llvm_utils->CreateLoad2(value_el_type->getPointerTo(), arr_descr->get_pointer_to_data(value)); target = llvm_utils->create_gep(target, 0); ASR::dimension_t* asr_dims = nullptr; size_t asr_n_dims = ASRUtils::extract_dimensions_from_ttype(target_type, asr_dims); int64_t size = ASRUtils::get_fixed_size_of_array(asr_dims, asr_n_dims); - llvm::Type* llvm_data_type = llvm_utils->get_type_from_ttype_t_util(ASRUtils::type_get_past_array( - ASRUtils::type_get_past_allocatable(ASRUtils::type_get_past_pointer(target_type))), module.get()); llvm::DataLayout data_layout(module.get()); - uint64_t data_size = data_layout.getTypeAllocSize(llvm_data_type); + uint64_t data_size = data_layout.getTypeAllocSize(target_el_type); llvm::Value* llvm_size = llvm::ConstantInt::get(context, llvm::APInt(32, size)); llvm_size = builder->CreateMul(llvm_size, llvm::ConstantInt::get(context, llvm::APInt(32, data_size))); builder->CreateMemCpy(target, llvm::MaybeAlign(), value, llvm::MaybeAlign(), llvm_size); } else if( is_target_descriptor_based_array && is_value_fixed_sized_array ) { if( ASRUtils::is_allocatable(target_type) ) { - target = LLVM::CreateLoad(*builder, target); + target = llvm_utils->CreateLoad(target); } llvm::Value* llvm_size = arr_descr->get_array_size(target, nullptr, 4); - target = LLVM::CreateLoad(*builder, arr_descr->get_pointer_to_data(target)); + target = llvm_utils->CreateLoad2(target_el_type->getPointerTo(), arr_descr->get_pointer_to_data(target)); value = llvm_utils->create_gep(value, 0); - llvm::Type* llvm_data_type = llvm_utils->get_type_from_ttype_t_util(ASRUtils::type_get_past_array( - ASRUtils::type_get_past_allocatable(ASRUtils::type_get_past_pointer(value_type))), module.get()); llvm::DataLayout data_layout(module.get()); - uint64_t data_size = data_layout.getTypeAllocSize(llvm_data_type); + uint64_t data_size = data_layout.getTypeAllocSize(value_el_type); llvm_size = builder->CreateMul(llvm_size, llvm::ConstantInt::get(context, llvm::APInt(32, data_size))); builder->CreateMemCpy(target, llvm::MaybeAlign(), value, llvm::MaybeAlign(), llvm_size); @@ -5192,7 +5460,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor llvm_size = builder->CreateMul(llvm_size, tmp); } } else { - target_data = LLVM::CreateLoad(*builder, arr_descr->get_pointer_to_data(target)); + target_data = llvm_utils->CreateLoad(arr_descr->get_pointer_to_data(target)); } if( is_value_data_only_array ) { value_data = value; @@ -5211,15 +5479,16 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } } } else { - value_data = LLVM::CreateLoad(*builder, arr_descr->get_pointer_to_data(value)); + llvm::Type* llvm_array_type = llvm_utils->get_type_from_ttype_t_util( + ASRUtils::type_get_past_array( + ASRUtils::type_get_past_allocatable_pointer( + ASRUtils::expr_type(x.m_value))), module.get()); + value_data = llvm_utils->CreateLoad2(llvm_array_type->getPointerTo(), + arr_descr->get_pointer_to_data(value)); } LCOMPILERS_ASSERT(data_only_copy); - llvm::Type* llvm_data_type = llvm_utils->get_type_from_ttype_t_util( - ASRUtils::type_get_past_allocatable( - ASRUtils::type_get_past_pointer( - ASRUtils::type_get_past_array(target_type))), module.get()); - arr_descr->copy_array_data_only(value_data, target_data, module.get(), - llvm_data_type, llvm_size); + arr_descr->copy_array_data_only(target_data, value_data, module.get(), + target_el_type, llvm_size); } else if ( is_target_simd_array ) { if (ASR::is_a(*x.m_value)) { int idx = 1; @@ -5230,10 +5499,8 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor ASR::dimension_t* asr_dims = nullptr; size_t asr_n_dims = ASRUtils::extract_dimensions_from_ttype(target_type, asr_dims); int64_t size = ASRUtils::get_fixed_size_of_array(asr_dims, asr_n_dims); - llvm::Type* llvm_data_type = llvm_utils->get_type_from_ttype_t_util(ASRUtils::type_get_past_array( - ASRUtils::type_get_past_allocatable(ASRUtils::type_get_past_pointer(target_type))), module.get()); llvm::DataLayout data_layout(module.get()); - uint64_t data_size = data_layout.getTypeAllocSize(llvm_data_type); + uint64_t data_size = data_layout.getTypeAllocSize(target_el_type); llvm::Value* llvm_size = llvm::ConstantInt::get(context, llvm::APInt(32, size)); llvm_size = builder->CreateMul(llvm_size, llvm::ConstantInt::get(context, llvm::APInt(32, data_size))); @@ -5242,13 +5509,11 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor builder->CreateStore(value, target); } } else { - bool create_dim_des_array = false; if( LLVM::is_llvm_pointer(*target_type) ) { - target = LLVM::CreateLoad(*builder, target); - create_dim_des_array = true; + target = llvm_utils->CreateLoad(target); } arr_descr->copy_array(value, target, module.get(), - target_type, create_dim_des_array, false); + target_type, false); } } else if( ASR::is_a(*x.m_target) ) { ASR::DictItem_t* dict_item_t = ASR::down_cast(x.m_target); @@ -5277,13 +5542,10 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } void PointerToData_to_Descriptor(ASR::ttype_t* m_type, ASR::ttype_t* m_type_for_dimensions) { - llvm::BasicBlock &entry_block = builder->GetInsertBlock()->getParent()->getEntryBlock(); - llvm::IRBuilder<> builder0(context); - builder0.SetInsertPoint(&entry_block, entry_block.getFirstInsertionPt()); llvm::Type* target_type = llvm_utils->get_type_from_ttype_t_util( ASRUtils::type_get_past_allocatable( ASRUtils::type_get_past_pointer(m_type)), module.get()); - llvm::AllocaInst *target = builder0.CreateAlloca( + llvm::AllocaInst *target = llvm_utils->CreateAlloca( target_type, nullptr, "array_descriptor"); builder->CreateStore(tmp, arr_descr->get_pointer_to_data(target)); ASR::dimension_t* m_dims = nullptr; @@ -5292,7 +5554,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor ASRUtils::type_get_past_pointer(ASRUtils::type_get_past_allocatable(m_type)), module.get()); fill_array_details(target, llvm_data_type, m_dims, n_dims, false, false); if( LLVM::is_llvm_pointer(*m_type) ) { - llvm::AllocaInst* target_ptr = builder0.CreateAlloca( + llvm::AllocaInst* target_ptr = llvm_utils->CreateAlloca( target_type->getPointerTo(), nullptr, "array_descriptor_ptr"); builder->CreateStore(target, target_ptr); target = target_ptr; @@ -5309,13 +5571,19 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor return ; } + llvm::Type *data_type = llvm_utils->get_type_from_ttype_t_util(ASRUtils::extract_type(ASRUtils::expr_type(m_arg)), module.get()); + llvm::Type *arr_type = llvm_utils->get_type_from_ttype_t_util( + ASRUtils::type_get_past_allocatable( + ASRUtils::type_get_past_pointer(ASRUtils::expr_type(m_arg))), + module.get()); if( m_new == ASR::array_physical_typeType::PointerToDataArray && m_old == ASR::array_physical_typeType::DescriptorArray ) { if( ASR::is_a(*m_arg) ) { - arg = LLVM::CreateLoad(*builder, arg); + arg = llvm_utils->CreateLoad2(ASRUtils::expr_type(m_arg), arg); + ptr_type[arg] = arr_type; } - tmp = LLVM::CreateLoad(*builder, arr_descr->get_pointer_to_data(arg)); - tmp = llvm_utils->create_ptr_gep(tmp, arr_descr->get_offset(arg)); + tmp = llvm_utils->CreateLoad2(data_type->getPointerTo(), arr_descr->get_pointer_to_data(arg)); + tmp = llvm_utils->create_ptr_gep2(data_type, tmp, arr_descr->get_offset(arg)); } else if( m_new == ASR::array_physical_typeType::PointerToDataArray && m_old == ASR::array_physical_typeType::FixedSizeArray) { @@ -5323,7 +5591,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor !ASR::is_a(*ASRUtils::expr_value(m_arg))) || ASRUtils::expr_value(m_arg) == nullptr ) && !ASR::is_a(*m_arg) ) { - tmp = llvm_utils->create_gep(tmp, 0); + tmp = llvm_utils->CreateGEP2(ASRUtils::expr_type(m_arg), tmp, 0); } } else if( m_new == ASR::array_physical_typeType::UnboundedPointerToDataArray && @@ -5341,7 +5609,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } else if ( m_new == ASR::array_physical_typeType::DescriptorArray && m_old == ASR::array_physical_typeType::SIMDArray) { - tmp = CreateLoad(arg); + tmp = llvm_utils->CreateLoad(arg); } else if( m_new == ASR::array_physical_typeType::DescriptorArray && m_old == ASR::array_physical_typeType::FixedSizeArray) { @@ -5349,7 +5617,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor !ASR::is_a(*ASRUtils::expr_value(m_arg))) || ASRUtils::expr_value(m_arg) == nullptr) && !ASR::is_a(*m_arg) ) { - tmp = llvm_utils->create_gep(tmp, 0); + tmp = llvm_utils->create_gep2(arr_type, tmp, 0); } PointerToData_to_Descriptor(m_type, m_type_for_dimensions); } else if( @@ -5359,7 +5627,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } else if( m_new == ASR::array_physical_typeType::FixedSizeArray && m_old == ASR::array_physical_typeType::DescriptorArray) { - tmp = LLVM::CreateLoad(*builder, arr_descr->get_pointer_to_data(tmp)); + tmp = llvm_utils->CreateLoad2(data_type->getPointerTo(), arr_descr->get_pointer_to_data(tmp)); llvm::Type* target_type = llvm_utils->get_type_from_ttype_t_util(m_type, module.get())->getPointerTo(); tmp = builder->CreateBitCast(tmp, target_type); } else if( @@ -5367,23 +5635,20 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor m_old == ASR::array_physical_typeType::DescriptorArray) { // TODO: For allocatables, first check if its allocated (generate code for it) // and then if its allocated only then proceed with reseting array details. - llvm::BasicBlock &entry_block = builder->GetInsertBlock()->getParent()->getEntryBlock(); - llvm::IRBuilder<> builder0(context); - builder0.SetInsertPoint(&entry_block, entry_block.getFirstInsertionPt()); llvm::Type* target_type = llvm_utils->get_type_from_ttype_t_util( ASRUtils::type_get_past_allocatable( ASRUtils::type_get_past_pointer(m_type)), module.get()); - llvm::AllocaInst *target = builder0.CreateAlloca( + llvm::AllocaInst *target = llvm_utils->CreateAlloca( target_type, nullptr, "array_descriptor"); - builder->CreateStore(llvm_utils->create_ptr_gep( - LLVM::CreateLoad(*builder, arr_descr->get_pointer_to_data(tmp)), + builder->CreateStore(llvm_utils->create_ptr_gep2(data_type, + llvm_utils->CreateLoad2(data_type->getPointerTo(), arr_descr->get_pointer_to_data(tmp)), arr_descr->get_offset(tmp)), arr_descr->get_pointer_to_data(target)); int n_dims = ASRUtils::extract_n_dims_from_ttype(m_type_for_dimensions); arr_descr->reset_array_details(target, tmp, n_dims); tmp = target; } else if ( m_new == ASR::array_physical_typeType::PointerToDataArray && - m_old == ASR::array_physical_typeType::CharacterArraySinglePointer) { + m_old == ASR::array_physical_typeType::StringArraySinglePointer) { // if (ASRUtils::is_fixed_size_array(m_type)) { if( ((ASRUtils::expr_value(m_arg) && @@ -5393,17 +5658,17 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor tmp = llvm_utils->create_gep(tmp, 0); } } else { - tmp = LLVM::CreateLoad(*builder, arr_descr->get_pointer_to_data(tmp)); + tmp = llvm_utils->CreateLoad(arr_descr->get_pointer_to_data(tmp)); } } else if ( - m_new == ASR::array_physical_typeType::CharacterArraySinglePointer && + m_new == ASR::array_physical_typeType::StringArraySinglePointer && m_old == ASR::array_physical_typeType::DescriptorArray) { if (ASRUtils::is_fixed_size_array(m_type)) { - tmp = LLVM::CreateLoad(*builder, arr_descr->get_pointer_to_data(tmp)); + tmp = llvm_utils->CreateLoad(arr_descr->get_pointer_to_data(tmp)); llvm::Type* target_type = llvm_utils->get_type_from_ttype_t_util(m_type, module.get())->getPointerTo(); tmp = builder->CreateBitCast(tmp, target_type); // [1 x i8*]* // we need [1 x i8*] - tmp = LLVM::CreateLoad(*builder, tmp); + tmp = llvm_utils->CreateLoad(tmp); } } else { LCOMPILERS_ASSERT(false); @@ -5494,8 +5759,9 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor x->type == ASR::exprType::ArraySection || x->type == ASR::exprType::StructInstanceMember ) { if( load_ref && - !ASRUtils::is_value_constant(ASRUtils::expr_value(x)) ) { - tmp = CreateLoad(tmp); + !ASRUtils::is_value_constant(ASRUtils::expr_value(x)) && + !ASRUtils::is_descriptorString(expr_type(x)) ) { + tmp = llvm_utils->CreateLoad2(ASRUtils::expr_type(x), tmp); } } } @@ -5511,17 +5777,27 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } void visit_SelectType(const ASR::SelectType_t& x) { - LCOMPILERS_ASSERT(ASR::is_a(*x.m_selector)); + LCOMPILERS_ASSERT(ASR::is_a(*x.m_selector) || ASR::is_a(*x.m_selector)); // Process TypeStmtName first, then ClassStmt std::vector select_type_stmts; fill_type_stmt(x, select_type_stmts, ASR::type_stmtType::TypeStmtName); fill_type_stmt(x, select_type_stmts, ASR::type_stmtType::TypeStmtType); fill_type_stmt(x, select_type_stmts, ASR::type_stmtType::ClassStmt); LCOMPILERS_ASSERT(x.n_body == select_type_stmts.size()); - ASR::Var_t* selector_var = ASR::down_cast(x.m_selector); + ASR::Var_t* selector_var = nullptr; + ASR::StructInstanceMember_t* selector_struct = nullptr; + if (ASR::is_a(*x.m_selector)) { + selector_var = ASR::down_cast(x.m_selector); + } else if (ASR::is_a(*x.m_selector)) { + selector_struct = ASR::down_cast(x.m_selector); + } uint64_t ptr_loads_copy = ptr_loads; ptr_loads = 0; - visit_Var(*selector_var); + if (selector_var) { + visit_Var(*selector_var); + } else if (selector_struct) { + visit_StructInstanceMember(*selector_struct); + } ptr_loads = ptr_loads_copy; llvm::Value* llvm_selector = tmp; llvm::BasicBlock *mergeBB = llvm::BasicBlock::Create(context, "ifcont"); @@ -5534,18 +5810,19 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor llvm::Value* cond = nullptr; ASR::stmt_t** type_block = nullptr; size_t n_type_block = 0; + llvm::Type *i64 = llvm::Type::getInt64Ty(context); switch( select_type_stmts[i]->type ) { case ASR::type_stmtType::TypeStmtName: { - llvm::Value* vptr_int_hash = CreateLoad(llvm_utils->create_gep(llvm_selector, 0)); ASR::ttype_t* selector_var_type = ASRUtils::expr_type(x.m_selector); + llvm::Value* vptr_int_hash = llvm_utils->CreateLoad2(i64, llvm_utils->create_gep(llvm_selector, 0)); if( ASRUtils::is_array(selector_var_type) ) { - vptr_int_hash = CreateLoad(llvm_utils->create_gep(vptr_int_hash, 0)); + vptr_int_hash = llvm_utils->CreateLoad(llvm_utils->create_gep(vptr_int_hash, 0)); } ASR::TypeStmtName_t* type_stmt_name = ASR::down_cast(select_type_stmts[i]); ASR::symbol_t* type_sym = ASRUtils::symbol_get_past_external(type_stmt_name->m_sym); if( ASR::is_a(*type_sym) ) { current_select_type_block_type = llvm_utils->getStructType( - ASR::down_cast(type_sym), module.get(), true); + ASR::down_cast(type_sym), module.get(), false); current_select_type_block_der_type = ASR::down_cast(type_sym)->m_name; } else { LCOMPILERS_ASSERT(false); @@ -5557,18 +5834,18 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor llvm::Value* type_sym_vtab = type2vtab[type_sym][current_scope]; cond = builder->CreateICmpEQ( vptr_int_hash, - CreateLoad( llvm_utils->create_gep(type_sym_vtab, 0) ) ); + llvm_utils->CreateLoad2( i64, llvm_utils->create_gep(type_sym_vtab, 0) ) ); type_block = type_stmt_name->m_body; n_type_block = type_stmt_name->n_body; break ; } case ASR::type_stmtType::ClassStmt: { - llvm::Value* vptr_int_hash = CreateLoad(llvm_utils->create_gep(llvm_selector, 0)); + llvm::Value* vptr_int_hash = llvm_utils->CreateLoad2(i64, llvm_utils->create_gep(llvm_selector, 0)); ASR::ClassStmt_t* class_stmt = ASR::down_cast(select_type_stmts[i]); ASR::symbol_t* class_sym = ASRUtils::symbol_get_past_external(class_stmt->m_sym); if( ASR::is_a(*class_sym) ) { current_select_type_block_type = llvm_utils->getStructType( - ASR::down_cast(class_sym), module.get(), true); + ASR::down_cast(class_sym), module.get(), false); current_select_type_block_der_type = ASR::down_cast(class_sym)->m_name; } else { LCOMPILERS_ASSERT(false); @@ -5580,7 +5857,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor for( size_t i = 0; i < class_sym_vtabs.size(); i++ ) { conds.push_back(builder->CreateICmpEQ( vptr_int_hash, - CreateLoad(llvm_utils->create_gep(class_sym_vtabs[i], 0)) )); + llvm_utils->CreateLoad2(i64, llvm_utils->create_gep(class_sym_vtabs[i], 0)) )); } cond = builder->CreateOr(conds); type_block = class_stmt->m_body; @@ -5591,16 +5868,17 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor ASR::ttype_t* selector_var_type = ASRUtils::expr_type(x.m_selector); ASR::TypeStmtType_t* type_stmt_type_t = ASR::down_cast(select_type_stmts[i]); ASR::ttype_t* type_stmt_type = type_stmt_type_t->m_type; - current_select_type_block_type = llvm_utils->get_type_from_ttype_t_util(type_stmt_type, module.get())->getPointerTo(); + current_select_type_block_type = llvm_utils->get_type_from_ttype_t_util(type_stmt_type, module.get()); llvm::Value* intrinsic_type_id = llvm::ConstantInt::get(llvm_utils->getIntType(8), llvm::APInt(64, -((int) type_stmt_type->type) - ASRUtils::extract_kind_from_ttype_t(type_stmt_type), true)); llvm::Value* _type_id = nullptr; if( ASRUtils::is_array(selector_var_type) ) { - llvm::Value* data_ptr = CreateLoad(arr_descr->get_pointer_to_data(llvm_selector)); - _type_id = CreateLoad(llvm_utils->create_gep(data_ptr, 0)); + llvm::Type* el_type = llvm_utils->get_type_from_ttype_t_util(ASRUtils::extract_type(selector_var_type), module.get()); + llvm::Value* data_ptr = llvm_utils->CreateLoad2(el_type->getPointerTo(), arr_descr->get_pointer_to_data(llvm_selector)); + _type_id = llvm_utils->CreateLoad2(llvm::Type::getInt64Ty(context), llvm_utils->create_gep2(el_type, data_ptr, 0)); } else { - _type_id = CreateLoad(llvm_utils->create_gep(llvm_selector, 0)); + _type_id = llvm_utils->CreateLoad(llvm_utils->create_gep(llvm_selector, 0)); } cond = builder->CreateICmpEQ(_type_id, intrinsic_type_id); type_block = type_stmt_type_t->m_body; @@ -5797,7 +6075,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor break; } case (ASR::cmpopType::NotEq) : { - tmp = builder->CreateFCmpONE(left, right); + tmp = builder->CreateFCmpUNE(left, right); break; } default : { @@ -5856,8 +6134,8 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor bool is_single_char = (ASR::is_a(*x.m_left) && ASR::is_a(*x.m_right)); if( is_single_char ) { - left = LLVM::CreateLoad(*builder, left); - right = LLVM::CreateLoad(*builder, right); + left = llvm_utils->CreateLoad2(llvm::Type::getInt8Ty(context), left); + right = llvm_utils->CreateLoad2(llvm::Type::getInt8Ty(context), right); } std::string fn; switch (x.m_op) { @@ -5991,7 +6269,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor this->visit_expr_wrapper(x.m_test, true); llvm::Value *cond = tmp; llvm::Type* _type = llvm_utils->get_type_from_ttype_t_util(x.m_type, module.get()); - llvm::Value* ifexp_res = CreateAlloca(_type, nullptr, ""); + llvm::Value* ifexp_res = llvm_utils->CreateAlloca(_type, nullptr, ""); llvm_utils->create_if_else(cond, [&]() { this->visit_expr_wrapper(x.m_body, true); builder->CreateStore(tmp, ifexp_res); @@ -5999,7 +6277,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor this->visit_expr_wrapper(x.m_orelse, true); builder->CreateStore(tmp, ifexp_res); }); - tmp = CreateLoad(ifexp_res); + tmp = llvm_utils->CreateLoad(ifexp_res); } // TODO: Implement visit_DooLoop @@ -6014,196 +6292,12 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor this->visit_expr_wrapper(x.m_test, true); call_lcompilers_free_strings(); return tmp; - }, [&]() { - for (size_t i=0; ivisit_stmt(*x.m_body[i]); - } - call_lcompilers_free_strings(); - }); - strings_to_be_deallocated.reserve(al, n); - strings_to_be_deallocated.n = n; - strings_to_be_deallocated.p = strings_to_be_deallocated_copy; - } - - void visit_ForEach(const ASR::ForEach_t &x) { - get_builder0() - llvm::Value **strings_to_be_deallocated_copy = strings_to_be_deallocated.p; - size_t n = strings_to_be_deallocated.n; - strings_to_be_deallocated.reserve(al, 1); - - int64_t ptr_loads_copy = ptr_loads; - ptr_loads = 0; - this->visit_expr(*x.m_container); - llvm::Value *pcontainer = tmp; - ptr_loads = 0; - this->visit_expr(*x.m_var); - llvm::Value *pvar = tmp; - ptr_loads = ptr_loads_copy; - - if (ASR::is_a(*ASRUtils::expr_type(x.m_container))) { - ASR::Dict_t *dict_type = ASR::down_cast( - ASRUtils::expr_type(x.m_container)); - ASR::ttype_t *key_type = dict_type->m_key_type; - llvm::Value *capacity = LLVM::CreateLoad(*builder, - llvm_utils->dict_api->get_pointer_to_capacity(pcontainer)); - llvm::Value *key_mask = LLVM::CreateLoad(*builder, - llvm_utils->dict_api->get_pointer_to_keymask(pcontainer)); - llvm::Value *key_list = llvm_utils->dict_api->get_key_list(pcontainer); - llvm::AllocaInst *idx_ptr = builder0.CreateAlloca( - llvm::Type::getInt32Ty(context), nullptr); - LLVM::CreateStore(*builder, llvm::ConstantInt::get( - llvm::Type::getInt32Ty(context), llvm::APInt(32, 0)), idx_ptr); - - if (llvm_utils->dict_api == llvm_utils->dict_api_sc) { - llvm::Value *key_value_pairs = LLVM::CreateLoad(*builder, - llvm_utils->dict_api->get_pointer_to_key_value_pairs(pcontainer)); - llvm::Type* kv_pair_type = - llvm_utils->dict_api->get_key_value_pair_type(key_type, dict_type->m_value_type); - llvm::AllocaInst *chain_itr = builder0.CreateAlloca( - llvm::Type::getInt8PtrTy(context), nullptr); - - create_loop(nullptr, [=](){ - call_lcompilers_free_strings(); - return builder->CreateICmpSGT(capacity, LLVM::CreateLoad(*builder, idx_ptr)); - }, [&](){ - llvm::Value* idx = LLVM::CreateLoad(*builder, idx_ptr); - llvm::Value* key_mask_value = LLVM::CreateLoad(*builder, - llvm_utils->create_ptr_gep(key_mask, idx)); - llvm::Value* is_key_set = builder->CreateICmpEQ(key_mask_value, - llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), llvm::APInt(8, 1))); - - llvm_utils->create_if_else(is_key_set, [&]() { - llvm::Value* dict_i = llvm_utils->create_ptr_gep(key_value_pairs, idx); - llvm::Value* kv_ll_i8 = builder->CreateBitCast(dict_i, llvm::Type::getInt8PtrTy(context)); - LLVM::CreateStore(*builder, kv_ll_i8, chain_itr); - - llvm::BasicBlock *loop2head = llvm::BasicBlock::Create(context, "loop2.head"); - llvm::BasicBlock *loop2body = llvm::BasicBlock::Create(context, "loop2.body"); - llvm::BasicBlock *loop2end = llvm::BasicBlock::Create(context, "loop2.end"); - - // head - llvm_utils->start_new_block(loop2head); - { - llvm::Value *cond = builder->CreateICmpNE( - LLVM::CreateLoad(*builder, chain_itr), - llvm::ConstantPointerNull::get(llvm::Type::getInt8PtrTy(context)) - ); - builder->CreateCondBr(cond, loop2body, loop2end); - } - - // body - llvm_utils->start_new_block(loop2body); - { - llvm::Value* kv_struct_i8 = LLVM::CreateLoad(*builder, chain_itr); - llvm::Value* kv_struct = builder->CreateBitCast(kv_struct_i8, kv_pair_type->getPointerTo()); - llvm::Value* kv_el = llvm_utils->create_gep(kv_struct, 0); - if( !LLVM::is_llvm_struct(key_type) ) { - kv_el = LLVM::CreateLoad(*builder, kv_el); - } - LLVM::CreateStore(*builder, kv_el, pvar); - for (size_t i=0; ivisit_stmt(*x.m_body[i]); - } - call_lcompilers_free_strings(); - llvm::Value* next_kv_struct = LLVM::CreateLoad(*builder, llvm_utils->create_gep(kv_struct, 2)); - LLVM::CreateStore(*builder, next_kv_struct, chain_itr); - } - - builder->CreateBr(loop2head); - - // end - llvm_utils->start_new_block(loop2end); - }, [=]() { - }); - llvm::Value* tmp = builder->CreateAdd(idx, - llvm::ConstantInt::get(context, llvm::APInt(32, 1))); - LLVM::CreateStore(*builder, tmp, idx_ptr); - - }); - - } else { - create_loop(nullptr, [=](){ - call_lcompilers_free_strings(); - return builder->CreateICmpSGT(capacity, LLVM::CreateLoad(*builder, idx_ptr)); - }, [&](){ - llvm::Value *idx = LLVM::CreateLoad(*builder, idx_ptr); - llvm::Value *key_mask_value = LLVM::CreateLoad(*builder, - llvm_utils->create_ptr_gep(key_mask, idx)); - llvm::Value *is_key_skip = builder->CreateICmpEQ(key_mask_value, - llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), - llvm::APInt(8, 3))); - llvm::Value *is_key_set = builder->CreateICmpNE(key_mask_value, - llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), - llvm::APInt(8, 0))); - - llvm::Value *el_exists = builder->CreateAnd(is_key_set, - builder->CreateNot(is_key_skip)); - - llvm_utils->create_if_else(el_exists, [&]() { - LLVM::CreateStore(*builder, llvm_utils->list_api->read_item(key_list, idx, - false, *module, LLVM::is_llvm_struct(key_type)), pvar); - - for (size_t i=0; ivisit_stmt(*x.m_body[i]); - } - call_lcompilers_free_strings(); - }, [=](){}); - - idx = builder->CreateAdd(idx, - llvm::ConstantInt::get(context, llvm::APInt(32, 1))); - LLVM::CreateStore(*builder, idx, idx_ptr); - }); - } - } else if (ASR::is_a(*ASRUtils::expr_type(x.m_container))) { - ASR::Set_t *set_type = ASR::down_cast( - ASRUtils::expr_type(x.m_container)); - ASR::ttype_t *el_type = set_type->m_type; - - llvm::AllocaInst *idx_ptr = builder0.CreateAlloca( - llvm::Type::getInt32Ty(context), nullptr); - LLVM::CreateStore(*builder, llvm::ConstantInt::get( - llvm::Type::getInt32Ty(context), llvm::APInt(32, 0)), idx_ptr); - - llvm::Value *capacity = LLVM::CreateLoad(*builder, - llvm_utils->set_api->get_pointer_to_capacity(pcontainer)); - llvm::Value *el_list = llvm_utils->set_api->get_el_list(pcontainer); - llvm::Value *el_mask = LLVM::CreateLoad(*builder, - llvm_utils->set_api->get_pointer_to_mask(pcontainer)); - - create_loop(nullptr, [=](){ - call_lcompilers_free_strings(); - return builder->CreateICmpSGT(capacity, LLVM::CreateLoad(*builder, idx_ptr)); - }, [&](){ - llvm::Value *idx = LLVM::CreateLoad(*builder, idx_ptr); - llvm::Value *el_mask_value = LLVM::CreateLoad(*builder, - llvm_utils->create_ptr_gep(el_mask, idx)); - llvm::Value *is_el_skip = builder->CreateICmpEQ(el_mask_value, - llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), - llvm::APInt(8, 3))); - llvm::Value *is_el_set = builder->CreateICmpNE(el_mask_value, - llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), - llvm::APInt(8, 0))); - - llvm::Value *el_exists = builder->CreateAnd(is_el_set, - builder->CreateNot(is_el_skip)); - - llvm_utils->create_if_else(el_exists, [&]() { - LLVM::CreateStore(*builder, llvm_utils->list_api->read_item(el_list, idx, - false, *module, LLVM::is_llvm_struct(el_type)), pvar); - - for (size_t i=0; ivisit_stmt(*x.m_body[i]); - } - call_lcompilers_free_strings(); - }, [=](){}); - - idx = builder->CreateAdd(idx, - llvm::ConstantInt::get(context, llvm::APInt(32, 1))); - LLVM::CreateStore(*builder, idx, idx_ptr); - }); - } else { - throw CodeGenError("Only sets and dictionaries are supported with this loop for now."); - } + }, [&]() { + for (size_t i=0; ivisit_stmt(*x.m_body[i]); + } + call_lcompilers_free_strings(); + }); strings_to_be_deallocated.reserve(al, n); strings_to_be_deallocated.n = n; strings_to_be_deallocated.p = strings_to_be_deallocated_copy; @@ -6323,7 +6417,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } cond = builder->CreateFCmpUEQ(left_val, zero); } else if (ASRUtils::is_character(*x.m_type)) { - zero = builder->CreateGlobalStringPtr(""); + zero = llvm::Constant::getNullValue(character_type); cond = lfortran_str_cmp(left_val, zero, "_lpython_str_compare_eq"); } else if (ASRUtils::is_logical(*x.m_type)) { zero = llvm::ConstantInt::get(context, @@ -6388,7 +6482,6 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } void visit_StringLen(const ASR::StringLen_t &x) { - get_builder0() if (x.m_value) { this->visit_expr_wrapper(x.m_value, true); return; @@ -6397,7 +6490,14 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor ptr_loads = 2 - LLVM::is_llvm_pointer(*ASRUtils::expr_type(x.m_arg)); this->visit_expr_wrapper(x.m_arg, true); ptr_loads = ptr_loads_copy; - llvm::AllocaInst *parg = builder0.CreateAlloca(character_type, nullptr); + if(ASRUtils::is_descriptorString(ASRUtils::expr_type(x.m_arg))){ + llvm::Value* str_size = builder->CreateLoad(llvm::Type::getInt64Ty(context), + llvm_utils->create_gep2(string_descriptor, tmp, 1)); + tmp = builder->CreateSExtOrTrunc(str_size, + llvm_utils->get_type_from_ttype_t_util(x.m_type, module.get())); + return; + } + llvm::AllocaInst *parg = llvm_utils->CreateAlloca(*builder, character_type); builder->CreateStore(tmp, parg); ASR::ttype_t* arg_type = ASRUtils::get_contained_type(ASRUtils::expr_type(x.m_arg)); tmp = builder->CreateSExtOrTrunc( @@ -6406,13 +6506,12 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } void visit_StringOrd(const ASR::StringOrd_t &x) { - get_builder0() if (x.m_value) { this->visit_expr_wrapper(x.m_value, true); return; } this->visit_expr_wrapper(x.m_arg, true); - llvm::AllocaInst *parg = builder0.CreateAlloca(character_type, nullptr); + llvm::AllocaInst *parg = llvm_utils->CreateAlloca(*builder, character_type); builder->CreateStore(tmp, parg); tmp = lfortran_str_ord(parg); } @@ -6442,29 +6541,13 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor idx = builder->CreateSub(builder->CreateSExtOrTrunc(idx, llvm::Type::getInt32Ty(context)), llvm::ConstantInt::get(context, llvm::APInt(32, 1))); std::vector idx_vec = {idx}; - tmp = CreateGEP(str, idx_vec); + tmp = llvm_utils->CreateGEP2(llvm::Type::getInt8Ty(context), str, idx_vec); } else { tmp = lfortran_str_item(str, idx); strings_to_be_deallocated.push_back(al, tmp); } } - void visit_StringContains(const ASR::StringContains_t& x) { - if (x.m_value) { - this->visit_expr_wrapper(x.m_value, true); - return; - } - - this->visit_expr_wrapper(x.m_substr, true); - llvm::Value *substr = tmp; - - this->visit_expr_wrapper(x.m_str, true); - llvm::Value *right = tmp; - - tmp = lfortran_str_contains(right, substr); - strings_to_be_deallocated.push_back(al, tmp); - } - void visit_StringSection(const ASR::StringSection_t& x) { if (x.m_value) { this->visit_expr_wrapper(x.m_value, true); @@ -6504,7 +6587,48 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor step = llvm::ConstantInt::get(context, llvm::APInt(32, 1)); } - tmp = lfortran_str_slice(str, left, right, step, left_present, right_present); + int x_step_kind = (ASRUtils::extract_kind_from_ttype_t(down_cast(x.m_step)->m_type)); + if(!x.m_start && !x.m_end && !x.m_step){ + tmp = str; // no need for slicing + } else { + if (x_step_kind == 8) { + tmp = lfortran_str_slice8(str, left, right, step, left_present, right_present); + } else { + tmp = lfortran_str_slice(str, left, right, step, left_present, right_present); + } + } + } + + void visit_StringPhysicalCast(const ASR::StringPhysicalCast_t &x){ + int64_t ptr_loads_copy = ptr_loads; + if( x.m_old == ASR::string_physical_typeType::DescriptorString && + x.m_new == ASR::string_physical_typeType::PointerString){ + ptr_loads = 0; + this->visit_expr(*x.m_arg); + llvm::Value* fetched_ptr = llvm_utils->create_gep2(string_descriptor, tmp, 0); + if(ptr_loads_copy > 0){ + tmp = llvm_utils->CreateLoad2(character_type, fetched_ptr); + } else { + tmp = fetched_ptr; + } + } else if ( x.m_old == ASR::string_physical_typeType::PointerString && + x.m_new == ASR::string_physical_typeType::DescriptorString){ + // Create string descriptor and fetch its char*, size, capacity + llvm::Value* string_desc = llvm_utils->CreateAlloca(*builder, string_descriptor, nullptr,"casted_string_ptr_to_desc"); + llvm::Value* char_ptr = llvm_utils->create_gep2(string_descriptor, string_desc, 0); + llvm::Value* string_size_ptr = llvm_utils->create_gep2(string_descriptor, string_desc, 1); + llvm::Value* string_capacity_ptr = llvm_utils->create_gep2(string_descriptor, string_desc, 2); + + ptr_loads = 1; // load char** + this->visit_expr_wrapper(x.m_arg, true); + + // Store char*, size, capacity + builder->CreateStore(tmp, char_ptr); + builder->CreateStore(llvm::ConstantInt::get(llvm::Type::getInt64Ty(context), -1), string_size_ptr); + builder->CreateStore(llvm::ConstantInt::get(llvm::Type::getInt64Ty(context), -1), string_capacity_ptr); + tmp = string_desc; + } + ptr_loads = ptr_loads_copy; } void visit_RealCopySign(const ASR::RealCopySign_t& x) { @@ -6523,10 +6647,10 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor a_kind = down_cast(ASRUtils::type_get_past_pointer(x.m_type))->m_kind; type = llvm_utils->getFPType(a_kind); if (ASR::is_a(*(x.m_target))) { - target = LLVM::CreateLoad(*builder, target); + target = llvm_utils->CreateLoad2(type, target); } if (ASR::is_a(*(x.m_source))) { - source = LLVM::CreateLoad(*builder, source); + source = llvm_utils->CreateLoad2(type, source); } llvm::Value *ftarget = builder->CreateSIToFP(target, type); @@ -6578,30 +6702,27 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor break; }; case ASR::binopType::Pow: { - llvm::Type *type; - int a_kind; - a_kind = down_cast(ASRUtils::extract_type(x.m_type))->m_kind; - if( a_kind <= 4 ) { - type = llvm_utils->getFPType(4); - } else { - type = llvm_utils->getFPType(8); - } - llvm::Value *fleft = builder->CreateSIToFP(left_val, - type); - llvm::Value *fright = builder->CreateSIToFP(right_val, - type); - std::string func_name = a_kind <= 4 ? "llvm.pow.f32" : "llvm.pow.f64"; + const int expr_return_kind = ASRUtils::extract_kind_from_ttype_t(x.m_type); + llvm::Type* const exponent_type = llvm::Type::getInt32Ty(context); + llvm::Type* const return_type = llvm_utils->getIntType(expr_return_kind); // returnType of the expression. + llvm::Type* const base_type =llvm_utils->getFPType(expr_return_kind == 8 ? 8 : 4 ); + #if LLVM_VERSION_MAJOR <= 12 + const std::string func_name = (expr_return_kind == 8) ? "llvm.powi.f64" : "llvm.powi.f32"; + #else + const std::string func_name = (expr_return_kind == 8) ? "llvm.powi.f64.i32" : "llvm.powi.f32.i32"; + #endif + llvm::Value *fleft = builder->CreateSIToFP(left_val, base_type); + llvm::Value* fright = llvm_utils->convert_kind(right_val, exponent_type); // `llvm.powi` only has `i32` exponent. llvm::Function *fn_pow = module->getFunction(func_name); if (!fn_pow) { llvm::FunctionType *function_type = llvm::FunctionType::get( - type, { type, type}, false); + base_type, {base_type, exponent_type}, false); fn_pow = llvm::Function::Create(function_type, llvm::Function::ExternalLinkage, func_name, module.get()); } tmp = builder->CreateCall(fn_pow, {fleft, fright}); - type = llvm_utils->getIntType(a_kind); - tmp = builder->CreateFPToSI(tmp, type); + tmp = builder->CreateFPToSI(tmp, return_type); break; }; case ASR::binopType::BitOr: { @@ -6648,10 +6769,10 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor lookup_enum_value_for_nonints = false; LCOMPILERS_ASSERT(ASRUtils::is_real(*x.m_type)) if (ASRUtils::is_simd_array(x.m_right) && is_a(*x.m_right)) { - right_val = CreateLoad(right_val); + right_val = llvm_utils->CreateLoad(right_val); } if (ASRUtils::is_simd_array(x.m_left) && is_a(*x.m_left)) { - left_val = CreateLoad(left_val); + left_val = llvm_utils->CreateLoad(left_val); } switch (x.m_op) { case ASR::binopType::Add: { @@ -6671,15 +6792,31 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor break; }; case ASR::binopType::Pow: { - llvm::Type *type; - int a_kind; - a_kind = down_cast(ASRUtils::extract_type(x.m_type))->m_kind; - type = llvm_utils->getFPType(a_kind); - std::string func_name = a_kind == 4 ? "llvm.pow.f32" : "llvm.pow.f64"; + const int return_kind = down_cast(ASRUtils::extract_type(x.m_type))->m_kind; + llvm::Type* const base_type = llvm_utils->getFPType(return_kind); + llvm::Type *exponent_type = nullptr; + std::string func_name; + // Choose the appropriate llvm_pow* intrinsic function + Set the exponent type. + if(ASRUtils::is_integer(*ASRUtils::expr_type(x.m_right))) { + #if LLVM_VERSION_MAJOR <= 12 + func_name = (return_kind == 4) ? "llvm.powi.f32" : "llvm.powi.f64"; + #else + func_name = (return_kind == 4) ? "llvm.powi.f32.i32" : "llvm.powi.f64.i32"; + #endif + right_val = llvm_utils->convert_kind(right_val, llvm::Type::getInt32Ty(context)); // `llvm.powi` only has `i32` exponent. + exponent_type = llvm::Type::getInt32Ty(context); + } else if (ASRUtils::is_real(*ASRUtils::expr_type(x.m_right))) { + func_name = (return_kind == 4) ? "llvm.pow.f32" : "llvm.pow.f64"; + right_val = llvm_utils->convert_kind(right_val, base_type); // `llvm.pow` exponent and base kinds have to match. + exponent_type = base_type; + } else { + LCOMPILERS_ASSERT_MSG(false, "Exponent in RealBinOp should either be [Integer or Real] only.") + } + llvm::Function *fn_pow = module->getFunction(func_name); if (!fn_pow) { llvm::FunctionType *function_type = llvm::FunctionType::get( - type, { type, type }, false); + base_type, { base_type, exponent_type }, false); fn_pow = llvm::Function::Create(function_type, llvm::Function::ExternalLinkage, func_name, module.get()); @@ -6706,13 +6843,15 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor LCOMPILERS_ASSERT(ASRUtils::is_complex(*x.m_type)); llvm::Type *type; int a_kind; - a_kind = down_cast(ASRUtils::type_get_past_pointer(x.m_type))->m_kind; + a_kind = ASR::down_cast( + ASRUtils::type_get_past_array( + ASRUtils::type_get_past_pointer(x.m_type)))->m_kind; type = llvm_utils->getComplexType(a_kind); if( left_val->getType()->isPointerTy() ) { - left_val = CreateLoad(left_val); + left_val = llvm_utils->CreateLoad(left_val); } if( right_val->getType()->isPointerTy() ) { - right_val = CreateLoad(right_val); + right_val = llvm_utils->CreateLoad(right_val); } std::string fn_name; switch (x.m_op) { @@ -6893,6 +7032,11 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor template void visit_ArrayConstructorUtil(const T& x) { + if (x.m_value) { + this->visit_expr_wrapper(x.m_value, true); + return; + } + llvm::Type* el_type = nullptr; ASR::ttype_t* x_m_type = ASRUtils::type_get_past_array(x.m_type); if (ASR::is_a(*x_m_type)) { @@ -6908,7 +7052,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } } else if (ASR::is_a(*x_m_type)) { el_type = llvm::Type::getInt1Ty(context); - } else if (ASR::is_a(*x_m_type)) { + } else if (ASR::is_a(*x_m_type)) { el_type = character_type; } else if (ASR::is_a(*x_m_type)) { int complex_kind = ASR::down_cast(x_m_type)->m_kind; @@ -6923,9 +7067,9 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor throw CodeGenError("ConstArray type not supported yet"); } // Create type, where `n` is the length of the `x` constant array - llvm::Type* type_fxn = FIXED_VECTOR_TYPE::get(el_type, x.n_args); + llvm::Type* type_fxn = FIXED_VECTOR_TYPE::get(el_type, ASRUtils::get_fixed_size_of_array(x.m_type)); // Create a pointer * to a stack allocated - llvm::AllocaInst *p_fxn = builder->CreateAlloca(type_fxn, nullptr); + llvm::AllocaInst *p_fxn = llvm_utils->CreateAlloca(*builder, type_fxn); // Assign the array elements to `p_fxn`. for (size_t i=0; i < x.n_args; i++) { llvm::Value *llvm_el = llvm_utils->create_gep(p_fxn, i); @@ -6940,12 +7084,60 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor tmp = llvm_utils->create_gep(p_fxn, 0); } + void visit_ArrayConstantUtil(const ASR::ArrayConstant_t &x) { + llvm::Type* el_type = nullptr; + ASR::ttype_t* x_m_type = ASRUtils::type_get_past_array(x.m_type); + if (ASR::is_a(*x_m_type)) { + el_type = llvm_utils->getIntType(ASR::down_cast(x_m_type)->m_kind); + } else if (ASR::is_a(*x_m_type)) { + switch (ASR::down_cast(x_m_type)->m_kind) { + case (4) : + el_type = llvm::Type::getFloatTy(context); break; + case (8) : + el_type = llvm::Type::getDoubleTy(context); break; + default : + throw CodeGenError("ConstArray real kind not supported yet"); + } + } else if (ASR::is_a(*x_m_type)) { + el_type = llvm::Type::getInt1Ty(context); + } else if (ASR::is_a(*x_m_type)) { + el_type = character_type; + } else if (ASR::is_a(*x_m_type)) { + int complex_kind = ASR::down_cast(x_m_type)->m_kind; + if( complex_kind == 4 ) { + el_type = llvm_utils->complex_type_4; + } else if( complex_kind == 8 ) { + el_type = llvm_utils->complex_type_8; + } else { + LCOMPILERS_ASSERT(false); + } + } else { + throw CodeGenError("ConstArray type not supported yet"); + } + // Create type, where `n` is the length of the `x` constant array + llvm::Type* type_fxn = FIXED_VECTOR_TYPE::get(el_type, ASRUtils::get_fixed_size_of_array(x.m_type)); + // Create a pointer * to a stack allocated + llvm::AllocaInst *p_fxn = llvm_utils->CreateAlloca(*builder, type_fxn); + // Assign the array elements to `p_fxn`. + for (size_t i=0; i < (size_t) ASRUtils::get_fixed_size_of_array(x.m_type); i++) { + llvm::Value *llvm_el = llvm_utils->create_gep(p_fxn, i); + ASR::expr_t *el = ASRUtils::fetch_ArrayConstant_value(al, x, i); + int64_t ptr_loads_copy = ptr_loads; + ptr_loads = 2; + this->visit_expr_wrapper(el, true); + ptr_loads = ptr_loads_copy; + builder->CreateStore(tmp, llvm_el); + } + // Return the vector as float* type: + tmp = llvm_utils->create_gep(p_fxn, 0); + } + void visit_ArrayConstructor(const ASR::ArrayConstructor_t &x) { visit_ArrayConstructorUtil(x); } void visit_ArrayConstant(const ASR::ArrayConstant_t &x) { - visit_ArrayConstructorUtil(x); + visit_ArrayConstantUtil(x); } void visit_Assert(const ASR::Assert_t &x) { @@ -7078,19 +7270,13 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor llvm::Value* x_v = llvm_symtab[x_h]; int64_t ptr_loads_copy = ptr_loads; tmp = x_v; - while( ptr_loads_copy-- ) { - tmp = CreateLoad(tmp); + while( ptr_loads_copy-- && !ASRUtils::is_descriptorString(x->m_type)) { + tmp = llvm_utils->CreateLoad(tmp); } } inline void fetch_val(ASR::Variable_t* x) { uint32_t x_h = get_hash((ASR::asr_t*)x); - if (compiler_options.interactive && - std::strcmp(x->m_name, "_") == 0 && - x->m_abi == ASR::abiType::Interactive && - llvm_symtab.find(x_h) == llvm_symtab.end()) { - x_h = global_underscore_hash; - } llvm::Value* x_v; LCOMPILERS_ASSERT(llvm_symtab.find(x_h) != llvm_symtab.end()); x_v = llvm_symtab[x_h]; @@ -7105,7 +7291,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor tmp = x_v; // Load only once since its a value if( ptr_loads > 0 ) { - tmp = CreateLoad(tmp); + tmp = llvm_utils->CreateLoad2(x->m_type, tmp); } } } @@ -7127,14 +7313,14 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor case ASR::ttypeType::Real: case ASR::ttypeType::Complex: case ASR::ttypeType::StructType: - case ASR::ttypeType::Character: + case ASR::ttypeType::String: case ASR::ttypeType::Logical: - case ASR::ttypeType::Class: { + case ASR::ttypeType::ClassType: { if( t2->type == ASR::ttypeType::StructType ) { ASR::StructType_t* d = ASR::down_cast(t2); current_der_type_name = ASRUtils::symbol_name(d->m_derived_type); - } else if( t2->type == ASR::ttypeType::Class ) { - ASR::Class_t* d = ASR::down_cast(t2); + } else if( t2->type == ASR::ttypeType::ClassType ) { + ASR::ClassType_t* d = ASR::down_cast(t2); current_der_type_name = ASRUtils::symbol_name(d->m_class_type); } fetch_ptr(x); @@ -7156,9 +7342,9 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } break; } - case ASR::ttypeType::Union: { - ASR::Union_t* der = ASR::down_cast(t2_); - ASR::UnionType_t* der_type = ASR::down_cast( + case ASR::ttypeType::UnionType: { + ASR::UnionType_t* der = ASR::down_cast(t2_); + ASR::Union_t* der_type = ASR::down_cast( ASRUtils::symbol_get_past_external(der->m_union_type)); current_der_type_name = std::string(der_type->m_name); uint32_t h = get_hash((ASR::asr_t*)x); @@ -7167,11 +7353,11 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } break; } - case ASR::ttypeType::Class: { - ASR::Class_t* der = ASR::down_cast(t2_); + case ASR::ttypeType::ClassType: { + ASR::ClassType_t* der = ASR::down_cast(t2_); ASR::symbol_t* der_sym = ASRUtils::symbol_get_past_external(der->m_class_type); - if( ASR::is_a(*der_sym) ) { - ASR::ClassType_t* der_type = ASR::down_cast(der_sym); + if( ASR::is_a(*der_sym) ) { + ASR::Class_t* der_type = ASR::down_cast(der_sym); current_der_type_name = std::string(der_type->m_name); } else if( ASR::is_a(*der_sym) ) { ASR::Struct_t* der_type = ASR::down_cast(der_sym); @@ -7183,6 +7369,40 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } break; } + case ASR::ttypeType::FunctionType: { + // break; + uint32_t h = get_hash((ASR::asr_t*)x); + uint32_t x_h = get_hash((ASR::asr_t*)x); + if ( llvm_symtab_fn_arg.find(h) != llvm_symtab_fn_arg.end() ) { + tmp = llvm_symtab_fn_arg[h]; + } else if ( llvm_symtab.find(x_h) != llvm_symtab.end() ) { + tmp = llvm_symtab[x_h]; + } else if (llvm_symtab_fn.find(h) != llvm_symtab_fn.end()) { + tmp = llvm_symtab_fn[h]; + tmp = llvm_utils->CreateLoad2(tmp->getType()->getPointerTo(), tmp); +#if LLVM_VERSION_MAJOR > 16 + ptr_type[tmp] = tmp->getType(); +#endif + } else { + throw CodeGenError("Function type not supported yet"); + } + if (x->m_value_attr) { + // Already a value, such as value argument to bind(c) + break; + } + if( ASRUtils::is_array(x->m_type) ) { + break; + } else { + // Load only once since its a value + if( ptr_loads > 0 ) { + tmp = llvm_utils->CreateLoad2(x->m_type, tmp); +#if LLVM_VERSION_MAJOR > 16 + ptr_type[tmp] = tmp->getType(); +#endif + } + } + break; + } default: { fetch_val(x); break; @@ -7231,18 +7451,21 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor this->visit_expr_wrapper(t.m_arg, false); ptr_loads = ptr_loads_copy; llvm::Value* des_complex_arr = tmp; - tmp = CreateLoad(arr_descr->get_pointer_to_data(des_complex_arr)); + llvm::Type* des_complex_type = llvm_utils->get_type_from_ttype_t_util( + ASRUtils::extract_type(ASRUtils::expr_type(t.m_arg)), module.get()); + tmp = llvm_utils->CreateLoad2(des_complex_type->getPointerTo(), arr_descr->get_pointer_to_data(des_complex_arr)); int kind = ASRUtils::extract_kind_from_ttype_t(t.m_type); llvm::Type* pointer_cast_type = nullptr; if (kind == 4) { - pointer_cast_type = llvm::Type::getFloatPtrTy(context); + pointer_cast_type = llvm::Type::getFloatTy(context)->getPointerTo(); } else { - pointer_cast_type = llvm::Type::getDoublePtrTy(context); + pointer_cast_type = llvm::Type::getDoubleTy(context)->getPointerTo(); } tmp = builder->CreateBitCast(tmp, pointer_cast_type); PointerToData_to_Descriptor(t.m_type, t.m_type); llvm::Value* des_real_arr = tmp; - llvm::Value* arr_data = CreateLoad(arr_descr->get_pointer_to_data(des_complex_arr)); + llvm::Value* arr_data = llvm_utils->CreateLoad2( + des_complex_type->getPointerTo(), arr_descr->get_pointer_to_data(des_complex_arr)); tmp = builder->CreateBitCast(arr_data, pointer_cast_type); builder->CreateStore(tmp, arr_descr->get_pointer_to_data(des_real_arr)); if (std::is_same::value) { @@ -7302,7 +7525,6 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } void visit_ComplexIm(const ASR::ComplexIm_t &x) { - get_builder0() if (x.m_value) { this->visit_expr_wrapper(x.m_value, true); return; @@ -7321,14 +7543,13 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor runtime_func_name = "_lfortran_complex_aimag_32"; ret_type = llvm::Type::getFloatTy(context); complex_type = complex_type_4; - arg = builder0.CreateAlloca(complex_type_4, + arg = llvm_utils->CreateAlloca(*builder, complex_type_4, nullptr); } else { - runtime_func_name = "_lfortran_complex_aimag_64"; + runtime_func_name = "_lfortran_complex_aimag_64"; ret_type = llvm::Type::getDoubleTy(context); complex_type = complex_type_8; - arg = builder0.CreateAlloca(complex_type_8, - nullptr); + arg = llvm_utils->CreateAlloca(*builder, complex_type_8); } fn = module->getFunction(runtime_func_name); if (!fn) { @@ -7336,16 +7557,16 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor llvm::Type::getVoidTy(context), { complex_type->getPointerTo(), ret_type->getPointerTo(), - }, true); + }, false); fn = llvm::Function::Create(function_type, llvm::Function::ExternalLinkage, runtime_func_name, *module); } this->visit_expr_wrapper(x.m_arg, true); builder->CreateStore(tmp, arg); - llvm::AllocaInst *result = builder0.CreateAlloca(ret_type, nullptr); + llvm::AllocaInst *result = llvm_utils->CreateAlloca(*builder, ret_type); std::vector args = {arg, result}; builder->CreateCall(fn, args); - tmp = CreateLoad(result); + tmp = llvm_utils->CreateLoad2(ret_type, result); } void visit_BitCast(const ASR::BitCast_t& x) { @@ -7357,14 +7578,14 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor this->visit_expr_wrapper(x.m_source, true); llvm::Value* source = tmp; llvm::Type* source_type = llvm_utils->get_type_from_ttype_t_util(ASRUtils::expr_type(x.m_source), module.get()); - llvm::Value* source_ptr = CreateAlloca(source_type, nullptr, "bitcast_source"); + llvm::Value* source_ptr = llvm_utils->CreateAlloca(source_type, nullptr, "bitcast_source"); builder->CreateStore(source, source_ptr); - llvm::Type* target_llvm_type = llvm_utils->get_type_from_ttype_t_util(x.m_type, module.get())->getPointerTo(); - tmp = LLVM::CreateLoad(*builder, builder->CreateBitCast(source_ptr, target_llvm_type)); + llvm::Type* target_base_type = llvm_utils->get_type_from_ttype_t_util(x.m_type, module.get()); + llvm::Type* target_llvm_type = target_base_type->getPointerTo(); + tmp = llvm_utils->CreateLoad2(target_base_type, builder->CreateBitCast(source_ptr, target_llvm_type)); } void visit_Cast(const ASR::Cast_t &x) { - get_builder0() if (x.m_value) { this->visit_expr_wrapper(x.m_value, true); return; @@ -7480,14 +7701,14 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor tmp = builder->CreateFCmpUNE(tmp, zero); break; } - case (ASR::cast_kindType::CharacterToLogical) : { - llvm::AllocaInst *parg = builder0.CreateAlloca(character_type, nullptr); + case (ASR::cast_kindType::StringToLogical) : { + llvm::AllocaInst *parg = llvm_utils->CreateAlloca(*builder, character_type); builder->CreateStore(tmp, parg); tmp = builder->CreateICmpNE(lfortran_str_len(parg), builder->getInt32(0)); break; } - case (ASR::cast_kindType::CharacterToInteger) : { - llvm::AllocaInst *parg = builder0.CreateAlloca(character_type, nullptr); + case (ASR::cast_kindType::StringToInteger) : { + llvm::AllocaInst *parg = llvm_utils->CreateAlloca(*builder, character_type); builder->CreateStore(tmp, parg); tmp = lfortran_str_to_int(parg); break; @@ -7689,7 +7910,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } break; } - case (ASR::cast_kindType::RealToCharacter) : { + case (ASR::cast_kindType::RealToString) : { llvm::Value *arg = tmp; ASR::ttype_t* arg_type = extract_ttype_t_from_expr(x.m_arg); LCOMPILERS_ASSERT(arg_type != nullptr) @@ -7697,7 +7918,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor tmp = lfortran_type_to_str(arg, llvm_utils->getFPType(arg_kind), "float", arg_kind); break; } - case (ASR::cast_kindType::IntegerToCharacter) : { + case (ASR::cast_kindType::IntegerToString) : { llvm::Value *arg = tmp; ASR::ttype_t* arg_type = extract_ttype_t_from_expr(x.m_arg); LCOMPILERS_ASSERT(arg_type != nullptr) @@ -7705,7 +7926,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor tmp = lfortran_type_to_str(arg, llvm_utils->getIntType(arg_kind), "int", arg_kind); break; } - case (ASR::cast_kindType::LogicalToCharacter) : { + case (ASR::cast_kindType::LogicalToString) : { llvm::Value *cmp = builder->CreateICmpEQ(tmp, builder->getInt1(0)); llvm::Value *zero_str = builder->CreateGlobalStringPtr("False"); llvm::Value *one_str = builder->CreateGlobalStringPtr("True"); @@ -7715,19 +7936,14 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor case (ASR::cast_kindType::ListToArray) : { if( !ASR::is_a(*ASRUtils::expr_type(x.m_arg)) ) { throw CodeGenError("The argument of ListToArray cast should " - "be a list/std::vector, found, " + ASRUtils::type_to_str( + "be a list/std::vector, found, " + ASRUtils::type_to_str_fortran( ASRUtils::expr_type(x.m_arg))); } int64_t ptr_loads_copy = ptr_loads; ptr_loads = 0; this->visit_expr(*x.m_arg); ptr_loads = ptr_loads_copy; - tmp = LLVM::CreateLoad(*builder, list_api->get_pointer_to_list_data(tmp)); - break; - } - case (ASR::cast_kindType::DerivedToBase) : { - this->visit_expr(*x.m_arg); - tmp = llvm_utils->create_gep(tmp, 0); + tmp = llvm_utils->CreateLoad(list_api->get_pointer_to_list_data(tmp)); break; } default : throw CodeGenError("Cast kind not implemented"); @@ -7765,7 +7981,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } break; } - case (ASR::ttypeType::Character): { + case (ASR::ttypeType::String): { std::string runtime_func_name = "_lfortran_read_char"; fn = module->getFunction(runtime_func_name); if (!fn) { @@ -7829,8 +8045,8 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor throw CodeGenError("Real arrays of kind 4 or 8 only supported for now. Found kind: " + std::to_string(a_kind)); } - } else if (ASR::is_a(*type)) { - if (ASR::down_cast(type)->m_len != 1) { + } else if (ASR::is_a(*type)) { + if (ASR::down_cast(type)->m_len != 1) { throw CodeGenError("Only `character(len=1)` array " "is supported for now"); } @@ -7853,7 +8069,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor break; } default: { - std::string s_type = ASRUtils::type_to_str(type); + std::string s_type = ASRUtils::type_to_str_fortran(type); throw CodeGenError("Read function not implemented for: " + s_type); } } @@ -7861,7 +8077,6 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } void visit_FileRead(const ASR::FileRead_t &x) { - get_builder0() if( x.m_overloaded ) { this->visit_stmt(*x.m_overloaded); return ; @@ -7877,6 +8092,10 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor is_string = ASRUtils::is_character(*expr_type(x.m_unit)); this->visit_expr_wrapper(x.m_unit, true); unit_val = tmp; + if(ASRUtils::is_integer(*ASRUtils::expr_type(x.m_unit))){ + // Convert the unit to 32 bit integer (We only support unit number up to 1000). + unit_val = llvm_utils->convert_kind(tmp, llvm::Type::getInt32Ty(context)); + } } if (x.m_iostat) { @@ -7886,8 +8105,8 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor ptr_loads = ptr_copy; iostat = tmp; } else { - iostat = builder0.CreateAlloca( - llvm::Type::getInt32Ty(context), nullptr); + iostat = llvm_utils->CreateAlloca(*builder, + llvm::Type::getInt32Ty(context)); } if (x.m_size) { @@ -7897,8 +8116,8 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor ptr_loads = ptr_copy; read_size = tmp; } else { - read_size = builder0.CreateAlloca( - llvm::Type::getInt32Ty(context), nullptr); + read_size = llvm_utils->CreateAlloca(*builder, + llvm::Type::getInt32Ty(context)); } if (x.m_fmt) { @@ -7941,32 +8160,56 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor llvm::Function *fn; if (is_string) { // TODO: Support multiple arguments and fmt - std::string runtime_func_name = "_lfortran_string_read"; - llvm::Function *fn = module->getFunction(runtime_func_name); + std::string runtime_func_name = "_lfortran_string_read_" + + ASRUtils::type_to_str_python(ASRUtils::extract_type(type)); + if (ASRUtils::is_array(type)) { + runtime_func_name += "_array"; + } + llvm::Function* fn = module->getFunction(runtime_func_name); if (!fn) { llvm::FunctionType *function_type = llvm::FunctionType::get( llvm::Type::getVoidTy(context), { character_type, character_type, - llvm::Type::getInt32Ty(context)->getPointerTo() + llvm_utils->get_type_from_ttype_t_util(type, module.get())->getPointerTo() }, false); fn = llvm::Function::Create(function_type, llvm::Function::ExternalLinkage, runtime_func_name, *module); } - llvm::Value *fmt = builder->CreateGlobalStringPtr("%d"); - builder->CreateCall(fn, {unit_val, fmt, tmp}); + llvm::Value *fmt = nullptr; + if (ASR::is_a(*ASRUtils::type_get_past_array( + ASRUtils::type_get_past_allocatable_pointer(type)))) { + ASR::Integer_t* int_type = ASR::down_cast(ASRUtils::type_get_past_array( + ASRUtils::type_get_past_allocatable_pointer(type))); + fmt = int_type->m_kind == 4 ? builder->CreateGlobalStringPtr("%d") + : builder->CreateGlobalStringPtr("%ld"); + } else if (ASR::is_a(*ASRUtils::type_get_past_array( + ASRUtils::type_get_past_allocatable_pointer(type)))) { + ASR::Real_t* real_type = ASR::down_cast(ASRUtils::type_get_past_array( + ASRUtils::type_get_past_allocatable_pointer(type))); + fmt = real_type->m_kind == 4 ? builder->CreateGlobalStringPtr("%f") + : builder->CreateGlobalStringPtr("%lf"); + } else if (ASR::is_a(*ASRUtils::type_get_past_array( + ASRUtils::type_get_past_allocatable_pointer(type)))) { + fmt = builder->CreateGlobalStringPtr("%s"); + } else if (ASR::is_a(*ASRUtils::type_get_past_array( + ASRUtils::type_get_past_allocatable_pointer(type)))) { + fmt = builder->CreateGlobalStringPtr("%d"); + } + builder->CreateCall(fn, { unit_val, fmt, tmp }); return; } else { fn = get_read_function(type); } if (ASRUtils::is_array(type)) { + llvm::Type *el_type = llvm_utils->get_type_from_ttype_t_util(ASRUtils::extract_type(type), module.get()); if (ASR::is_a(*type) || ASR::is_a(*type)) { - tmp = CreateLoad(tmp); + tmp = llvm_utils->CreateLoad(tmp); } tmp = arr_descr->get_pointer_to_data(tmp); if (ASR::is_a(*type) || ASR::is_a(*type)) { - tmp = CreateLoad(tmp); + tmp = llvm_utils->CreateLoad2(el_type->getPointerTo(), tmp); } llvm::Value *arr = tmp; ASR::ttype_t *type32 = ASRUtils::TYPE(ASR::make_Integer_t(al, x.base.base.loc, 4)); @@ -8006,7 +8249,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor llvm::Value *unit_val = nullptr, *f_name = nullptr; llvm::Value *status = nullptr, *form = nullptr; this->visit_expr_wrapper(x.m_newunit, true); - unit_val = tmp; + unit_val = llvm_utils->convert_kind(tmp, llvm::Type::getInt32Ty(context)); int ptr_copy = ptr_loads; if (x.m_filename) { ptr_loads = 1; @@ -8045,8 +8288,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } void visit_FileInquire(const ASR::FileInquire_t &x) { - get_builder0() - llvm::Value *exist_val = nullptr, *f_name = nullptr, *unit = nullptr, *opened_val = nullptr; + llvm::Value *exist_val = nullptr, *f_name = nullptr, *unit = nullptr, *opened_val = nullptr, *size_val = nullptr; if (x.m_file) { this->visit_expr_wrapper(x.m_file, true); @@ -8061,8 +8303,8 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor exist_val = tmp; ptr_loads = ptr_loads_copy; } else { - exist_val = builder0.CreateAlloca( - llvm::Type::getInt1Ty(context), nullptr); + exist_val = llvm_utils->CreateAlloca(*builder, + llvm::Type::getInt1Ty(context)); } if (x.m_unit) { @@ -8079,8 +8321,19 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor opened_val = tmp; ptr_loads = ptr_loads_copy; } else { - opened_val = builder0.CreateAlloca( - llvm::Type::getInt1Ty(context), nullptr); + opened_val = llvm_utils->CreateAlloca(*builder, + llvm::Type::getInt1Ty(context)); + } + + if (x.m_size) { + int ptr_loads_copy = ptr_loads; + ptr_loads = 0; + this->visit_expr_wrapper(x.m_size, true); + size_val = tmp; + ptr_loads = ptr_loads_copy; + } else { + size_val = llvm_utils->CreateAlloca(*builder, + llvm::Type::getInt32Ty(context)); } std::string runtime_func_name = "_lfortran_inquire"; @@ -8092,11 +8345,12 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor llvm::Type::getInt1Ty(context)->getPointerTo(), llvm::Type::getInt32Ty(context), llvm::Type::getInt1Ty(context)->getPointerTo(), + llvm::Type::getInt32Ty(context)->getPointerTo(), }, false); fn = llvm::Function::Create(function_type, llvm::Function::ExternalLinkage, runtime_func_name, *module); } - tmp = builder->CreateCall(fn, {f_name, exist_val, unit, opened_val}); + tmp = builder->CreateCall(fn, {f_name, exist_val, unit, opened_val, size_val}); } void visit_Flush(const ASR::Flush_t& x) { @@ -8147,35 +8401,53 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } void visit_FileClose(const ASR::FileClose_t &x) { - llvm::Value *unit_val = nullptr; + llvm::Value *unit_val, *status = nullptr; this->visit_expr_wrapper(x.m_unit, true); - unit_val = tmp; + unit_val = llvm_utils->convert_kind(tmp, llvm::Type::getInt32Ty(context)); + if (x.m_status) { + this->visit_expr_wrapper(x.m_status, true); + status = tmp; + } else { + status = llvm::Constant::getNullValue(character_type); + } std::string runtime_func_name = "_lfortran_close"; llvm::Function *fn = module->getFunction(runtime_func_name); if (!fn) { llvm::FunctionType *function_type = llvm::FunctionType::get( llvm::Type::getVoidTy(context), { llvm::Type::getInt32Ty(context), + character_type, }, false); fn = llvm::Function::Create(function_type, llvm::Function::ExternalLinkage, runtime_func_name, *module); } - tmp = builder->CreateCall(fn, {unit_val}); + tmp = builder->CreateCall(fn, {unit_val, status}); } void visit_Print(const ASR::Print_t &x) { - handle_print(x); + handle_print(x.m_text, nullptr); } void visit_FileWrite(const ASR::FileWrite_t &x) { - get_builder0() if( x.m_overloaded ) { this->visit_stmt(*x.m_overloaded); return ; } if (x.m_unit == nullptr) { - handle_print(x); + llvm::Value* end = nullptr; + if (x.m_end) { + this->visit_expr_wrapper(x.m_end, true); + end = tmp; + } + if(x.n_values == 0){ // TODO : We should remove any function that creates a `FileWrite` with no args + llvm::Value *fmt_ptr = builder->CreateGlobalStringPtr("%s"); + printf(context, *module, *builder, {fmt_ptr, end}); + } else if (x.n_values == 1){ + handle_print(x.m_values[0], end); + } else { + throw CodeGenError("File write should have single argument of type character)", x.base.base.loc); + } return; } std::vector args; @@ -8193,6 +8465,8 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor ptr_loads = 0; runtime_func_name = "_lfortran_string_write"; args_type.push_back(character_type->getPointerTo()); + args_type.push_back(llvm::Type::getInt64Ty(context)->getPointerTo()); + args_type.push_back(llvm::Type::getInt64Ty(context)->getPointerTo()); } else if ( ASRUtils::is_integer(*expr_type(x.m_unit)) ) { ptr_loads = 1; runtime_func_name = "_lfortran_file_write"; @@ -8202,7 +8476,25 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } this->visit_expr_wrapper(x.m_unit); ptr_loads = ptr_loads_copy; - unit = tmp; + + // Set string_size, string_capacity to be used if lfortran_string_write will be used. + llvm::Value* string_size, *string_capacity; + if(!is_string){ + unit = tmp; + } else { + if (ASRUtils::is_descriptorString(expr_type(x.m_unit))){ + unit = llvm_utils->create_gep2(string_descriptor, tmp, 0); //fetch char* + string_size = llvm_utils->create_gep2(string_descriptor, tmp, 1); + string_capacity = llvm_utils->create_gep2(string_descriptor, tmp, 2); + + } else { + unit = tmp; + llvm::Value* negative_one_constant = builder->CreateAlloca(llvm::Type::getInt64Ty(context), nullptr, "negative_one_constant"); + builder->CreateStore(llvm::ConstantInt::get(context, llvm::APInt(64, -1, true)), negative_one_constant); + string_size = negative_one_constant; + string_capacity = negative_one_constant; + } + } if (x.m_iostat) { int ptr_copy = ptr_loads; @@ -8211,8 +8503,11 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor ptr_loads = ptr_copy; iostat = tmp; } else { - iostat = builder0.CreateAlloca( - llvm::Type::getInt32Ty(context), nullptr); + iostat = llvm_utils->CreateAlloca(*builder, + llvm::Type::getInt32Ty(context)->getPointerTo()); + builder->CreateStore(llvm::ConstantInt::getNullValue( + llvm::Type::getInt32Ty(context)->getPointerTo()), iostat); + iostat = llvm_utils->CreateLoad(iostat); } if (x.m_separator) { @@ -8248,13 +8543,17 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor std::vector printf_args; printf_args.push_back(unit); + if(is_string){ + printf_args.push_back(string_size); + printf_args.push_back(string_capacity); + } printf_args.push_back(iostat); printf_args.push_back(fmt_ptr); printf_args.insert(printf_args.end(), args.begin(), args.end()); llvm::Function *fn = module->getFunction(runtime_func_name); if (!fn) { - args_type.push_back(llvm::Type::getInt32PtrTy(context)); - args_type.push_back(llvm::Type::getInt8PtrTy(context)); + args_type.push_back(llvm::Type::getInt32Ty(context)->getPointerTo()); + args_type.push_back(llvm::Type::getInt8Ty(context)->getPointerTo()); llvm::FunctionType *function_type = llvm::FunctionType::get( llvm::Type::getVoidTy(context), args_type, true); fn = llvm::Function::Create(function_type, @@ -8263,9 +8562,15 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor tmp = builder->CreateCall(fn, printf_args); } - // It appends the format specifier and arg based on the type of expression + // Enumeration for the types to be used by the runtime stringformat intrinsic. + // (1)i64, (2)i32, (3)i16, (4)i8, (5)f64, (6)f32, (7)character, (8)logical, + // (9)array[i64], (10)array[i32], (11)array[i16], (12)array[i8], + // (13)array[f64], (14)array[f32] + // (15)array[character], (16)array[logical], (17)array[cptr], (18)array[enumType], + // (19)cptr + pointer , (20)enumType + void compute_fmt_specifier_and_arg(std::vector &fmt, - std::vector &args, ASR::expr_t *v, const Location &loc) { + std::vector &args, ASR::expr_t *v, const Location &loc, bool add_type_as_int = false) { int64_t ptr_loads_copy = ptr_loads; int reduce_loads = 0; ptr_loads = 2; @@ -8284,36 +8589,48 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor ptr_loads = ptr_loads_copy; ASR::ttype_t *t = ASRUtils::expr_type(v); - if (t->type == ASR::ttypeType::CPtr || + llvm::Value* type_as_int = nullptr; + if ((t->type == ASR::ttypeType::CPtr && !ASRUtils::is_array(t)) || (t->type == ASR::ttypeType::Pointer && - (ASR::is_a(*v) || ASR::is_a(*v))) + (ASR::is_a(*v) || ASR::is_a(*v)) + && !ASRUtils::is_array(t)) ) { fmt.push_back("%lld"); llvm::Value* d = builder->CreatePtrToInt(tmp, llvm_utils->getIntType(8, false)); + if(add_type_as_int){ + type_as_int = llvm::ConstantInt::get(context, llvm::APInt(32, 19)); + args.push_back(type_as_int); + } args.push_back(d); return ; } load_non_array_non_character_pointers(v, ASRUtils::expr_type(v), tmp); - t = ASRUtils::type_get_past_allocatable(ASRUtils::type_get_past_pointer(t)); + bool is_array = ASRUtils::is_array(t) && add_type_as_int; // add (type_as_int + array_size) + t = ASRUtils::extract_type(t); int a_kind = ASRUtils::extract_kind_from_ttype_t(t); + int32_t number_of_type = -1; if (ASRUtils::is_integer(*t)) { switch( a_kind ) { case 1 : { fmt.push_back("%hhi"); + number_of_type = is_array? 12 : 4; break; } case 2 : { fmt.push_back("%hi"); + number_of_type = is_array? 11 : 3; break; } case 4 : { fmt.push_back("%d"); + number_of_type = is_array? 10 : 2; break; } case 8 : { fmt.push_back("%lld"); + number_of_type = is_array? 9 : 1; break; } default: { @@ -8322,7 +8639,19 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor loc); } } - args.push_back(tmp); + llvm::Value* d = tmp; + if(!is_array && add_type_as_int){ //cast all integers to int64. + d =builder->CreateSExt(tmp, llvm_utils->getIntType(8, false)); + } + if (add_type_as_int) { + if(!is_array){ + type_as_int = llvm::ConstantInt::get(context, llvm::APInt(32, number_of_type)); + args.push_back(type_as_int); + args.push_back(d); + } + } else { + args.push_back(d); + } } else if (ASRUtils::is_unsigned_integer(*t)) { switch( a_kind ) { case 1 : { @@ -8349,21 +8678,31 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } args.push_back(tmp); } else if (ASRUtils::is_real(*t)) { - llvm::Value *d; + llvm::Value *d = tmp; switch( a_kind ) { case 4 : { // Cast float to double as a workaround for the fact that // vprintf() seems to cast to double even for %f, which // causes it to print 0.000000. - fmt.push_back("%13.8e"); - d = builder->CreateFPExt(tmp, - llvm::Type::getDoubleTy(context)); + if(is_array){ + number_of_type = 14; //arr[f32] + } else { + number_of_type = 6; //f32 + fmt.push_back("%13.8e"); + d = builder->CreateFPExt(tmp, + llvm::Type::getDoubleTy(context)); + } break; } case 8 : { - fmt.push_back("%23.17e"); - d = builder->CreateFPExt(tmp, - llvm::Type::getDoubleTy(context)); + if(is_array){ + number_of_type = 13; //arr[f64] + } else { + number_of_type = 5; //f64 + fmt.push_back("%23.17e"); + d = builder->CreateFPExt(tmp, + llvm::Type::getDoubleTy(context)); + } break; } default: { @@ -8372,17 +8711,46 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor loc); } } - args.push_back(d); - } else if (t->type == ASR::ttypeType::Character) { + if(add_type_as_int){ + if(!is_array){ + type_as_int = llvm::ConstantInt::get(context, llvm::APInt(32, number_of_type)); + args.push_back(type_as_int); + args.push_back(d); + } + } else { + args.push_back(d); + } + } else if (t->type == ASR::ttypeType::String) { fmt.push_back("%s"); - args.push_back(tmp); + number_of_type = 15; + if(add_type_as_int){ + if(!is_array){ + type_as_int = llvm::ConstantInt::get(context, llvm::APInt(32, 7)); + args.push_back(type_as_int); + args.push_back(tmp); + } + } else { + args.push_back(tmp); + } } else if (ASRUtils::is_logical(*t)) { - llvm::Value *cmp = builder->CreateICmpEQ(tmp, builder->getInt1(0)); - llvm::Value *zero_str = builder->CreateGlobalStringPtr("False"); - llvm::Value *one_str = builder->CreateGlobalStringPtr("True"); - llvm::Value *str = builder->CreateSelect(cmp, zero_str, one_str); + llvm::Value *str; + number_of_type = 16; //arr[logical] + if(!is_array){ + llvm::Value *cmp = builder->CreateICmpEQ(tmp, builder->getInt1(0)); + llvm::Value *zero_str = builder->CreateGlobalStringPtr("False"); + llvm::Value *one_str = builder->CreateGlobalStringPtr("True"); + str = builder->CreateSelect(cmp, zero_str, one_str); + } fmt.push_back("%s"); - args.push_back(str); + if(add_type_as_int){ + if(!is_array){ + type_as_int = llvm::ConstantInt::get(context, llvm::APInt(32, 8)); + args.push_back(type_as_int); + args.push_back(str); + } + } else { + args.push_back(str); + } } else if (ASRUtils::is_complex(*t)) { llvm::Type *type, *complex_type; switch( a_kind ) { @@ -8393,12 +8761,14 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor fmt.push_back("(%f,%f)"); type = llvm::Type::getDoubleTy(context); complex_type = complex_type_4; + number_of_type = is_array? 14 : 6; break; } case 8 : { fmt.push_back("(%lf,%lf)"); type = llvm::Type::getDoubleTy(context); complex_type = complex_type_8; + number_of_type =is_array? 13 : 5; break; } default: { @@ -8407,61 +8777,100 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor loc); } } - llvm::Value *d; - d = builder->CreateFPExt(complex_re(tmp, complex_type), type); - args.push_back(d); - d = builder->CreateFPExt(complex_im(tmp, complex_type), type); - args.push_back(d); + llvm::Value *d = tmp; + if(add_type_as_int){ + if(!is_array){ + type_as_int = llvm::ConstantInt::get(context, llvm::APInt(32, number_of_type)); + d = builder->CreateFPExt(complex_re(tmp, complex_type), type); + args.push_back(type_as_int); + args.push_back(d); + d = builder->CreateFPExt(complex_im(tmp, complex_type), type); + args.push_back(type_as_int); + args.push_back(d); + } + } else { + d = builder->CreateFPExt(complex_re(tmp, complex_type), type); + args.push_back(d); + d = builder->CreateFPExt(complex_im(tmp, complex_type), type); + args.push_back(d); + } } else if (t->type == ASR::ttypeType::CPtr) { + number_of_type = 19; //arr[cptr] fmt.push_back("%lld"); llvm::Value* d = builder->CreatePtrToInt(tmp, llvm_utils->getIntType(8, false)); - args.push_back(d); - } else if (t->type == ASR::ttypeType::Enum) { + if(add_type_as_int){ + if(!is_array){ + type_as_int = llvm::ConstantInt::get(context, llvm::APInt(32, 17)); + args.push_back(type_as_int); + args.push_back(d); + } + } else { + args.push_back(d); + } + } else if (t->type == ASR::ttypeType::EnumType) { // TODO: Use recursion to generalise for any underlying type in enum + number_of_type = 20; //arr[EnumType] fmt.push_back("%d"); - args.push_back(tmp); + if(add_type_as_int){ + if(!is_array){ + type_as_int = llvm::ConstantInt::get(context, llvm::APInt(32, 18)); + args.push_back(type_as_int); + args.push_back(tmp); + } + } else { + args.push_back(tmp); + } } else { throw CodeGenError("Printing support is not available for `" + - ASRUtils::type_to_str(t) + "` type.", loc); + ASRUtils::type_to_str_fortran(t) + "` type.", loc); + } + + if(is_array){ + ASR::Array_t* arr = ASR::down_cast(ASRUtils::type_get_past_allocatable( + ASRUtils::type_get_past_pointer(ASRUtils::expr_type(v)))); + + //Create ArrayPhysicalCast to get the array pointer. + ASR::ttype_t* array_type = ASRUtils::TYPE(ASR::make_Array_t(al, v->base.loc,arr->m_type, arr->m_dims, + arr->n_dims,ASR::array_physical_typeType::FixedSizeArray)); + ASR::expr_t* array_casted_to_pointer; + if(arr->m_physical_type == ASR::array_physical_typeType::PointerToDataArray){ + array_casted_to_pointer = v; //Don't cast, It's already casted. + } else { + array_casted_to_pointer = ASRUtils::EXPR(ASR::make_ArrayPhysicalCast_t(al, v->base.loc, v,arr->m_physical_type, + ASR::array_physical_typeType::PointerToDataArray, array_type, nullptr)); + } + + // Create size argument. + int array_size; + ASR::expr_t* compile_time_size = nullptr; + array_size =ASRUtils::get_fixed_size_of_array(ASRUtils::expr_type(v)); + if(array_size != -1){ + compile_time_size = ASRUtils::EXPR( + ASR::make_IntegerConstant_t(al,v->base.loc,array_size, + ASRUtils::TYPE(ASR::make_Integer_t(al, v->base.loc, 8)))); + } + ASR::expr_t* array_size_expr = ASRUtils::EXPR( + ASR::make_ArraySize_t(al, v->base.loc, v, + nullptr, ASRUtils::TYPE(ASR::make_Integer_t(al, v->base.loc, 8)), + compile_time_size)); + + //Push type_as_int, size, arr_ptr + args.push_back(llvm::ConstantInt::get(context, llvm::APInt(32, number_of_type))); + visit_expr(*array_size_expr); + args.push_back(tmp); + visit_expr(*array_casted_to_pointer); + args.push_back(tmp); } } - template - void handle_print(const T &x) { + void handle_print(ASR::expr_t* arg, llvm::Value* end) { std::vector args; args.push_back(nullptr); // reserve space for fmt_str std::vector fmt; - llvm::Value *sep = nullptr; - llvm::Value *sep_no_space = nullptr; - llvm::Value *end = nullptr; - bool global_sep_space = false; - if (x.m_separator) { - this->visit_expr_wrapper(x.m_separator, true); - sep = tmp; - } else { - global_sep_space = true; - sep = builder->CreateGlobalStringPtr(" "); - } - if (x.m_end) { - this->visit_expr_wrapper(x.m_end, true); - end = tmp; - } else { + if(end == nullptr){ end = builder->CreateGlobalStringPtr("\n"); } - for (size_t i=0; iCreateGlobalStringPtr(""); - args.push_back(sep_no_space); - } - } - compute_fmt_specifier_and_arg(fmt, args, x.m_values[i], x.base.base.loc); - } + compute_fmt_specifier_and_arg(fmt, args, arg, arg->base.loc); fmt.push_back("%s"); args.push_back(end); std::string fmt_str; @@ -8478,12 +8887,12 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor std::vector fmt; std::vector args; args.push_back(nullptr); // reserve space for fmt_str - ASR::ttype_t *str_type_len_msg = ASRUtils::TYPE(ASR::make_Character_t( - al, loc, 1, stop_msg.size(), nullptr)); + ASR::ttype_t *str_type_len_msg = ASRUtils::TYPE(ASR::make_String_t( + al, loc, 1, stop_msg.size(), nullptr, ASR::string_physical_typeType::PointerString)); ASR::expr_t* STOP_MSG = ASRUtils::EXPR(ASR::make_StringConstant_t(al, loc, s2c(al, stop_msg), str_type_len_msg)); - ASR::ttype_t *str_type_len_1 = ASRUtils::TYPE(ASR::make_Character_t( - al, loc, 1, 1, nullptr)); + ASR::ttype_t *str_type_len_1 = ASRUtils::TYPE(ASR::make_String_t( + al, loc, 1, 1, nullptr, ASR::string_physical_typeType::PointerString)); ASR::expr_t* NEWLINE = ASRUtils::EXPR(ASR::make_StringConstant_t(al, loc, s2c(al, "\n"), str_type_len_1)); compute_fmt_specifier_and_arg(fmt, args, STOP_MSG, loc); @@ -8569,7 +8978,6 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor template std::vector convert_call_args(const T &x, bool is_method) { - get_builder0() std::vector args; for (size_t i=0; i if( clss_proc->m_proc->type == ASR::symbolType::Function ) { ASR::Function_t* func = down_cast(clss_proc->m_proc); set_func_subrout_params(func, x_abi, m_h, orig_arg, orig_arg_name, orig_arg_intent, i + is_method); + func_subrout = clss_proc->m_proc; } } else if( func_subrout->type == ASR::symbolType::Variable ) { ASR::Variable_t* v = down_cast(func_subrout); - ASR::Function_t* func = down_cast(v->m_type_declaration); + ASR::Function_t* func = down_cast(ASRUtils::symbol_get_past_external(v->m_type_declaration)); + func_subrout = ASRUtils::symbol_get_past_external(v->m_type_declaration); set_func_subrout_params(func, x_abi, m_h, orig_arg, orig_arg_name, orig_arg_intent, i + is_method); } else { LCOMPILERS_ASSERT(false) @@ -8598,7 +9008,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor if( x.m_args[i].m_value == nullptr ) { LCOMPILERS_ASSERT(orig_arg != nullptr); llvm::Type* llvm_orig_arg_type = llvm_utils->get_type_from_ttype_t_util(orig_arg->m_type, module.get()); - llvm::Value* llvm_arg = builder0.CreateAlloca(llvm_orig_arg_type); + llvm::Value* llvm_arg = llvm_utils->CreateAlloca(*builder, llvm_orig_arg_type); args.push_back(llvm_arg); continue ; } @@ -8608,13 +9018,12 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor if (ASR::is_a(*var_sym)) { ASR::Variable_t *arg = EXPR2VAR(x.m_args[i].m_value); uint32_t h = get_hash((ASR::asr_t*)arg); - if (compiler_options.interactive && - std::strcmp(arg->m_name, "_") == 0 && - arg->m_abi == ASR::abiType::Interactive) { - h = global_underscore_hash; - } if (llvm_symtab.find(h) != llvm_symtab.end()) { - tmp = llvm_symtab[h]; + if (llvm_symtab_deep_copy.find(h) != llvm_symtab_deep_copy.end()) { + tmp = llvm_symtab_deep_copy[h]; + } else { + tmp = llvm_symtab[h]; + } if( !ASRUtils::is_array(arg->m_type) ) { if (x_abi == ASR::abiType::Source && ASR::is_a(*arg->m_type)) { @@ -8623,46 +9032,39 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor // Local variable of type // CPtr is a void**, so we // have to load it - tmp = CreateLoad(tmp); + tmp = llvm_utils->CreateLoad(tmp); } } else if ( x_abi == ASR::abiType::BindC ) { if (orig_arg->m_abi == ASR::abiType::BindC && orig_arg->m_value_attr) { ASR::ttype_t* arg_type = arg->m_type; if (ASR::is_a(*arg_type)) { - int c_kind = ASRUtils::extract_kind_from_ttype_t(arg_type); - if (c_kind == 4) { - if (compiler_options.platform == Platform::Windows) { - // tmp is {float, float}* - // type_fx2p is i64* - llvm::Type* type_fx2p = llvm::Type::getInt64PtrTy(context); - // Convert {float,float}* to i64* using bitcast - tmp = builder->CreateBitCast(tmp, type_fx2p); - // Then convert i64* -> i64 - tmp = CreateLoad(tmp); - } else if (compiler_options.platform == Platform::macOS_ARM) { - // tmp is {float, float}* - // type_fx2p is [2 x float]* - llvm::Type* type_fx2p = llvm::ArrayType::get(llvm::Type::getFloatTy(context), 2)->getPointerTo(); - // Convert {float,float}* to [2 x float]* using bitcast - tmp = builder->CreateBitCast(tmp, type_fx2p); - // Then convert [2 x float]* -> [2 x float] - tmp = CreateLoad(tmp); - } else { - // tmp is {float, float}* - // type_fx2p is <2 x float>* - llvm::Type* type_fx2p = FIXED_VECTOR_TYPE::get(llvm::Type::getFloatTy(context), 2)->getPointerTo(); - // Convert {float,float}* to <2 x float>* using bitcast - tmp = builder->CreateBitCast(tmp, type_fx2p); - // Then convert <2 x float>* -> <2 x float> - tmp = CreateLoad(tmp); - } - } else { - LCOMPILERS_ASSERT(c_kind == 8) - if (compiler_options.platform == Platform::Windows) { - // 128 bit aggregate type is passed by reference + if (!startswith(compiler_options.target, "wasm")) { + int c_kind = ASRUtils::extract_kind_from_ttype_t(arg_type); + if (c_kind == 4) { + if (compiler_options.platform == Platform::Windows) { + // tmp is {float, float}* + // type_fx2 is i64 + llvm::Type* type_fx2 = llvm::Type::getInt64Ty(context); + tmp = llvm_utils->CreateLoad2(type_fx2, tmp); + } else if (compiler_options.platform == Platform::macOS_ARM) { + // tmp is {float, float}* + // type_fx2 is [2 x float] + llvm::Type* type_fx2 = llvm::ArrayType::get(llvm::Type::getFloatTy(context), 2); + tmp = llvm_utils->CreateLoad2(type_fx2, tmp); + } else { + // tmp is {float, float}* + // type_fx2 is <2 x float> + llvm::Type* type_fx2 = FIXED_VECTOR_TYPE::get(llvm::Type::getFloatTy(context), 2); + tmp = llvm_utils->CreateLoad2(type_fx2, tmp); + } } else { - // Pass by value - tmp = CreateLoad(tmp); + LCOMPILERS_ASSERT(c_kind == 8) + if (compiler_options.platform == Platform::Windows) { + // 128 bit aggregate type is passed by reference + } else { + // Pass by value + tmp = llvm_utils->CreateLoad2(arg_type, tmp); + } } } } else if (is_a(*arg_type)) { @@ -8671,16 +9073,16 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor // Local variable or Dummy out argument // of type CPtr is a void**, so we // have to load it - tmp = CreateLoad(tmp); + tmp = llvm_utils->CreateLoad(tmp); } } else { - if (!arg->m_value_attr) { + if (!arg->m_value_attr && !ASR::is_a(*arg_type)) { // Dereference the pointer argument (unless it is a CPtr) // to pass by value // E.g.: // i32* -> i32 // {double,double}* -> {double,double} - tmp = CreateLoad(tmp); + tmp = llvm_utils->CreateLoad2(arg_type, tmp); } } } @@ -8690,15 +9092,19 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor // at the beginning of the function to avoid // using alloca inside a loop, which would // run out of stack - llvm::BasicBlock &entry_block = builder->GetInsertBlock()->getParent()->getEntryBlock(); - llvm::IRBuilder<> builder0(context); - builder0.SetInsertPoint(&entry_block, entry_block.getFirstInsertionPt()); - llvm::AllocaInst *target = builder0.CreateAlloca( + llvm::AllocaInst *target = llvm_utils->CreateAlloca( target_type, nullptr, "call_arg_value_ptr"); builder->CreateStore(tmp, target); tmp = target; } + if (ASR::is_a(*arg->m_type)) { + tmp = llvm_utils->CreateLoad2(arg->m_type, tmp); + } } else { + if( arg->m_intent == intent_local && ASR::is_a(*arg->m_type) ) { + // (FunctionType**) --> (FunctionType*) + tmp = llvm_utils->CreateLoad2(arg->m_type, tmp); + } if( orig_arg && !LLVM::is_llvm_pointer(*orig_arg->m_type) && LLVM::is_llvm_pointer(*arg->m_type) && @@ -8710,14 +9116,14 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor !ASRUtils::is_character(*arg->m_type) ) { // TODO: Remove call to ASRUtils::check_equal_type // pass(rhs) is not respected in integration_tests/class_08.f90 - tmp = LLVM::CreateLoad(*builder, tmp); + tmp = llvm_utils->CreateLoad(tmp); } } } else { if( orig_arg && !LLVM::is_llvm_pointer(*orig_arg->m_type) && LLVM::is_llvm_pointer(*arg->m_type) ) { - tmp = LLVM::CreateLoad(*builder, tmp); + tmp = llvm_utils->CreateLoad(tmp); } } } else { @@ -8740,10 +9146,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor this->visit_expr_wrapper(arg->m_value, true); if( x_abi != ASR::abiType::BindC && !ASR::is_a(*arg->m_value) ) { - llvm::BasicBlock &entry_block = builder->GetInsertBlock()->getParent()->getEntryBlock(); - llvm::IRBuilder<> builder0(context); - builder0.SetInsertPoint(&entry_block, entry_block.getFirstInsertionPt()); - llvm::AllocaInst *target = builder0.CreateAlloca( + llvm::AllocaInst *target = llvm_utils->CreateAlloca( llvm_utils->get_type_from_ttype_t_util(arg->m_type, module.get()), nullptr, "call_arg_value"); builder->CreateStore(tmp, target); @@ -8795,13 +9198,13 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor size_t n_dims = ASRUtils::extract_dimensions_from_ttype(arg_type, arg_m_dims); if( !(ASRUtils::is_fixed_size_array(arg_m_dims, n_dims) && ASRUtils::expr_abi(x.m_args[i].m_value) == ASR::abiType::BindC) ) { - tmp = LLVM::CreateLoad(*builder, arr_descr->get_pointer_to_data(tmp)); + tmp = llvm_utils->CreateLoad(arr_descr->get_pointer_to_data(tmp)); } else { tmp = llvm_utils->create_gep(tmp, llvm::ConstantInt::get( llvm::Type::getInt32Ty(context), llvm::APInt(32, 0))); } } else { - tmp = LLVM::CreateLoad(*builder, tmp); + tmp = llvm_utils->CreateLoad(tmp); } } } @@ -8833,7 +9236,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor target_type = llvm_utils->getComplexType(a_kind); break; } - case (ASR::ttypeType::Character) : { + case (ASR::ttypeType::String) : { ASR::Variable_t *orig_arg = nullptr; if( func_subrout->type == ASR::symbolType::Function ) { ASR::Function_t* func = down_cast(func_subrout); @@ -8851,7 +9254,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor case (ASR::ttypeType::Logical) : target_type = llvm::Type::getInt1Ty(context); break; - case (ASR::ttypeType::Enum) : + case (ASR::ttypeType::EnumType) : target_type = llvm::Type::getInt32Ty(context); break; case (ASR::ttypeType::StructType) : @@ -8863,7 +9266,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor case (ASR::ttypeType::Pointer) : { ASR::ttype_t* type_ = ASRUtils::get_contained_type(arg_type); target_type = llvm_utils->get_type_from_ttype_t_util(type_, module.get()); - if( !ASR::is_a(*type_) ) { + if( !ASR::is_a(*type_) ) { target_type = target_type->getPointerTo(); } break; @@ -8880,16 +9283,8 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor target_type = llvm_utils->get_type_from_ttype_t_util(arg_type_, module.get()); break; } - case (ASR::ttypeType::Dict): { - target_type = llvm_utils->get_type_from_ttype_t_util(arg_type_, module.get()); - break; - } - case (ASR::ttypeType::Set): { - target_type = llvm_utils->get_type_from_ttype_t_util(arg_type_, module.get()); - break; - } default : - throw CodeGenError("Type " + ASRUtils::type_to_str(arg_type) + " not implemented yet."); + throw CodeGenError("Type " + ASRUtils::type_to_str_fortran(arg_type) + " not implemented yet."); } if( ASR::is_a(*x.m_args[i].m_value) ) { target_type = llvm::Type::getInt32Ty(context); @@ -8906,10 +9301,6 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor if( func_subrout->type == ASR::symbolType::Function ) { ASR::Function_t* func = down_cast(func_subrout); orig_arg = EXPR2VAR(func->m_args[i]); - } else if( func_subrout->type == ASR::symbolType::Variable ) { - ASR::Variable_t *v = ASR::down_cast(func_subrout); - ASR::Function_t* func = down_cast(v->m_type_declaration); - orig_arg = EXPR2VAR(func->m_args[i]); } else { LCOMPILERS_ASSERT(false) } @@ -8927,24 +9318,20 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor // run out of stack if( (ASR::is_a(*x.m_args[i].m_value) || (ASR::is_a(*x.m_args[i].m_value) && - (ASRUtils::is_array(arg_type) || + !ASRUtils::is_allocatable(arg_type) && (ASRUtils::is_array(arg_type) || ASR::is_a(*ASRUtils::expr_type(x.m_args[i].m_value))))) && value->getType()->isPointerTy()) { - value = CreateLoad(value); + value = llvm_utils->CreateLoad(value); } if( !ASR::is_a(*arg_type) && !(orig_arg && !LLVM::is_llvm_pointer(*orig_arg->m_type) && - LLVM::is_llvm_pointer(*arg_type) && - !ASRUtils::is_character(*orig_arg->m_type)) && !ASR::is_a(*x.m_args[i].m_value) ) { - llvm::BasicBlock &entry_block = builder->GetInsertBlock()->getParent()->getEntryBlock(); - llvm::IRBuilder<> builder0(context); - builder0.SetInsertPoint(&entry_block, entry_block.getFirstInsertionPt()); - llvm::AllocaInst *target = builder0.CreateAlloca( + LLVM::is_llvm_pointer(*arg_type) && + !ASRUtils::is_character(*orig_arg->m_type) && + ASRUtils::is_descriptorString(arg_type)) && !ASR::is_a(*x.m_args[i].m_value) ) { + llvm::AllocaInst *target = llvm_utils->CreateAlloca( target_type, nullptr, "call_arg_value"); if( ASR::is_a(*arg_type) || - ASR::is_a(*arg_type) || - ASR::is_a(*arg_type) || - ASR::is_a(*arg_type)) { + ASR::is_a(*arg_type) ) { llvm_utils->deepcopy(value, target, arg_type, module.get(), name2memidx); } else { builder->CreateStore(value, target); @@ -8961,7 +9348,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor // To avoid segmentation faults when original argument // is not a ASR::Variable_t like callbacks. - if( orig_arg && !ASR::is_a( + if( orig_arg && !ASR::is_a( *ASRUtils::type_get_past_array( ASRUtils::type_get_past_allocatable( ASRUtils::type_get_past_pointer( @@ -8991,7 +9378,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor int signal_kind = ASRUtils::extract_kind_from_ttype_t(signal_type); llvm::Value* num_shifts = llvm::ConstantInt::get(context, llvm::APInt(32, signal_kind * 8 - 1)); llvm::Value* shifted_signal = builder->CreateShl(signal, num_shifts); - llvm::Value* int_var = builder->CreateBitCast(CreateLoad(variable), shifted_signal->getType()); + llvm::Value* int_var = builder->CreateBitCast(llvm_utils->CreateLoad(variable), shifted_signal->getType()); tmp = builder->CreateXor(shifted_signal, int_var); llvm::Type* variable_type = llvm_utils->get_type_from_ttype_t_util(asr_variable->m_type, module.get()); tmp = builder->CreateBitCast(tmp, variable_type); @@ -9050,29 +9437,30 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor llvm::Value* convert_to_polymorphic_arg(llvm::Value* dt, ASR::ttype_t* s_m_args0_type, ASR::ttype_t* arg_type) { - get_builder0() - if( !ASR::is_a(*ASRUtils::type_get_past_array(s_m_args0_type)) ) { + if( !ASR::is_a(*ASRUtils::type_get_past_array(s_m_args0_type)) ) { return dt; } if( ASRUtils::is_abstract_class_type(s_m_args0_type) ) { if( ASRUtils::is_array(s_m_args0_type) ) { llvm::Type* array_type = llvm_utils->get_type_from_ttype_t_util(s_m_args0_type, module.get()); - llvm::Value* abstract_array = builder0.CreateAlloca(array_type); + llvm::Value* abstract_array = llvm_utils->CreateAlloca(*builder, array_type); llvm::Type* array_data_type = llvm_utils->get_el_type( ASRUtils::type_get_past_array(s_m_args0_type), module.get()); - llvm::Value* array_data = builder0.CreateAlloca(array_data_type); + llvm::Type* dt_array_data_type = llvm_utils->get_el_type( + ASRUtils::type_get_past_array(arg_type), module.get()); + llvm::Value* array_data = llvm_utils->CreateAlloca(*builder, array_data_type); builder->CreateStore(array_data, arr_descr->get_pointer_to_data(abstract_array)); - arr_descr->fill_array_details(dt, abstract_array, s_m_args0_type, true); - llvm::Value* polymorphic_data = CreateLoad( + arr_descr->fill_array_details(dt, abstract_array, arg_type, s_m_args0_type, module.get(), true); + llvm::Value* polymorphic_data = llvm_utils->CreateLoad2(array_data_type->getPointerTo(), arr_descr->get_pointer_to_data(abstract_array)); - llvm::Value* polymorphic_data_addr = llvm_utils->create_gep(polymorphic_data, 1); - llvm::Value* dt_data = CreateLoad(arr_descr->get_pointer_to_data(dt)); + llvm::Value* polymorphic_data_addr = llvm_utils->create_gep2(array_data_type, polymorphic_data, 1); + llvm::Value* dt_data = llvm_utils->CreateLoad2(dt_array_data_type->getPointerTo(), arr_descr->get_pointer_to_data(dt)); builder->CreateStore( builder->CreateBitCast(dt_data, llvm::Type::getVoidTy(context)->getPointerTo()), polymorphic_data_addr); - llvm::Value* type_id_addr = llvm_utils->create_gep(polymorphic_data, 0); + llvm::Value* type_id_addr = llvm_utils->create_gep2(array_data_type, polymorphic_data, 0); builder->CreateStore( llvm::ConstantInt::get(llvm_utils->getIntType(8), llvm::APInt(64, -((int) ASRUtils::type_get_past_array(arg_type)->type) - @@ -9081,17 +9469,19 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor return abstract_array; } else { llvm::Type* _type = llvm_utils->get_type_from_ttype_t_util(s_m_args0_type, module.get()); - llvm::Value* abstract_ = builder0.CreateAlloca(_type); + llvm::Value* abstract_ = llvm_utils->CreateAlloca(*builder, _type); llvm::Value* polymorphic_addr = llvm_utils->create_gep(abstract_, 1); builder->CreateStore( builder->CreateBitCast(dt, llvm::Type::getVoidTy(context)->getPointerTo()), polymorphic_addr); llvm::Value* type_id_addr = llvm_utils->create_gep(abstract_, 0); - ASR::StructType_t* struct_t = ASR::down_cast(arg_type); - ASR::symbol_t* struct_sym = ASRUtils::symbol_get_past_external(struct_t->m_derived_type); - llvm::Value* hash = llvm::ConstantInt::get(llvm_utils->getIntType(8), + if (ASR::is_a(*arg_type)) { + ASR::StructType_t* struct_t = ASR::down_cast(arg_type); + ASR::symbol_t* struct_sym = ASRUtils::symbol_get_past_external(struct_t->m_derived_type); + llvm::Value* hash = llvm::ConstantInt::get(llvm_utils->getIntType(8), llvm::APInt(64, get_class_hash(struct_sym))); - builder->CreateStore(hash, type_id_addr); + builder->CreateStore(hash, type_id_addr); + } return abstract_; } } else if( ASR::is_a(*ASRUtils::type_get_past_array(arg_type)) ) { @@ -9101,12 +9491,13 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor type2vtab[struct_sym].find(current_scope) == type2vtab[struct_sym].end() ) { create_vtab_for_struct_type(struct_sym, current_scope); } - llvm::Value* dt_polymorphic = builder0.CreateAlloca( + llvm::Value* dt_polymorphic = llvm_utils->CreateAlloca(*builder, llvm_utils->getClassType(s_m_args0_type, true)); - llvm::Value* hash_ptr = llvm_utils->create_gep(dt_polymorphic, 0); + llvm::Type* _type = llvm_utils->get_type_from_ttype_t_util(s_m_args0_type, module.get()); + llvm::Value* hash_ptr = llvm_utils->create_gep2(_type, dt_polymorphic, 0); llvm::Value* hash = llvm::ConstantInt::get(llvm_utils->getIntType(8), llvm::APInt(64, get_class_hash(struct_sym))); builder->CreateStore(hash, hash_ptr); - llvm::Value* class_ptr = llvm_utils->create_gep(dt_polymorphic, 1); + llvm::Value* class_ptr = llvm_utils->create_gep2(_type, dt_polymorphic, 1); builder->CreateStore(builder->CreateBitCast(dt, llvm_utils->getStructType(s_m_args0_type, module.get(), true)), class_ptr); return dt_polymorphic; } @@ -9114,7 +9505,6 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } void visit_SubroutineCall(const ASR::SubroutineCall_t &x) { - get_builder0() if (compiler_options.emit_debug_info) debug_emit_loc(x); if( ASRUtils::is_intrinsic_optimization(x.m_name) ) { ASR::Function_t* routine = ASR::down_cast( @@ -9132,7 +9522,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor ptr_loads = 1; this->visit_expr(*x.m_dt); ptr_loads = ptr_loads_copy; - llvm::Value* callee = LLVM::CreateLoad(*builder, tmp); + llvm::Value* callee = llvm_utils->CreateLoad(tmp); args = convert_call_args(x, false); llvm::FunctionType* fntype = llvm_utils->get_function_type( @@ -9170,8 +9560,8 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor proc_sym = clss_proc->m_proc; } else if (ASR::is_a(*proc_sym)) { ASR::symbol_t *type_decl = ASR::down_cast(proc_sym)->m_type_declaration; - LCOMPILERS_ASSERT(type_decl); - s = ASR::down_cast(type_decl); + LCOMPILERS_ASSERT(type_decl && ASR::is_a(*ASRUtils::symbol_get_past_external(type_decl))); + s = ASR::down_cast(ASRUtils::symbol_get_past_external(type_decl)); } else { throw CodeGenError("SubroutineCall: Symbol type not supported"); } @@ -9222,22 +9612,25 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor ASRUtils::type_get_past_pointer(ASRUtils::expr_type(s->m_args[0]))); } // Convert to polymorphic argument - dt_polymorphic = builder0.CreateAlloca( + dt_polymorphic = llvm_utils->CreateAlloca(*builder, llvm_utils->getClassType(s_m_args0_type, true)); llvm::Value* hash_ptr = llvm_utils->create_gep(dt_polymorphic, 0); llvm::Value* hash = llvm::ConstantInt::get( llvm_utils->getIntType(8), llvm::APInt(64, get_class_hash(struct_sym))); builder->CreateStore(hash, hash_ptr); struct_sym = ASRUtils::symbol_get_past_external( - ASR::down_cast(caller->m_type)->m_class_type); + ASR::down_cast(caller->m_type)->m_class_type); int dt_idx = name2memidx[ASRUtils::symbol_name(struct_sym)] [ASRUtils::symbol_name(ASRUtils::symbol_get_past_external(struct_mem->m_m))]; - llvm::Value* dt_1 = llvm_utils->create_gep( - CreateLoad(llvm_utils->create_gep(dt, 1)), dt_idx); + llvm::Type *dt_type = llvm_utils->getStructType(caller->m_type, + module.get()); + llvm::Value* dt_1 = llvm_utils->create_gep2(dt_type, + llvm_utils->CreateLoad2(dt_type->getPointerTo(), llvm_utils->create_gep(dt, 1)), dt_idx); llvm::Value* class_ptr = llvm_utils->create_gep(dt_polymorphic, 1); - if (is_nested_pointer(dt_1)) { - dt_1 = CreateLoad(dt_1); + if ( LLVM::is_llvm_pointer(*arg_type) ) { + dt_1 = llvm_utils->CreateLoad2(llvm_utils->getStructType( + s_m_args0_type, module.get(), true), dt_1); } builder->CreateStore(dt_1, class_ptr); if (self_argument == nullptr) { @@ -9245,6 +9638,13 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } else { pass_arg = dt_polymorphic; } + } else if (ASR::is_a(*x.m_dt)){ + this->visit_expr(*x.m_dt); + llvm::Value* dt = tmp; + llvm::Value* dt_polymorphic = tmp; + dt_polymorphic = convert_to_polymorphic_arg(dt, ASRUtils::expr_type(s->m_args[0]), + ASRUtils::expr_type(x.m_dt)); + args.push_back(dt_polymorphic); } else { throw CodeGenError("SubroutineCall: StructType symbol type not supported"); } @@ -9274,7 +9674,8 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } args = convert_call_args(x, is_method); LCOMPILERS_ASSERT(args.size() > 0); - tmp = builder->CreateCall(fn, {CreateLoad(args[0])}); + tmp = builder->CreateCall(fn, {llvm_utils->CreateLoad2( + llvm::Type::getInt32Ty(context), args[0])}); if (args.size() > 1) builder->CreateStore(tmp, args[1]); return; @@ -9290,11 +9691,11 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } args = convert_call_args(x, is_method); LCOMPILERS_ASSERT(args.size() > 0); - tmp = builder->CreateCall(fn, {CreateLoad(args[0])}); + tmp = builder->CreateCall(fn, {llvm_utils->CreateLoad(args[0])}); if (args.size() > 1) builder->CreateStore(tmp, args[1]); return; - } else if (sub_name == "execute_command_line") { + } else if (sub_name == "_lcompilers_execute_command_line_") { llvm::Function *fn = module->getFunction("_lfortran_exec_command"); if (!fn) { llvm::FunctionType *function_type = llvm::FunctionType::get( @@ -9306,7 +9707,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } args = convert_call_args(x, is_method); LCOMPILERS_ASSERT(args.size() > 0); - tmp = builder->CreateCall(fn, {CreateLoad(args[0])}); + tmp = builder->CreateCall(fn, {llvm_utils->CreateLoad(args[0])}); return; } h = get_hash((ASR::asr_t*)proc_sym); @@ -9321,9 +9722,20 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor std::string m_name = ASRUtils::symbol_name(x.m_name); args = convert_call_args(x, is_method); tmp = builder->CreateCall(fntype, fn, args); + } else if (ASR::is_a(*proc_sym) && + llvm_symtab.find(h) != llvm_symtab.end()) { + llvm::Value* fn = llvm_symtab[h]; + fn = llvm_utils->CreateLoad(fn); + ASR::Variable_t* v = ASR::down_cast(proc_sym); + llvm::FunctionType* fntype = llvm_utils->get_function_type( + ASR::down_cast(v->m_type), module.get()); + std::string m_name = ASRUtils::symbol_name(x.m_name); + args = convert_call_args(x, is_method); + tmp = builder->CreateCall(fntype, fn, args); } else if (llvm_symtab_fn.find(h) == llvm_symtab_fn.end()) { throw CodeGenError("Subroutine code not generated for '" + std::string(s->m_name) + "'"); + return; } else { llvm::Function *fn = llvm_symtab_fn[h]; std::string m_name = ASRUtils::symbol_name(x.m_name); @@ -9390,10 +9802,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor int n_dims = ASRUtils::extract_n_dims_from_ttype(asr_type); if( n_dims > 0 ) { llvm::Type* llvm_data_type = llvm_utils->get_type_from_ttype_t_util( - ASRUtils::type_get_past_allocatable( - ASRUtils::type_get_past_pointer( - ASRUtils::type_get_past_array(asr_type))), - module.get(), ASRUtils::expr_abi(arg)); + ASRUtils::extract_type(asr_type), module.get(), ASRUtils::expr_abi(arg)); tmp = arr_descr->get_is_allocated_flag(tmp, llvm_data_type); } else { tmp = builder->CreateICmpNE( @@ -9405,14 +9814,13 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor llvm::Value* CreatePointerToStructTypeReturnValue(llvm::FunctionType* fnty, llvm::Value* return_value, ASR::ttype_t* asr_return_type) { - get_builder0() if( !LLVM::is_llvm_struct(asr_return_type) ) { return return_value; } // Call to LLVM APIs not needed to fetch the return type of the function. // We can use asr_return_type as well but anyways for compactness I did it here. - llvm::Value* pointer_to_struct = builder0.CreateAlloca(fnty->getReturnType(), nullptr); + llvm::Value* pointer_to_struct = llvm_utils->CreateAlloca(*builder, fnty->getReturnType()); LLVM::CreateStore(*builder, return_value, pointer_to_struct); return pointer_to_struct; } @@ -9431,7 +9839,6 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } void visit_RuntimePolymorphicSubroutineCall(const ASR::SubroutineCall_t& x, std::string proc_sym_name) { - get_builder0() std::vector> vtabs; ASR::Struct_t* dt_sym_type = nullptr; ASR::ttype_t* dt_ttype_t = ASRUtils::type_get_past_allocatable(ASRUtils::type_get_past_pointer( @@ -9440,8 +9847,8 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor ASR::StructType_t* struct_t = ASR::down_cast(dt_ttype_t); dt_sym_type = ASR::down_cast( ASRUtils::symbol_get_past_external(struct_t->m_derived_type)); - } else if( ASR::is_a(*dt_ttype_t) ) { - ASR::Class_t* class_t = ASR::down_cast(dt_ttype_t); + } else if( ASR::is_a(*dt_ttype_t) ) { + ASR::ClassType_t* class_t = ASR::down_cast(dt_ttype_t); dt_sym_type = ASR::down_cast( ASRUtils::symbol_get_past_external(class_t->m_class_type)); } @@ -9466,23 +9873,26 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor ptr_loads = ptr_loads_copy; llvm::Value* llvm_dt = tmp; llvm::BasicBlock *mergeBB = llvm::BasicBlock::Create(context, "ifcont"); + llvm::Type* i64 = llvm::Type::getInt64Ty(context); for( size_t i = 0; i < vtabs.size(); i++ ) { llvm::Function *fn = builder->GetInsertBlock()->getParent(); llvm::BasicBlock *thenBB = llvm::BasicBlock::Create(context, "then", fn); llvm::BasicBlock *elseBB = llvm::BasicBlock::Create(context, "else"); - llvm::Value* vptr_int_hash = CreateLoad(llvm_utils->create_gep(llvm_dt, 0)); - llvm::Value* dt_data = CreateLoad(llvm_utils->create_gep(llvm_dt, 1)); + llvm::Value* vptr_int_hash = llvm_utils->CreateLoad2(i64, llvm_utils->create_gep(llvm_dt, 0)); + llvm::Type *dt_type = llvm_utils->getStructType(ASRUtils::extract_type( + ASRUtils::expr_type(x.m_dt)), module.get(), true); + llvm::Value* dt_data = llvm_utils->CreateLoad2(dt_type, llvm_utils->create_gep(llvm_dt, 1)); ASR::ttype_t* selector_var_type = ASRUtils::expr_type(x.m_dt); if( ASRUtils::is_array(selector_var_type) ) { - vptr_int_hash = CreateLoad(llvm_utils->create_gep(vptr_int_hash, 0)); + vptr_int_hash = llvm_utils->CreateLoad(llvm_utils->create_gep(vptr_int_hash, 0)); } ASR::symbol_t* type_sym = ASRUtils::symbol_get_past_external(vtabs[i].second); llvm::Value* type_sym_vtab = vtabs[i].first; llvm::Value* cond = builder->CreateICmpEQ( vptr_int_hash, - CreateLoad( + llvm_utils->CreateLoad2(i64, llvm_utils->create_gep(type_sym_vtab, 0) ) ); builder->CreateCondBr(cond, thenBB, elseBB); @@ -9492,7 +9902,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor ASR::Struct_t* struct_type_t = ASR::down_cast(type_sym); llvm::Type* target_dt_type = llvm_utils->getStructType(struct_type_t, module.get(), true); llvm::Type* target_class_dt_type = llvm_utils->getClassType(struct_type_t); - llvm::Value* target_dt = builder0.CreateAlloca(target_class_dt_type); + llvm::Value* target_dt = llvm_utils->CreateAlloca(*builder, target_class_dt_type); llvm::Value* target_dt_hash_ptr = llvm_utils->create_gep(target_dt, 0); builder->CreateStore(vptr_int_hash, target_dt_hash_ptr); llvm::Value* target_dt_data_ptr = llvm_utils->create_gep(target_dt, 1); @@ -9518,7 +9928,6 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } void visit_RuntimePolymorphicFunctionCall(const ASR::FunctionCall_t& x, std::string proc_sym_name) { - get_builder0() std::vector> vtabs; ASR::Struct_t* dt_sym_type = nullptr; ASR::ttype_t* dt_ttype_t = ASRUtils::type_get_past_allocatable(ASRUtils::type_get_past_pointer( @@ -9527,8 +9936,8 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor ASR::StructType_t* struct_t = ASR::down_cast(dt_ttype_t); dt_sym_type = ASR::down_cast( ASRUtils::symbol_get_past_external(struct_t->m_derived_type)); - } else if( ASR::is_a(*dt_ttype_t) ) { - ASR::Class_t* class_t = ASR::down_cast(dt_ttype_t); + } else if( ASR::is_a(*dt_ttype_t) ) { + ASR::ClassType_t* class_t = ASR::down_cast(dt_ttype_t); dt_sym_type = ASR::down_cast( ASRUtils::symbol_get_past_external(class_t->m_class_type)); } @@ -9552,25 +9961,28 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor this->visit_expr_wrapper(x.m_dt); ptr_loads = ptr_loads_copy; llvm::Value* llvm_dt = tmp; - tmp = builder0.CreateAlloca(llvm_utils->get_type_from_ttype_t_util(x.m_type, module.get())); + tmp = llvm_utils->CreateAlloca(*builder, llvm_utils->get_type_from_ttype_t_util(x.m_type, module.get())); llvm::BasicBlock *mergeBB = llvm::BasicBlock::Create(context, "ifcont"); + llvm::Type* i64 = llvm::Type::getInt64Ty(context); for( size_t i = 0; i < vtabs.size(); i++ ) { llvm::Function *fn = builder->GetInsertBlock()->getParent(); llvm::BasicBlock *thenBB = llvm::BasicBlock::Create(context, "then", fn); llvm::BasicBlock *elseBB = llvm::BasicBlock::Create(context, "else"); - llvm::Value* vptr_int_hash = CreateLoad(llvm_utils->create_gep(llvm_dt, 0)); - llvm::Value* dt_data = CreateLoad(llvm_utils->create_gep(llvm_dt, 1)); + llvm::Value* vptr_int_hash = llvm_utils->CreateLoad2(i64, llvm_utils->create_gep(llvm_dt, 0)); + llvm::Type *dt_type = llvm_utils->getStructType(ASRUtils::extract_type( + ASRUtils::expr_type(x.m_dt)), module.get(), true); + llvm::Value* dt_data = llvm_utils->CreateLoad2(dt_type, llvm_utils->create_gep(llvm_dt, 1)); ASR::ttype_t* selector_var_type = ASRUtils::expr_type(x.m_dt); if( ASRUtils::is_array(selector_var_type) ) { - vptr_int_hash = CreateLoad(llvm_utils->create_gep(vptr_int_hash, 0)); + vptr_int_hash = llvm_utils->CreateLoad(llvm_utils->create_gep(vptr_int_hash, 0)); } ASR::symbol_t* type_sym = ASRUtils::symbol_get_past_external(vtabs[i].second); llvm::Value* type_sym_vtab = vtabs[i].first; llvm::Value* cond = builder->CreateICmpEQ( vptr_int_hash, - CreateLoad( + llvm_utils->CreateLoad2(i64, llvm_utils->create_gep(type_sym_vtab, 0) ) ); builder->CreateCondBr(cond, thenBB, elseBB); @@ -9580,7 +9992,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor ASR::Struct_t* struct_type_t = ASR::down_cast(type_sym); llvm::Type* target_dt_type = llvm_utils->getStructType(struct_type_t, module.get(), true); llvm::Type* target_class_dt_type = llvm_utils->getClassType(struct_type_t); - llvm::Value* target_dt = builder0.CreateAlloca(target_class_dt_type); + llvm::Value* target_dt = llvm_utils->CreateAlloca(*builder, target_class_dt_type); llvm::Value* target_dt_hash_ptr = llvm_utils->create_gep(target_dt, 0); builder->CreateStore(vptr_int_hash, target_dt_hash_ptr); llvm::Value* target_dt_data_ptr = llvm_utils->create_gep(target_dt, 1); @@ -9606,11 +10018,10 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor current_select_type_block_der_type.clear(); } start_new_block(mergeBB); - tmp = CreateLoad(tmp); + tmp = llvm_utils->CreateLoad(tmp); } void visit_FunctionCall(const ASR::FunctionCall_t &x) { - get_builder0() if ( compiler_options.emit_debug_info ) debug_emit_loc(x); if( ASRUtils::is_intrinsic_optimization(x.m_name) ) { ASR::Function_t* routine = ASR::down_cast( @@ -9632,7 +10043,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor ptr_loads = 1; this->visit_expr(*x.m_dt); ptr_loads = ptr_loads_copy; - llvm::Value* callee = LLVM::CreateLoad(*builder, tmp); + llvm::Value* callee = llvm_utils->CreateLoad(tmp); args = convert_call_args(x, false); llvm::FunctionType* fntype = llvm_utils->get_function_type( @@ -9714,8 +10125,8 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor ASR::StructType_t* struct_t = ASR::down_cast(arg_type); struct_sym = ASRUtils::symbol_get_past_external( struct_t->m_derived_type); - } else if (ASR::is_a(*arg_type)) { - ASR::Class_t* struct_t = ASR::down_cast(arg_type); + } else if (ASR::is_a(*arg_type)) { + ASR::ClassType_t* struct_t = ASR::down_cast(arg_type); struct_sym = ASRUtils::symbol_get_past_external( struct_t->m_class_type); } else { @@ -9735,7 +10146,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor ASRUtils::expr_type(s->m_args[0]))); } // Convert to polymorphic argument - llvm::Value* dt_polymorphic = builder0.CreateAlloca( + llvm::Value* dt_polymorphic = llvm_utils->CreateAlloca(*builder, llvm_utils->getClassType(s_m_args0_type, true)); llvm::Value* hash_ptr = llvm_utils->create_gep(dt_polymorphic, 0); llvm::Value* hash = llvm::ConstantInt::get( @@ -9745,17 +10156,23 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor if (ASR::is_a(*caller_type)) { struct_sym = ASRUtils::symbol_get_past_external( ASR::down_cast(caller_type)->m_derived_type); - } else if (ASR::is_a(*caller_type)) { + } else if (ASR::is_a(*caller_type)) { struct_sym = ASRUtils::symbol_get_past_external( - ASR::down_cast(caller_type)->m_class_type); + ASR::down_cast(caller_type)->m_class_type); } else { LCOMPILERS_ASSERT(false); } int dt_idx = name2memidx[ASRUtils::symbol_name(struct_sym)] [ASRUtils::symbol_name(ASRUtils::symbol_get_past_external(struct_mem->m_m))]; - llvm::Value* dt_1 = llvm_utils->create_gep(dt, dt_idx); - dt_1 = CreateLoad(llvm_utils->create_gep(CreateLoad(dt_1), 1)); + llvm::Type *a_poly_type = llvm_utils->get_type_from_ttype_t_util( + s_m_args0_type, module.get()); + llvm::Type *a_type = llvm_utils->getStructType(s_m_args0_type, + module.get()); + llvm::Type *dt_type = llvm_utils->getStructType(caller_type, + module.get()); + llvm::Value* dt_1 = llvm_utils->create_gep2(dt_type, dt, dt_idx); + dt_1 = llvm_utils->CreateLoad2(a_type, llvm_utils->create_gep2(a_poly_type, llvm_utils->CreateLoad2(a_poly_type->getPointerTo(), dt_1), 1)); llvm::Value* class_ptr = llvm_utils->create_gep(dt_polymorphic, 1); builder->CreateStore(dt_1, class_ptr); if (self_argument.length() == 0) { @@ -9763,6 +10180,13 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } else { pass_arg = dt_polymorphic; } + } else if(ASR::is_a(*x.m_dt)) { + this->visit_expr(*x.m_dt); + llvm::Value* dt = tmp; + llvm::Value* dt_polymorphic = tmp; + dt_polymorphic = convert_to_polymorphic_arg(dt, ASRUtils::expr_type(s->m_args[0]), + ASRUtils::expr_type(x.m_dt)); + args.push_back(dt_polymorphic); } else { throw CodeGenError("FunctionCall: StructType symbol type not supported"); } @@ -9805,12 +10229,12 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor tmp = lfortran_str_len(args[0]); return; } else if (func_name == "command_argument_count") { - llvm::Function *fn = module->getFunction("_lpython_get_argc"); + llvm::Function *fn = module->getFunction("_lfortran_get_argc"); if(!fn) { llvm::FunctionType *function_type = llvm::FunctionType::get( llvm::Type::getInt32Ty(context), {}, false); fn = llvm::Function::Create(function_type, - llvm::Function::ExternalLinkage, "_lpython_get_argc", *module); + llvm::Function::ExternalLinkage, "_lfortran_get_argc", *module); } tmp = builder->CreateCall(fn, {}); return; @@ -9856,11 +10280,11 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor int a_kind = down_cast(return_var_type0)->m_kind; if (a_kind == 8) { if (compiler_options.platform == Platform::Windows) { - tmp = builder->CreateAlloca(complex_type_8, nullptr); + tmp = llvm_utils->CreateAlloca(*builder, complex_type_8); args.insert(args.begin(), tmp); builder->CreateCall(fn, args); // Convert {double,double}* to {double,double} - tmp = CreateLoad(tmp); + tmp = llvm_utils->CreateLoad(tmp); } else { tmp = builder->CreateCall(fn, args); } @@ -9873,6 +10297,12 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } else { tmp = CreateCallUtil(fn, args, return_var_type0); } + // always use string_descriptor* in the codebase. + if(fn->getReturnType() == string_descriptor){ + llvm::Value* string_descriptor_ptr = llvm_utils->CreateAlloca(*builder, string_descriptor); + builder->CreateStore(tmp, string_descriptor_ptr); + tmp = string_descriptor_ptr; + } } if (ASRUtils::get_FunctionType(s)->m_abi == ASR::abiType::BindC) { ASR::ttype_t *return_var_type0 = EXPR2VAR(s->m_return_var)->m_type; @@ -9885,12 +10315,12 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor // i64 llvm::Type* type_fx2 = llvm::Type::getInt64Ty(context); // Convert i64 to i64* - llvm::AllocaInst *p_fx2 = builder0.CreateAlloca(type_fx2, nullptr); + llvm::AllocaInst *p_fx2 = llvm_utils->CreateAlloca(*builder, type_fx2); builder->CreateStore(tmp, p_fx2); // Convert i64* to {float,float}* using bitcast tmp = builder->CreateBitCast(p_fx2, complex_type_4->getPointerTo()); // Convert {float,float}* to {float,float} - tmp = CreateLoad(tmp); + tmp = llvm_utils->CreateLoad(tmp); } else if (compiler_options.platform == Platform::macOS_ARM) { // pass } else { @@ -9899,12 +10329,12 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor // <2 x float> llvm::Type* type_fx2 = FIXED_VECTOR_TYPE::get(llvm::Type::getFloatTy(context), 2); // Convert <2 x float> to <2 x float>* - llvm::AllocaInst *p_fx2 = builder0.CreateAlloca(type_fx2, nullptr); + llvm::AllocaInst *p_fx2 = llvm_utils->CreateAlloca(*builder, type_fx2); builder->CreateStore(tmp, p_fx2); // Convert <2 x float>* to {float,float}* using bitcast tmp = builder->CreateBitCast(p_fx2, complex_type_4->getPointerTo()); // Convert {float,float}* to {float,float} - tmp = CreateLoad(tmp); + tmp = llvm_utils->CreateLoad(tmp); } } } @@ -9914,6 +10344,26 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } } + void load_array_size_deep_copy(ASR::expr_t* x) { + if (x != nullptr && ASR::is_a(*x)) { + ASR::Var_t* x_var = ASR::down_cast(x); + ASR::symbol_t* x_sym = ASRUtils::symbol_get_past_external(x_var->m_v); + if (x_sym != nullptr && ASR::is_a(*x_sym)) { + ASR::Variable_t* x_sym_variable = ASR::down_cast(x_sym); + uint32_t x_sym_variable_h = get_hash((ASR::asr_t*)x_sym_variable); + if (llvm_symtab_deep_copy.find(x_sym_variable_h) != llvm_symtab_deep_copy.end()) { + tmp = llvm_utils->CreateLoad2(ASRUtils::expr_type(x),llvm_symtab_deep_copy[x_sym_variable_h]); + } else { + this->visit_expr_wrapper(x, true); + } + } else { + this->visit_expr_wrapper(x, true); + } + } else { + this->visit_expr_wrapper(x, true); + } + } + void visit_ArraySizeUtil(ASR::expr_t* m_v, ASR::ttype_t* m_type, ASR::expr_t* m_dim=nullptr, ASR::expr_t* m_value=nullptr) { if( m_value ) { @@ -9928,9 +10378,15 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor LLVM::is_llvm_pointer(*ASRUtils::expr_type(m_v)); visit_expr_wrapper(m_v); ptr_loads = ptr_loads_copy; - bool is_pointer_array = tmp->getType()->getContainedType(0)->isPointerTy(); - if (is_pointer_array) { - tmp = CreateLoad(tmp); + ASR::ttype_t* x_mv_type = ASRUtils::expr_type(m_v); + LCOMPILERS_ASSERT(ASRUtils::is_array(x_mv_type)); + llvm::Type* array_type = llvm_utils->get_type_from_ttype_t_util( + ASRUtils::type_get_past_allocatable(ASRUtils::type_get_past_pointer(x_mv_type)), module.get()); + if (is_a(*m_v)) { + tmp = llvm_utils->CreateLoad2(array_type->getPointerTo(), tmp); +#if LLVM_VERSION_MAJOR > 16 + ptr_type[tmp] = array_type; +#endif } llvm::Value* llvm_arg = tmp; @@ -9941,9 +10397,8 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor llvm_dim = tmp; } - ASR::ttype_t* x_mv_type = ASRUtils::expr_type(m_v); ASR::array_physical_typeType physical_type = ASRUtils::extract_physical_type(x_mv_type); - if (physical_type == ASR::array_physical_typeType::CharacterArraySinglePointer) { + if (physical_type == ASR::array_physical_typeType::StringArraySinglePointer) { if (ASRUtils::is_fixed_size_array(x_mv_type)) { physical_type = ASR::array_physical_typeType::FixedSizeArray; } else { @@ -9965,10 +10420,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor ASR::dimension_t* m_dims = nullptr; int n_dims = ASRUtils::extract_dimensions_from_ttype(x_mv_type, m_dims); if( llvm_dim ) { - llvm::BasicBlock &entry_block = builder->GetInsertBlock()->getParent()->getEntryBlock(); - llvm::IRBuilder<> builder0(context); - builder0.SetInsertPoint(&entry_block, entry_block.getFirstInsertionPt()); - llvm::AllocaInst *target = builder0.CreateAlloca( + llvm::AllocaInst *target = llvm_utils->CreateAlloca( target_type, nullptr, "array_size"); llvm::BasicBlock *mergeBB = llvm::BasicBlock::Create(context, "ifcont"); for( int i = 0; i < n_dims; i++ ) { @@ -9990,7 +10442,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor start_new_block(elseBB); } start_new_block(mergeBB); - tmp = LLVM::CreateLoad(*builder, target); + tmp = llvm_utils->CreateLoad(target); } else { int kind = ASRUtils::extract_kind_from_ttype_t(m_type); if( physical_type == ASR::array_physical_typeType::FixedSizeArray ) { @@ -10001,7 +10453,17 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor int ptr_loads_copy = ptr_loads; ptr_loads = 2; for( int i = 0; i < n_dims; i++ ) { - visit_expr_wrapper(m_dims[i].m_length, true); + load_array_size_deep_copy(m_dims[i].m_length); + + // Make dimension length and return size compatible. + if(ASRUtils::extract_kind_from_ttype_t( + ASRUtils::expr_type(m_dims[i].m_length)) > kind){ + tmp = builder->CreateTrunc(tmp, llvm::IntegerType::get(context, 8 * kind)); + } else if (ASRUtils::extract_kind_from_ttype_t( + ASRUtils::expr_type(m_dims[i].m_length)) < kind){ + tmp = builder->CreateSExt(tmp, llvm::IntegerType::get(context, 8 * kind)); + } + llvm_size = builder->CreateMul(tmp, llvm_size); } ptr_loads = ptr_loads_copy; @@ -10029,7 +10491,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor if( x.m_bound == ASR::arrayboundType::LBound ) { bound_value = 1; } else if( x.m_bound == ASR::arrayboundType::UBound ) { - bound_value = array_const->n_args; + bound_value = ASRUtils::get_fixed_size_of_array(array_const->m_type); } else { LCOMPILERS_ASSERT(false); } @@ -10037,24 +10499,28 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor return ; } + ASR::ttype_t* x_mv_type = ASRUtils::expr_type(x.m_v); + llvm::Type* array_type = llvm_utils->get_type_from_ttype_t_util( + ASRUtils::type_get_past_allocatable(ASRUtils::type_get_past_pointer(x_mv_type)), module.get()); int64_t ptr_loads_copy = ptr_loads; ptr_loads = 2 - // Sync: instead of 2 - , should this be ptr_loads_copy - (LLVM::is_llvm_pointer(*ASRUtils::expr_type(x.m_v))); visit_expr_wrapper(x.m_v); ptr_loads = ptr_loads_copy; - bool is_pointer_array = tmp->getType()->getContainedType(0)->isPointerTy(); - if (is_pointer_array) { - tmp = CreateLoad(tmp); + if (is_a(*x.m_v)) { + tmp = llvm_utils->CreateLoad2(array_type->getPointerTo(), tmp); +#if LLVM_VERSION_MAJOR > 16 + ptr_type[tmp] = array_type; +#endif } llvm::Value* llvm_arg1 = tmp; visit_expr_wrapper(x.m_dim, true); llvm::Value* dim_val = tmp; - ASR::ttype_t* x_mv_type = ASRUtils::expr_type(x.m_v); ASR::array_physical_typeType physical_type = ASRUtils::extract_physical_type(x_mv_type); switch( physical_type ) { case ASR::array_physical_typeType::DescriptorArray: { - llvm::Value* dim_des_val = arr_descr->get_pointer_to_dimension_descriptor_array(llvm_arg1); + llvm::Value* dim_des_val = arr_descr->get_pointer_to_dimension_descriptor_array(array_type, llvm_arg1); llvm::Value* const_1 = llvm::ConstantInt::get(context, llvm::APInt(32, 1)); dim_val = builder->CreateSub(dim_val, const_1); llvm::Value* dim_struct = arr_descr->get_pointer_to_dimension_descriptor(dim_des_val, dim_val); @@ -10069,13 +10535,10 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } case ASR::array_physical_typeType::FixedSizeArray: case ASR::array_physical_typeType::PointerToDataArray: { - llvm::BasicBlock &entry_block = builder->GetInsertBlock()->getParent()->getEntryBlock(); - llvm::IRBuilder<> builder0(context); - builder0.SetInsertPoint(&entry_block, entry_block.getFirstInsertionPt()); llvm::Type* target_type = llvm_utils->get_type_from_ttype_t_util( ASRUtils::type_get_past_allocatable( ASRUtils::type_get_past_pointer(x.m_type)), module.get()); - llvm::AllocaInst *target = builder0.CreateAlloca( + llvm::AllocaInst *target = llvm_utils->CreateAlloca( target_type, nullptr, "array_bound"); llvm::BasicBlock *mergeBB = llvm::BasicBlock::Create(context, "ifcont"); ASR::dimension_t* m_dims = nullptr; @@ -10099,7 +10562,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor llvm::Value *lbound = nullptr, *length = nullptr; this->visit_expr_wrapper(m_dims[i].m_start, true); lbound = tmp; - this->visit_expr_wrapper(m_dims[i].m_length, true); + load_array_size_deep_copy(m_dims[i].m_length); length = tmp; builder->CreateStore( builder->CreateSub(builder->CreateAdd(length, lbound), @@ -10112,7 +10575,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor start_new_block(elseBB); } start_new_block(mergeBB); - tmp = LLVM::CreateLoad(*builder, target); + tmp = llvm_utils->CreateLoad2(target_type, target); break; } case ASR::array_physical_typeType::SIMDArray: { @@ -10124,7 +10587,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } break; } - case ASR::array_physical_typeType::CharacterArraySinglePointer: { + case ASR::array_physical_typeType::StringArraySinglePointer: { ASR::dimension_t* m_dims = nullptr; int n_dims = ASRUtils::extract_dimensions_from_ttype(x_mv_type, m_dims); if (ASRUtils::is_dimension_empty(m_dims, n_dims)) { @@ -10142,13 +10605,10 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor tmp = res; break; } else if (ASRUtils::is_fixed_size_array(x_mv_type)) { - llvm::BasicBlock &entry_block = builder->GetInsertBlock()->getParent()->getEntryBlock(); - llvm::IRBuilder<> builder0(context); - builder0.SetInsertPoint(&entry_block, entry_block.getFirstInsertionPt()); llvm::Type* target_type = llvm_utils->get_type_from_ttype_t_util( ASRUtils::type_get_past_allocatable( ASRUtils::type_get_past_pointer(x.m_type)), module.get()); - llvm::AllocaInst *target = builder0.CreateAlloca( + llvm::AllocaInst *target = llvm_utils->CreateAlloca( target_type, nullptr, "array_bound"); llvm::BasicBlock *mergeBB = llvm::BasicBlock::Create(context, "ifcont"); ASR::dimension_t* m_dims = nullptr; @@ -10171,7 +10631,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor llvm::Value *lbound = nullptr, *length = nullptr; this->visit_expr_wrapper(m_dims[i].m_start, true); lbound = tmp; - this->visit_expr_wrapper(m_dims[i].m_length, true); + load_array_size_deep_copy(m_dims[i].m_length); length = tmp; builder->CreateStore( builder->CreateSub(builder->CreateAdd(length, lbound), @@ -10184,7 +10644,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor start_new_block(elseBB); } start_new_block(mergeBB); - tmp = LLVM::CreateLoad(*builder, target); + tmp = llvm_utils->CreateLoad2(target_type, target); break; } else { LCOMPILERS_ASSERT(false); @@ -10203,13 +10663,20 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor // if (fmt_value) ... if (x.m_kind == ASR::string_format_kindType::FormatFortran) { std::vector args; - visit_expr(*x.m_fmt); - args.push_back(tmp); + if(x.m_fmt == nullptr){ // default formatting + llvm::Type* int8Type = builder->getInt8Ty(); + llvm::PointerType* charPtrType = int8Type->getPointerTo(); + llvm::Constant* nullCharPtr = llvm::ConstantPointerNull::get(charPtrType); + args.push_back(nullCharPtr); + } else { + visit_expr(*x.m_fmt); + args.push_back(tmp); + } for (size_t i=0; i fmt; // Use the function to compute the args, but ignore the format - compute_fmt_specifier_and_arg(fmt, args, x.m_args[i], x.base.base.loc); + compute_fmt_specifier_and_arg(fmt, args, x.m_args[i], x.base.base.loc,true); } llvm::Value *args_cnt = llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), args.size() - 1); @@ -10221,18 +10688,17 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } void visit_ArrayBroadcast(const ASR::ArrayBroadcast_t &x) { - get_builder0() this->visit_expr_wrapper(x.m_array, true); llvm::Value *value = tmp; llvm::Type* ele_type = llvm_utils->get_type_from_ttype_t_util( ASRUtils::type_get_past_array(x.m_type), module.get()); size_t n_eles = ASRUtils::get_fixed_size_of_array(x.m_type); llvm::Type* vec_type = FIXED_VECTOR_TYPE::get(ele_type, n_eles); - llvm::AllocaInst *vec = builder0.CreateAlloca(vec_type, nullptr); + llvm::AllocaInst *vec = llvm_utils->CreateAlloca(*builder, vec_type); for (size_t i=0; i < n_eles; i++) { builder->CreateStore(value, llvm_utils->create_gep(vec, i)); } - tmp = CreateLoad(vec); + tmp = llvm_utils->CreateLoad(vec); } }; @@ -10260,7 +10726,6 @@ Result> asr_to_llvm(ASR::TranslationUnit_t &asr, ASRUtils::IntrinsicElementalFunctions::SignFromValue)); co.po.run_fun = run_fn; - co.po.global_underscore = global_underscore; co.po.always_run = false; co.po.skip_optimization_func_instantiation = skip_optimization_func_instantiation; pass_manager.rtlib = co.rtlib; diff --git a/src/libasr/codegen/asr_to_mlir.cpp b/src/libasr/codegen/asr_to_mlir.cpp new file mode 100644 index 0000000000..cd0751bc18 --- /dev/null +++ b/src/libasr/codegen/asr_to_mlir.cpp @@ -0,0 +1,911 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +using LCompilers::ASR::is_a; +using LCompilers::ASR::down_cast; + +namespace LCompilers { + +uint64_t static inline get_hash(ASR::asr_t *node) { + return (uint64_t)node; +} + +// Local exception that is only used in this file to exit the visitor +// pattern and caught later (not propagated outside) +class CodeGenError +{ +public: + diag::Diagnostic d; +public: + CodeGenError(const std::string &msg) + : d{diag::Diagnostic(msg, diag::Level::Error, diag::Stage::CodeGen)} + { } + + CodeGenError(const std::string &msg, const Location &loc) + : d{diag::Diagnostic(msg, diag::Level::Error, diag::Stage::CodeGen, { + diag::Label("", {loc}) + })} + { } +}; + + +class ASRToMLIRVisitor : public ASR::BaseVisitor +{ +public: + Allocator &al; + std::string src; + + std::unique_ptr context; + std::unique_ptr builder; + std::unique_ptr module; + + mlir::Location loc; // UnknownLoc for now + mlir::Value tmp; // Used for temporary returning the value + mlir::LLVM::LLVMPointerType voidPtr; // ptr => void * + + std::map mlir_symtab; // Used for variables + +public: + ASRToMLIRVisitor(Allocator &al) + : al{al}, + context(std::make_unique()), + builder(std::make_unique(context.get())), + loc(builder->getUnknownLoc()) + { + // Load MLIR Dialects + context->getOrLoadDialect(); + context->getOrLoadDialect(); + + // Initialize values + voidPtr = mlir::LLVM::LLVMPointerType::get(context.get()); + } + + /********************************** Utils *********************************/ + mlir::Type getType(ASR::ttype_t *asr_type) { + int kind = ASRUtils::extract_kind_from_ttype_t(asr_type); + switch (asr_type->type) { + case ASR::ttypeType::Integer: { + if (kind == 4) return builder->getI32Type(); + else if (kind == 8) return builder->getI64Type(); + else + throw LCompilersException("Unhandled Integer kind: " + + std::to_string(kind)); + } case ASR::ttypeType::Real: { + if (kind == 4) return builder->getF32Type(); + else if (kind == 8) return builder->getF64Type(); + else + throw LCompilersException("Unhandled Real kind: " + + std::to_string(kind)); + } case ASR::ttypeType::Logical : { + return builder->getI1Type(); + } case ASR::ttypeType::Array: { + ASR::Array_t *arr_type = down_cast(asr_type); + return mlir::LLVM::LLVMArrayType::get(getType(arr_type->m_type), + ASRUtils::get_fixed_size_of_array(asr_type)); + } default: { + throw LCompilersException("Variable type '"+ + ASRUtils::type_to_str_python(asr_type) + + "' is not supported yet"); + } + } + } + + std::string getUniqueName(std::string name = "") { + static int itr = 0; ++itr; + return name + std::to_string(itr); + } + + mlir::Value createGlobalString(std::string value) { + mlir::OpBuilder builder0(module->getBodyRegion()); + mlir::LLVM::LLVMArrayType arrayI8Ty = mlir::LLVM::LLVMArrayType::get( + builder->getI8Type(), value.size()+1); + + llvm::SmallVector vecValue(value.begin(), value.end()); + vecValue.push_back('\0'); + mlir::LLVM::GlobalOp globalStr = builder0.create( + loc, arrayI8Ty, false, mlir::LLVM::Linkage::Private, + getUniqueName("char_const_"), builder0.getStringAttr(vecValue)); + return builder->create(loc, globalStr); + } + + void visit_expr2(ASR::expr_t &x) { + this->visit_expr(x); + if (ASR::is_a(x) || ASR::is_a(x)) { + mlir::Type type = getType(ASRUtils::expr_type(&x)); + tmp = builder->create(loc, type, tmp); + } + } + + /******************************** Visitors ********************************/ + void visit_TranslationUnit(const ASR::TranslationUnit_t &x) { + module = std::make_unique(builder->create(loc, + llvm::StringRef("LFortran"))); + + // Visit all the Functions + for (auto &item : x.m_symtab->get_scope()) { + if (is_a(*item.second)) { + visit_symbol(*item.second); + } + } + // Visit all the Modules + for (auto &item : x.m_symtab->get_scope()) { + if (is_a(*item.second)) { + visit_symbol(*item.second); + } + } + // Finally, visit Program + for (auto &item : x.m_symtab->get_scope()) { + if (is_a(*item.second)) { + visit_symbol(*item.second); + } + } + } + + void visit_Module(const ASR::Module_t &x) { + if (!module) { + module = std::make_unique( + builder->create(loc, + llvm::StringRef("LFortran"))); + } + // Visit all the Functions + for (auto &item : x.m_symtab->get_scope()) { + if (is_a(*item.second)) { + visit_symbol(*item.second); + } + } + } + + void visit_Function(const ASR::Function_t &x) { + ASR::FunctionType_t *fnType = down_cast( + x.m_function_signature); + if (fnType->m_deftype == ASR::deftypeType::Interface) { + // Skip Interface function for now + return; + } + Vec argsType; argsType.reserve(al, fnType->n_arg_types); + // Collect all the arguments type + for (size_t i=0; in_arg_types; i++) { + argsType.push_back(al, voidPtr); + } + mlir::Type returnType; + // Collect the return type + if (fnType->m_return_var_type) { + returnType = getType(fnType->m_return_var_type); + } else { + returnType = mlir::LLVM::LLVMVoidType::get(context.get()); + } + + mlir::LLVM::LLVMFunctionType llvmFnType = mlir::LLVM::LLVMFunctionType::get( + returnType, argsType.as_vector(), false); + mlir::OpBuilder builder0(module->getBodyRegion()); + // Create function + mlir::LLVM::LLVMFuncOp fn = builder0.create( + loc, x.m_name, llvmFnType); + + mlir::Block &entryBlock = *fn.addEntryBlock(*builder); + builder = std::make_unique(mlir::OpBuilder::atBlockBegin( + &entryBlock)); + + // Store all the argument symbols in the mlir_symtab + // Later, this is used in the function's body + for (size_t i=0; iget_scope()) { + if (is_a(*item.second)) { + ASR::Variable_t *v = down_cast(item.second); + if (v->m_intent == ASR::intentType::Local || + v->m_intent == ASR::intentType::ReturnVar) { + visit_symbol(*item.second); + } + } + } + + // Visit the function body + for (size_t i = 0; i < x.n_body; i++) { + visit_stmt(*x.m_body[i]); + } + if (x.m_return_var) { + this->visit_expr2(*x.m_return_var); + builder->create(loc, tmp); + } else { + builder->create(loc, mlir::ValueRange{}); + } + } + + void visit_Program(const ASR::Program_t &x) { + mlir::LLVM::LLVMFunctionType llvmFnType = mlir::LLVM::LLVMFunctionType::get( + builder->getI32Type(), {}, false); + mlir::OpBuilder builder0(module->getBodyRegion()); + mlir::LLVM::LLVMFuncOp function = builder0.create( + loc, "main", llvmFnType); + + // Visit all the Functions + for (auto &item : x.m_symtab->get_scope()) { + if (is_a(*item.second)) { + visit_symbol(*item.second); + } + } + + mlir::Block &entryBlock = *function.addEntryBlock(*builder); + builder = std::make_unique(mlir::OpBuilder::atBlockBegin( + &entryBlock)); + + // Visit all the Variables + for (auto &item : x.m_symtab->get_scope()) { + if (is_a(*item.second)) { + visit_symbol(*item.second); + } + } + + for (size_t i = 0; i < x.n_body; i++) { + visit_stmt(*x.m_body[i]); + } + + mlir::LLVM::ConstantOp zero = builder->create( + loc, builder->getI32Type(), builder->getI32IntegerAttr(0)); + builder->create(loc, zero.getResult()); + } + + void visit_Variable(const ASR::Variable_t &x) { + uint32_t h = get_hash((ASR::asr_t*) &x); + mlir::Value size = builder->create(loc, + builder->getI32Type(), builder->getI64IntegerAttr(1)); + mlir_symtab[h] = builder->create(loc, + voidPtr, getType(x.m_type), size); + if (x.m_symbolic_value) { + this->visit_expr2(*x.m_symbolic_value); + builder->create(loc, tmp, mlir_symtab[h]); + } + } + + void visit_Var(const ASR::Var_t &x) { + ASR::Variable_t *v = ASRUtils::EXPR2VAR(&x.base); + uint32_t h = get_hash((ASR::asr_t*) v); + if (mlir_symtab.find(h) != mlir_symtab.end()) { + tmp = mlir_symtab[h]; + } else { + throw CodeGenError("Symbol '"+ + std::string(v->m_name) + +"' not found", x.base.base.loc); + } + } + + template + void visit_Call(const T &x) { + Vec args; args.reserve(al, x.n_args); + Vec argTypes; argTypes.reserve(al, x.n_args); + for (size_t i=0; ivisit_expr(*x.m_args[i].m_value); + if (!is_a(*ASRUtils::get_past_array_physical_cast( + x.m_args[i].m_value))) { + // Constant, BinOp, etc would have the type i32, but not i32* + // So, We create an `alloca` here, store the value and + // then, pass the alloca as an argument + mlir::Type argType = getType(ASRUtils::extract_type( + ASRUtils::expr_type(x.m_args[i].m_value))); + mlir::Value size = builder->create(loc, + builder->getI32Type(), builder->getI64IntegerAttr(1)); + mlir::Value alloca = builder->create( + loc, voidPtr, argType, size); + builder->create(loc, tmp, alloca); + args.push_back(al, alloca); + } else { + args.push_back(al, tmp); + } + argTypes.push_back(al, voidPtr); + } + mlir::LLVM::LLVMFuncOp fn = module->lookupSymbol( + ASRUtils::symbol_name(x.m_name)); + if (!fn) { + // Add function declaration + ASR::FunctionType_t *fnType = down_cast( + down_cast(x.m_name)->m_function_signature); + mlir::Type returnType; + if (fnType->m_return_var_type) { + returnType = getType(fnType->m_return_var_type); + } else { + returnType = mlir::LLVM::LLVMVoidType::get(context.get()); + } + + mlir::LLVM::LLVMFunctionType llvmFnType = mlir::LLVM::LLVMFunctionType::get( + returnType, argTypes.as_vector(), false); + mlir::OpBuilder builder0(module->getBodyRegion()); + fn = builder0.create(loc, + ASRUtils::symbol_name(x.m_name), llvmFnType); + } + tmp = builder->create(loc, fn, + args.as_vector()).getResult(); + } + + void visit_SubroutineCall(const ASR::SubroutineCall_t &x) { + visit_Call(x); + } + + void visit_FunctionCall(const ASR::FunctionCall_t &x) { + visit_Call(x); + } + + void visit_Assignment(const ASR::Assignment_t &x) { + this->visit_expr(*x.m_target); + mlir::Value target = tmp; + this->visit_expr2(*x.m_value); + mlir::Value value = tmp; + builder->create(loc, value, target); + } + + void visit_IntegerConstant(const ASR::IntegerConstant_t &x) { + int kind = ASRUtils::extract_kind_from_ttype_t(x.m_type); + mlir::Type type; mlir::IntegerAttr attr; + switch (kind) { + case 4: { + type = builder->getI32Type(); + attr = builder->getI32IntegerAttr(x.m_n); + break; + } case 8: { + type = builder->getI64Type(); + attr = builder->getI64IntegerAttr(x.m_n); + break; + } + default: + throw CodeGenError("Integer constant of kind: `"+ + std::to_string(kind) +"` is not supported yet", + x.base.base.loc); + } + tmp = builder->create(loc, + type, attr).getResult(); + } + + void visit_IntegerUnaryMinus(const ASR::IntegerUnaryMinus_t &x) { + mlir::Type type = getType(x.m_type); + int unaryMinus = 0; + if (ASRUtils::extract_value(x.m_value, unaryMinus)) { + mlir::IntegerAttr attr = builder->getIntegerAttr(type, unaryMinus); + tmp = builder->create(loc, + type, attr).getResult(); + } else { + mlir::IntegerAttr attr = builder->getIntegerAttr(type, unaryMinus); + mlir::Value zero = builder->create(loc, + type, attr); + this->visit_expr2(*x.m_arg); + tmp = builder->create(loc, zero, tmp); + } + } + + void visit_RealConstant(const ASR::RealConstant_t &x) { + int kind = ASRUtils::extract_kind_from_ttype_t(x.m_type); + mlir::Type type; mlir::FloatAttr attr; + switch (kind) { + case 4: { + type = builder->getF32Type(); + attr = builder->getF32FloatAttr(x.m_r); + break; + } case 8: { + type = builder->getF64Type(); + attr = builder->getF64FloatAttr(x.m_r); + break; + } + default: + throw CodeGenError("Integer constant of kind: `"+ + std::to_string(kind) +"` is not supported yet", + x.base.base.loc); + } + tmp = builder->create(loc, + type, attr).getResult(); + } + + void visit_RealUnaryMinus(const ASR::RealUnaryMinus_t &x) { + mlir::Type type = getType(x.m_type); + double unaryMinus = 0.0; + if (ASRUtils::extract_value(x.m_value, unaryMinus)) { + mlir::FloatAttr attr = builder->getFloatAttr(type, unaryMinus); + tmp = builder->create(loc, + type, attr).getResult(); + } else { + mlir::FloatAttr attr = builder->getFloatAttr(type, unaryMinus); + mlir::Value zero = builder->create(loc, + type, attr); + this->visit_expr2(*x.m_arg); + tmp = builder->create(loc, zero, tmp); + } + } + + void visit_Cast(const ASR::Cast_t &x) { + this->visit_expr2(*x.m_arg); + int kind = ASRUtils::extract_kind_from_ttype_t(x.m_type); + switch (x.m_kind) { + case (ASR::cast_kindType::IntegerToReal): { + mlir::Type type; + switch (kind) { + case 4: { + type = builder->getF32Type(); break; + } case 8: { + type = builder->getF64Type(); break; + } + default: + throw CodeGenError("Integer constant of kind: `"+ + std::to_string(kind) +"` is not supported yet", + x.base.base.loc); + } + tmp = builder->create(loc, type, tmp); + break; + } default: { + throw CodeGenError("Cast of kind: `"+ + std::to_string(x.m_kind) +"` is not supported yet", + x.base.base.loc); + } + } + } + + void visit_StringConstant(const ASR::StringConstant_t &x) { + tmp = createGlobalString(x.m_s); + } + + void visit_ArrayPhysicalCast(const ASR::ArrayPhysicalCast_t &x) { + this->visit_expr(*x.m_arg); + switch (x.m_old) { + case (ASR::array_physical_typeType::FixedSizeArray): { + if (x.m_new == ASR::array_physical_typeType::PointerToDataArray) { + mlir::Value zero = builder->create(loc, + builder->getI64Type(), builder->getIndexAttr(0)); + mlir::Type type = getType(x.m_type); + tmp = builder->create(loc, voidPtr, type, + tmp, mlir::ValueRange{zero, zero}); + } else { + throw CodeGenError("ArrayPhysicalCast to of kind: `"+ + std::to_string(x.m_old) +"` is not supported yet", + x.base.base.loc); + } + break; + } default: { + throw CodeGenError("ArrayPhysicalCast from of kind: `"+ + std::to_string(x.m_old) +"` is not supported yet", + x.base.base.loc); + } + } + } + + void visit_ArrayBound(const ASR::ArrayBound_t &x) { + int bound_value = -1; + ASR::ttype_t *arr_type = ASRUtils::expr_type(x.m_v); + if (is_a(*arr_type)) { + ASR::Array_t *arr = down_cast(arr_type); + int dim = -1; + if (ASRUtils::extract_value(x.m_dim, dim)) { + if (x.m_bound == ASR::arrayboundType::LBound) { + ASRUtils::extract_value(arr->m_dims[dim-1].m_start, + bound_value); + } else { + ASRUtils::extract_value(arr->m_dims[dim-1].m_length, + bound_value); + } + } else { + throw CodeGenError("Runtime `dim` in ArrayBound is not " + "supported yet", x.base.base.loc); + } + } else { + throw CodeGenError("The type `"+ + ASRUtils::type_to_str_python(arr_type) + +"` is not supported yet", x.base.base.loc); + } + tmp = builder->create(loc, + builder->getI32Type(), + builder->getI32IntegerAttr(bound_value)).getResult(); + } + + void visit_IntegerBinOp(const ASR::IntegerBinOp_t &x) { + this->visit_expr2(*x.m_left); + mlir::Value left = tmp; + this->visit_expr2(*x.m_right); + mlir::Value right = tmp; + switch (x.m_op) { + case ASR::binopType::Add: { + tmp = builder->create(loc, left, right); + break; + } case ASR::binopType::Sub: { + tmp = builder->create(loc, left, right); + break; + } case ASR::binopType::Mul: { + tmp = builder->create(loc, left, right); + break; + } case ASR::binopType::Div: { + tmp = builder->create(loc, left, right); + break; + } + default: + throw CodeGenError("BinOp operator not supported yet", + x.base.base.loc); + } + } + + void visit_RealBinOp(const ASR::RealBinOp_t &x) { + this->visit_expr2(*x.m_left); + mlir::Value left = tmp; + this->visit_expr2(*x.m_right); + mlir::Value right = tmp; + switch (x.m_op) { + case ASR::binopType::Add: { + tmp = builder->create(loc, left, right); + break; + } case ASR::binopType::Sub: { + tmp = builder->create(loc, left, right); + break; + } case ASR::binopType::Mul: { + tmp = builder->create(loc, left, right); + break; + } case ASR::binopType::Div: { + tmp = builder->create(loc, left, right); + break; + } + default: + throw CodeGenError("BinOp operator not supported yet", + x.base.base.loc); + } + } + + void visit_IntegerCompare(const ASR::IntegerCompare_t &x) { + this->visit_expr2(*x.m_left); + mlir::Value left = tmp; + this->visit_expr2(*x.m_right); + mlir::Value right = tmp; + mlir::LLVM::ICmpPredicate op; + switch (x.m_op) { + case ASR::cmpopType::Eq: { + op = mlir::LLVM::ICmpPredicate::eq; break; + } case ASR::cmpopType::Lt: { + op = mlir::LLVM::ICmpPredicate::slt; break; + } case ASR::cmpopType::LtE: { + op = mlir::LLVM::ICmpPredicate::sle; break; + } case ASR::cmpopType::Gt: { + op = mlir::LLVM::ICmpPredicate::sgt; break; + } case ASR::cmpopType::GtE: { + op = mlir::LLVM::ICmpPredicate::sge; break; + } case ASR::cmpopType::NotEq: { + op = mlir::LLVM::ICmpPredicate::ne; break; + } + default: + throw CodeGenError("Compare operator not supported yet", + x.base.base.loc); + } + tmp = builder->create(loc, op, left, right); + } + + void visit_RealCompare(const ASR::RealCompare_t &x) { + this->visit_expr2(*x.m_left); + mlir::Value left = tmp; + this->visit_expr2(*x.m_right); + mlir::Value right = tmp; + mlir::LLVM::FCmpPredicate op; + switch (x.m_op) { + case ASR::cmpopType::Eq: { + op = mlir::LLVM::FCmpPredicate::oeq; break; + } case ASR::cmpopType::Lt: { + op = mlir::LLVM::FCmpPredicate::olt; break; + } case ASR::cmpopType::LtE: { + op = mlir::LLVM::FCmpPredicate::ole; break; + } case ASR::cmpopType::Gt: { + op = mlir::LLVM::FCmpPredicate::ogt; break; + } case ASR::cmpopType::GtE: { + op = mlir::LLVM::FCmpPredicate::oge; break; + } case ASR::cmpopType::NotEq: { + op = mlir::LLVM::FCmpPredicate::one; break; + } + default: + throw CodeGenError("Compare operator not supported yet", + x.base.base.loc); + } + tmp = builder->create(loc, getType(x.m_type), + op, left, right); + } + + void visit_ArrayItem(const ASR::ArrayItem_t &x) { + this->visit_expr(*x.m_v); + mlir::Value m_v = tmp; + + LCOMPILERS_ASSERT(x.n_args == 1); + this->visit_expr2(*x.m_args[0].m_right); + mlir::Value idx = tmp; + + if (ASRUtils::extract_kind_from_ttype_t(ASRUtils::expr_type( + x.m_args[0].m_right)) != 8) { + idx = builder->create(loc, + builder->getI64Type(), idx); + } + mlir::LLVM::ConstantOp one = builder->create(loc, + builder->getI64Type(), builder->getIndexAttr(1)); + + idx = builder->create(loc, idx, one); + mlir::Type baseType; + mlir::ValueRange gepIdx; + if (ASRUtils::extract_physical_type(ASRUtils::expr_type(x.m_v)) + == ASR::array_physical_typeType::PointerToDataArray) { + gepIdx = {idx}; + baseType = getType(x.m_type); + } else { + mlir::Value zero = builder->create(loc, + builder->getI64Type(), builder->getIndexAttr(0)); + gepIdx = {zero, idx}; + baseType = getType(ASRUtils::expr_type(x.m_v)); + } + tmp = builder->create(loc, voidPtr, + baseType, m_v, gepIdx); + + } + + void visit_If(const ASR::If_t &x) { + this->visit_expr(*x.m_test); + mlir::Value test = tmp; + + mlir::Block *thisBlock = builder->getBlock(); + mlir::Block *thenBlock = builder->createBlock(thisBlock->getParent()); + mlir::Block *elseBlock = builder->createBlock(thisBlock->getParent()); + mlir::Block *contBlock = builder->createBlock(thisBlock->getParent()); + + builder->setInsertionPointToEnd(thisBlock); + builder->create(loc, test, thenBlock, elseBlock); + builder->setInsertionPointToStart(thenBlock); + for (size_t i=0; ivisit_stmt(*x.m_body[i]); + } + if (!(!thenBlock->empty() && + mlir::isa(thenBlock->back()))) { + builder->create(loc, mlir::ValueRange{}, contBlock); + } + + builder->setInsertionPointToStart(elseBlock); + for (size_t i=0; ivisit_stmt(*x.m_orelse[i]); + } + if (!(!elseBlock->empty() && + mlir::isa(elseBlock->back()))) { + builder->create(loc, mlir::ValueRange{}, contBlock); + } + + builder->setInsertionPointToStart(contBlock); + } + + void visit_WhileLoop(const ASR::WhileLoop_t &x) { + mlir::Block *thisBlock = builder->getBlock(); + mlir::Block *headBlock = builder->createBlock(thisBlock->getParent()); + mlir::Block *bodyBlock = builder->createBlock(thisBlock->getParent()); + mlir::Block *contBlock = builder->createBlock(thisBlock->getParent()); + + builder->setInsertionPointToEnd(thisBlock); + builder->create(loc, mlir::ValueRange{}, headBlock); + + builder->setInsertionPointToStart(headBlock); + this->visit_expr(*x.m_test); + builder->create(loc, tmp, bodyBlock, contBlock); + + builder->setInsertionPointToStart(bodyBlock); + for (size_t i=0; ivisit_stmt(*x.m_body[i]); + } + builder->create(loc, mlir::ValueRange{}, headBlock); + + builder->setInsertionPointToStart(contBlock); + } + + void visit_DoConcurrentLoop(const ASR::DoConcurrentLoop_t &x) { + // + // The following source code: + // + // do concurrent (i = 1: 10) + // x(i) = i + // end do + // + // becomes: + // + // %i = llvm.alloca %0 x i32 : (i32) -> !llvm.ptr + // omp.parallel { + // %c1 = llvm.mlir.constant(1 : index) : i32 + // %c10 = llvm.mlir.constant(10 : index) : i32 + // %1 = llvm.add %c10, %c1 : i32 + // omp.wsloop { + // omp.loop_nest(%arg0) : i32 = (%c1) to (%1) inclusive step (%c1) { + // llvm.store %arg0, %i : !llvm.ptr + // [...] // x(i) = i + // omp.yield + // } + // omp.terminator + // } + // omp.terminator + // } + mlir::OpBuilder::InsertionGuard ipGuard(*builder); + + mlir::omp::ParallelOp pOp{builder->create(loc)}; + mlir::Block *pOpBlock{builder->createBlock(&pOp.getRegion())}; + builder->setInsertionPointToStart(pOpBlock); + + this->visit_expr2(*x.m_head->m_start); + mlir::Value lowerBound{tmp}; + + this->visit_expr2(*x.m_head->m_end); + mlir::Value upperBound{tmp}; + mlir::Value step{}; + + if (x.m_head->m_increment) { + this->visit_expr2(*x.m_head->m_increment); + step = tmp; + } else { + mlir::Type type{getType(ASRUtils::expr_type(x.m_head->m_v))}; + mlir::Value one = builder->create( + loc, type, builder->getIndexAttr(1)).getResult(); + step = one; + } + + mlir::omp::WsloopOp wslOp{builder->create(loc)}; + builder->create(loc); + + mlir::Block *wslOpBlock{builder->createBlock(&wslOp.getRegion())}; + builder->setInsertionPointToStart(wslOpBlock); + + mlir::omp::LoopNestOp lnOp{builder->create(loc, + lowerBound, upperBound, step, true)}; + builder->create(loc); + mlir::Block *lnOpBlock{builder->createBlock(&lnOp.getRegion())}; + builder->setInsertionPointToStart(lnOpBlock); + + lnOpBlock->addArgument(getType(ASRUtils::expr_type(x.m_head->m_v)), loc); + this->visit_expr(*x.m_head->m_v); + builder->create(loc, lnOpBlock->getArgument(0), tmp); + + for (size_t i=0; ivisit_stmt(*x.m_body[i]); + } + builder->create(loc); + } + + void visit_ErrorStop(const ASR::ErrorStop_t &) { + mlir::OpBuilder builder0(module->getBodyRegion()); + mlir::LLVM::LLVMFuncOp printf_fn = + module->lookupSymbol("printf"); + if (!printf_fn) { + mlir::LLVM::LLVMVoidType voidTy = + mlir::LLVM::LLVMVoidType::get(context.get()); + mlir::LLVM::LLVMFunctionType llvmFnType = + mlir::LLVM::LLVMFunctionType::get(voidTy, voidPtr, true); + printf_fn = builder0.create( + loc, "printf", llvmFnType); + } + mlir::Value zero = builder->create(loc, + builder->getI64Type(), builder->getIndexAttr(0)); + tmp = builder->create(loc, voidPtr, voidPtr, + createGlobalString("ERROR STOP\n"), zero); + builder->create(loc, printf_fn, tmp); + + mlir::LLVM::LLVMFuncOp exit_fn = + module->lookupSymbol("exit"); + if (!exit_fn) { + mlir::LLVM::LLVMVoidType voidTy = + mlir::LLVM::LLVMVoidType::get(context.get()); + mlir::LLVM::LLVMFunctionType llvmFnType = + mlir::LLVM::LLVMFunctionType::get(voidTy, builder->getI32Type()); + exit_fn = builder0.create( + loc, "exit", llvmFnType); + } + mlir::LLVM::ConstantOp one = builder->create( + loc, builder->getI32Type(), builder->getI32IntegerAttr(1)); + builder->create(loc, exit_fn, one.getResult()); + + builder->create(loc); + } + + void handle_Print(const Location &l, ASR::expr_t *x) { + std::string fmt = ""; + Vec args; + if (ASR::is_a(*x)) { + ASR::StringFormat_t *sf = ASR::down_cast(x); + args.reserve(al, sf->n_args+1); + args.push_back(al, nullptr); // Later used by `printf_fmt` + for (size_t i=0; in_args; i++) { + ASR::ttype_t *t = ASRUtils::expr_type(sf->m_args[i]); + this->visit_expr2(*sf->m_args[i]); + if (ASRUtils::is_integer(*t)) { + fmt += " %d"; + } else if (ASRUtils::is_real(*t)) { + tmp = builder->create(loc, + builder->getF64Type(), tmp); + fmt += " %f"; + } else if (ASRUtils::is_character(*t)) { + fmt += " %s"; + } else { + throw CodeGenError("Unhandled type in print statement", l); + } + args.push_back(al, tmp); + } + } else if (ASRUtils::is_character(*ASRUtils::expr_type(x))) { + this->visit_expr(*x); + args.reserve(al, 2); + args.push_back(al, nullptr); // Later used by `printf_fmt` + args.push_back(al, tmp); + fmt += " %s"; + } else { + throw CodeGenError("Unsupported expression as formatter in print", l); + } + fmt += "\n"; + + mlir::OpBuilder builder0(module->getBodyRegion()); + mlir::LLVM::LLVMFuncOp printf_fn = + module->lookupSymbol("printf"); + if (!printf_fn) { + mlir::LLVM::LLVMVoidType voidTy = + mlir::LLVM::LLVMVoidType::get(context.get()); + mlir::LLVM::LLVMFunctionType llvmFnType = + mlir::LLVM::LLVMFunctionType::get(voidTy, voidPtr, true); + printf_fn = builder0.create( + loc, "printf", llvmFnType); + } + mlir::Value zero = builder->create(loc, + builder->getI64Type(), builder->getIndexAttr(0)); + args.p[0] = builder->create(loc, + voidPtr, voidPtr, createGlobalString(fmt), zero); + builder->create(loc, printf_fn, + mlir::ValueRange{args.as_vector()}); + } + + void visit_Print(const ASR::Print_t &x) { + handle_Print(x.base.base.loc, x.m_text); + } + + void visit_FileWrite(const ASR::FileWrite_t &x) { + if (!x.m_unit) { + LCOMPILERS_ASSERT(x.n_values == 1); + handle_Print(x.base.base.loc, x.m_values[0]); + } else { + throw CodeGenError("Only write(*, *) [...] is implemented for now", + x.base.base.loc); + } + } + +}; + +Result> asr_to_mlir(Allocator &al, + ASR::asr_t &asr, diag::Diagnostics &diagnostics) { + if ( !(ASR::is_a(asr) || + (ASR::is_a((ASR::symbol_t &)asr))) ) { + diagnostics.diagnostics.push_back(diag::Diagnostic("Unhandled type " + "passed as argument: 'asr' to asr_to_mlir(...)", + diag::Level::Error, diag::Stage::CodeGen)); + Error error; return error; + } + ASRToMLIRVisitor v(al); + try { + v.visit_asr(asr); + } catch (const CodeGenError &e) { + diagnostics.diagnostics.push_back(e.d); + return Error(); + } + + mlir::registerBuiltinDialectTranslation(*v.context); + mlir::registerLLVMDialectTranslation(*v.context); + mlir::registerOpenMPDialectTranslation(*v.context); + + if (mlir::failed(mlir::verify(*v.module))) { + std::string mlir_str; + llvm::raw_string_ostream raw_os(mlir_str); + v.module->print(raw_os); + std::cout << "\n" << mlir_str << "\n"; + std::string msg = "asr_to_mlir: module verification failed"; + diagnostics.diagnostics.push_back(diag::Diagnostic(msg, + diag::Level::Error, diag::Stage::CodeGen)); + Error error; + return error; + } + return std::make_unique(std::move(v.module), std::move(v.context)); +} + +} // namespace LCompilers diff --git a/src/libasr/codegen/asr_to_mlir.h b/src/libasr/codegen/asr_to_mlir.h new file mode 100644 index 0000000000..0bad787b8f --- /dev/null +++ b/src/libasr/codegen/asr_to_mlir.h @@ -0,0 +1,15 @@ +#ifndef LFORTRAN_ASR_TO_MLIR_H +#define LFORTRAN_ASR_TO_MLIR_H + +#include +#include +#include + +namespace LCompilers { + + Result> asr_to_mlir(Allocator &al, + ASR::asr_t &asr, diag::Diagnostics &diagnostics); + +} // namespace LCompilers + +#endif // LFORTRAN_ASR_TO_MLIR_H diff --git a/src/libasr/codegen/asr_to_py.cpp b/src/libasr/codegen/asr_to_py.cpp index cc8daaf37d..d50a24507e 100644 --- a/src/libasr/codegen/asr_to_py.cpp +++ b/src/libasr/codegen/asr_to_py.cpp @@ -1,5 +1,3 @@ -#include -#include #include #include #include @@ -44,7 +42,7 @@ _X(ASR::Complex_t, 8, "double _Complex" ) \ \ _X(ASR::Logical_t, 1, "_Bool" ) \ - _X(ASR::Character_t, 1, "char" ) + _X(ASR::String_t, 1, "char" ) /* @@ -86,7 +84,7 @@ _X(ASR::Complex_t, "c_long_double_complex", "long double _Complex" ) \ \ _X(ASR::Logical_t, "c_bool", "_Bool" ) \ - _X(ASR::Character_t, "c_char", "char" ) + _X(ASR::String_t, "c_char", "char" ) */ namespace LCompilers { diff --git a/src/libasr/codegen/asr_to_python.cpp b/src/libasr/codegen/asr_to_python.cpp index 7f361f8aa6..a5a660574e 100644 --- a/src/libasr/codegen/asr_to_python.cpp +++ b/src/libasr/codegen/asr_to_python.cpp @@ -129,6 +129,35 @@ class ASRToLpythonVisitor : public ASR::BaseVisitor } } + std::string get_type(const ASR::ttype_t *t) { + std::string r = ""; + switch (t->type) { + case ASR::ttypeType::Integer : { + r += "i"; + r += std::to_string(ASRUtils::extract_kind_from_ttype_t(t)*8); + break; + } case ASR::ttypeType::Real : { + r += "f"; + r += std::to_string(ASRUtils::extract_kind_from_ttype_t(t)*8); + break; + } case ASR::ttypeType::Complex : { + r += "c"; + r += std::to_string(ASRUtils::extract_kind_from_ttype_t(t)*8); + break; + } case ASR::ttypeType::String : { + r = "str"; + break; + } case ASR::ttypeType::Logical : { + r = "bool"; + break; + } default : { + throw LCompilersException("The type `" + + ASRUtils::type_to_str_python(t) + "` is not handled yet"); + } + } + return r; + } + void visit_TranslationUnit(const ASR::TranslationUnit_t &x) { std::string r = ""; @@ -216,7 +245,7 @@ class ASRToLpythonVisitor : public ASR::BaseVisitor std::string r = indent; r += x.m_name; r += ": "; - r += ASRUtils::type_to_str_python(x.m_type); + r += get_type(x.m_type); r += "\n"; s = r; } @@ -224,11 +253,20 @@ class ASRToLpythonVisitor : public ASR::BaseVisitor void visit_Print(const ASR::Print_t &x) { std::string r = indent; r += "print("; - for (size_t i = 0; i < x.n_values; i++) { - visit_expr(*x.m_values[i]); + if (ASR::is_a(*x.m_text)) { + ASR::StringFormat_t str_fmt = *ASR::down_cast(x.m_text); + for (size_t i = 0; i < str_fmt.n_args; i++) { + visit_expr(*str_fmt.m_args[i]); + r += s; + if (i < str_fmt.n_args-1) + r += ", "; + } + } else if (ASR::is_a(*ASRUtils::expr_type(x.m_text))){ + visit_expr(*x.m_text); r += s; - if (i < x.n_values-1) - r += ", "; + } else { + throw CodeGenError("print statment supported for stringformat and single character argument", + x.base.base.loc); } r += ")"; r += "\n"; @@ -590,102 +628,6 @@ class ASRToLpythonVisitor : public ASR::BaseVisitor s = r; } - void visit_DictConstant(const ASR::DictConstant_t &x) { - LCOMPILERS_ASSERT(x.n_keys == x.n_values); - std::string r = ""; - r += "{"; - for (size_t i = 0; i < x.n_keys; i++) { - visit_expr(*x.m_keys[i]); - r += s; - r += ": "; - visit_expr(*x.m_values[i]); - r += s; - if (i < x.n_keys - 1) { - r += ", "; - } - } - r += "}"; - - s = r; - } - - // An aggregate visitor for `ListConstant`, `TupleConstant` & `SetConstant` - void visit_AggregateConstant(size_t n_args, ASR::expr_t** m_args, - std::string opening_braces, std::string closing_braces) { - std::string r = ""; - r += opening_braces; - for (size_t i = 0; i < n_args; i++) { - this->visit_expr(*m_args[i]); - r.append(s); - if (i < n_args - 1) { - r.append(", "); - } - } - r += closing_braces; - s = r; - } - - void visit_ListConstant(const ASR::ListConstant_t &x) { - visit_AggregateConstant(x.n_args, x.m_args, "[", "]"); - } - - void visit_TupleConstant(const ASR::TupleConstant_t &x) { - visit_AggregateConstant(x.n_elements, x.m_elements, "(", ")"); - } - - void visit_SetConstant(const ASR::SetConstant_t &x) { - visit_AggregateConstant(x.n_elements, x.m_elements, "{", "}"); - } - - // An aggregate visitor for list methods with 0 or 1 argument - void visit_UnaryListMethods(ASR::expr_t* list, std::string method_name, - ASR::expr_t* arg=nullptr, bool has_return_value=false) { - std::string r = ""; - visit_expr(*list); - r += s; - r += "." + method_name + "("; - if (arg != nullptr) { - visit_expr(*arg); - r += s; - } - r += ")"; - if (!has_return_value) { - r = indent + r + "\n"; - } - - s = r; - } - - void visit_ListAppend(const ASR::ListAppend_t &x) { - visit_UnaryListMethods(x.m_a, "append", x.m_ele); - } - - void visit_ListCount(const ASR::ListCount_t &x) { - visit_UnaryListMethods(x.m_arg, "count", x.m_ele, true); - } - - void visit_ListRemove(const ASR::ListRemove_t &x) { - visit_UnaryListMethods(x.m_a, "remove", x.m_ele); - } - - void visit_ListClear(const ASR::ListClear_t &x) { - visit_UnaryListMethods(x.m_a, "clear"); - } - - void visit_ListInsert(const ASR::ListInsert_t &x) { - std::string r = indent; - visit_expr(*x.m_a); - r += s; - r += ".insert("; - visit_expr(*x.m_pos); - r += s + ", "; - visit_expr(*x.m_ele); - r += s; - r += ")\n"; - - s = r; - } - }; Result asr_to_python(Allocator& al, ASR::TranslationUnit_t &asr, diff --git a/src/libasr/codegen/asr_to_wasm.cpp b/src/libasr/codegen/asr_to_wasm.cpp index 10562629b0..002d2baf48 100644 --- a/src/libasr/codegen/asr_to_wasm.cpp +++ b/src/libasr/codegen/asr_to_wasm.cpp @@ -1,8 +1,6 @@ #include -#include #include #include -#include #include #include @@ -691,7 +689,7 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { } break; } - case ASR::ttypeType::Character: { + case ASR::ttypeType::String: { std::string init_val = ""; if (v->m_value) { init_val = ASR::down_cast(v->m_value)->m_s; @@ -701,13 +699,13 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { case 1: global_var_idx = m_wa.declare_global_var(i32, m_string_to_iov_loc_map[init_val]); break; - default: throw CodeGenError("Declare Global: Unsupported Character kind"); + default: throw CodeGenError("Declare Global: Unsupported String kind"); } break; } default: { diag.codegen_warning_label("Declare Global: Type " - + ASRUtils::type_to_str(v_m_type) + " not yet supported", {v->base.base.loc}, ""); + + ASRUtils::type_to_str_fortran(v_m_type) + " not yet supported", {v->base.base.loc}, ""); global_var_idx = m_wa.declare_global_var(i32, 0); } } @@ -872,8 +870,8 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { "Integers of kind 4 and 8 only supported"); } } else { - diag.codegen_error_label("Type number '" + - std::to_string(v->m_type->type) + + diag.codegen_error_label("Type '" + + ASRUtils::type_to_str_python(v->m_type) + "' not supported", {v->base.base.loc}, ""); throw CodeGenAbort(); @@ -927,21 +925,21 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { } } } else if (ASRUtils::is_character(*ttype)) { - ASR::Character_t *v_int = - ASR::down_cast( + ASR::String_t *v_int = + ASR::down_cast( ASRUtils::type_get_past_array(ttype)); if (is_array) { type_vec.push_back(i32); } else { if (v_int->m_kind == 1) { - /* Character is stored as string in memory. + /* String is stored as string in memory. The variable points to this location in memory */ type_vec.push_back(i32); } else { throw CodeGenError( - "Characters of kind 1 only supported"); + "Strings of kind 1 only supported"); } } } else if (ASRUtils::is_complex(*ttype)) { @@ -965,7 +963,7 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { } } else { diag.codegen_warning_label("Unsupported variable type: " + - ASRUtils::type_to_str(v->m_type), {v->base.base.loc}, + ASRUtils::type_to_str_fortran(v->m_type), {v->base.base.loc}, "Only integer, floats, logical and complex supported currently"); type_vec.push_back(i32); } @@ -1204,6 +1202,107 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { } } + uint32_t emit_memory_store(ASR::ttype_t* type) { + auto ttype = ASRUtils::type_get_past_array(type); + auto kind = ASRUtils::extract_kind_from_ttype_t(ttype); + switch (ttype->type) { + case ASR::ttypeType::Integer: { + switch (kind) { + case 4: + m_wa.emit_i32_store(wasm::mem_align::b8, 0); + break; + case 8: + m_wa.emit_i64_store(wasm::mem_align::b8, 0); + break; + default: + throw CodeGenError( + "MemoryStore: Unsupported Integer kind"); + } + break; + } + case ASR::ttypeType::Real: { + switch (kind) { + case 4: + m_wa.emit_f32_store(wasm::mem_align::b8, 0); + break; + case 8: + m_wa.emit_f64_store(wasm::mem_align::b8, 0); + break; + default: + throw CodeGenError( + "MemoryStore: Unsupported Real kind"); + } + break; + } + case ASR::ttypeType::Logical: { + switch (kind) { + case 4: + m_wa.emit_i32_store(wasm::mem_align::b8, 0); + break; + default: + throw CodeGenError( + "MemoryStore: Unsupported Logical kind"); + } + break; + } + case ASR::ttypeType::String: { + switch (kind) { + case 4: + m_wa.emit_i32_store(wasm::mem_align::b8, 0); + break; + case 8: + m_wa.emit_i64_store(wasm::mem_align::b8, 0); + break; + default: + throw CodeGenError( + "MemoryStore: Unsupported String kind"); + } + break; + } + case ASR::ttypeType::Complex: { + switch (kind) { + case 4: + m_wa.emit_global_set(m_compiler_globals[tmp_reg_f32]); // complex part + m_wa.emit_global_set(m_compiler_globals[tmp_reg2_f32]); // real part + m_wa.emit_global_set(m_compiler_globals[tmp_reg_i32]); // location + + m_wa.emit_global_get(m_compiler_globals[tmp_reg_i32]); // location + m_wa.emit_global_get(m_compiler_globals[tmp_reg2_f32]); // real part + m_wa.emit_f32_store(wasm::mem_align::b8, 0); + + m_wa.emit_global_get(m_compiler_globals[tmp_reg_i32]); // location + m_wa.emit_global_get(m_compiler_globals[tmp_reg_f32]); // complex part + m_wa.emit_f32_store(wasm::mem_align::b8, kind); + break; + case 8: + m_wa.emit_global_set(m_compiler_globals[tmp_reg_f64]); // complex part + m_wa.emit_global_set(m_compiler_globals[tmp_reg2_f64]); // real part + m_wa.emit_global_set(m_compiler_globals[tmp_reg_i32]); // location + + m_wa.emit_global_get(m_compiler_globals[tmp_reg_i32]); // location + m_wa.emit_global_get(m_compiler_globals[tmp_reg2_f64]); // real part + m_wa.emit_f64_store(wasm::mem_align::b8, 0); + + m_wa.emit_global_get(m_compiler_globals[tmp_reg_i32]); // location + m_wa.emit_global_get(m_compiler_globals[tmp_reg_f64]); // complex part + m_wa.emit_f64_store(wasm::mem_align::b8, kind); + break; + default: + throw CodeGenError( + "MemoryStore: Unsupported Complex kind"); + } + kind *= 2; + break; + } + default: { + throw CodeGenError("MemoryStore: Type " + + ASRUtils::type_to_str_fortran(ttype) + + " not yet supported"); + } + } + return kind; + } + uint32_t emit_memory_store(ASR::expr_t *v) { auto ttype = ASRUtils::type_get_past_array(ASRUtils::expr_type(v)); auto kind = ASRUtils::extract_kind_from_ttype_t(ttype); @@ -1247,7 +1346,7 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { } break; } - case ASR::ttypeType::Character: { + case ASR::ttypeType::String: { switch (kind) { case 4: m_wa.emit_i32_store(wasm::mem_align::b8, 0); @@ -1257,7 +1356,7 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { break; default: throw CodeGenError( - "MemoryStore: Unsupported Character kind"); + "MemoryStore: Unsupported String kind"); } break; } @@ -1298,7 +1397,7 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { } default: { throw CodeGenError("MemoryStore: Type " + - ASRUtils::type_to_str(ttype) + + ASRUtils::type_to_str_fortran(ttype) + " not yet supported"); } } @@ -1347,7 +1446,7 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { } break; } - case ASR::ttypeType::Character: { + case ASR::ttypeType::String: { switch (kind) { case 4: m_wa.emit_i32_load(wasm::mem_align::b8, 0); @@ -1357,7 +1456,7 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { break; default: throw CodeGenError( - "MemoryLoad: Unsupported Character kind"); + "MemoryLoad: Unsupported String kind"); } break; } @@ -1386,7 +1485,7 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { } default: { throw CodeGenError("MemoryLoad: Type " + - ASRUtils::type_to_str(ttype) + + ASRUtils::type_to_str_fortran(ttype) + " not yet supported"); } } @@ -1415,7 +1514,8 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { } this->visit_expr(*x.m_left); this->visit_expr(*x.m_right); - ASR::Integer_t *i = ASR::down_cast(x.m_type); + LCOMPILERS_ASSERT(ASR::is_a(*ASRUtils::extract_type(x.m_type))); + ASR::Integer_t *i = ASR::down_cast(ASRUtils::extract_type(x.m_type)); if (i->m_kind == 4) { switch (x.m_op) { case ASR::binopType::Add: { @@ -1598,7 +1698,8 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { } this->visit_expr(*x.m_left); this->visit_expr(*x.m_right); - ASR::Real_t *f = ASR::down_cast(x.m_type); + LCOMPILERS_ASSERT(ASR::is_a(*ASRUtils::extract_type(x.m_type))); + ASR::Real_t *f = ASR::down_cast(ASRUtils::extract_type(x.m_type)); if (f->m_kind == 4) { switch (x.m_op) { case ASR::binopType::Add: { @@ -1632,10 +1733,23 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { "RealBinop: only x**2 implemented so far for " "powers"); } + } else if(ASR::is_a(*val)) { + ASR::IntegerConstant_t *c = + ASR::down_cast(val); + if (c->m_n == 2) { + // drop the last stack item in the wasm stack + m_wa.emit_drop(); + this->visit_expr(*x.m_left); + m_wa.emit_f32_mul(); + } else { + throw CodeGenError( + "RealBinop: only x**2 implemented so far for " + "powers"); + } } else { throw CodeGenError( - "RealBinop: only x**2 implemented so far for " - "powers"); + "RealBinop: Only exponent of type [Integer, Real] are supported" + "for ** operator."); } break; }; @@ -1677,10 +1791,23 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { "RealBinop: only x**2 implemented so far for " "powers"); } + } else if(ASR::is_a(*val)) { + ASR::IntegerConstant_t *c = + ASR::down_cast(val); + if (c->m_n == 2) { + // drop the last stack item in the wasm stack + m_wa.emit_drop(); + this->visit_expr(*x.m_left); + m_wa.emit_f64_mul(); + } else { + throw CodeGenError( + "RealBinop: only x**2 implemented so far for " + "powers"); + } } else { throw CodeGenError( - "RealBinop: only x**2 implemented so far for " - "powers"); + "RealBinop: Only exponent of type [Integer, Real] are supported" + "for ** operator."); } break; }; @@ -1700,8 +1827,8 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { } this->visit_expr(*x.m_left); this->visit_expr(*x.m_right); - LCOMPILERS_ASSERT(ASRUtils::is_complex(*x.m_type)); - int a_kind = ASR::down_cast(ASRUtils::type_get_past_pointer(x.m_type))->m_kind; + LCOMPILERS_ASSERT(ASR::is_a(*ASRUtils::extract_type(x.m_type))); + int a_kind = ASR::down_cast(ASRUtils::extract_type(x.m_type))->m_kind; switch (x.m_op) { case ASR::binopType::Add: { if (a_kind == 4) { @@ -1745,7 +1872,8 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { visit_expr(*x.m_value); return; } - ASR::Integer_t *i = ASR::down_cast(x.m_type); + LCOMPILERS_ASSERT(ASR::is_a(*ASRUtils::extract_type(x.m_type))); + ASR::Integer_t *i = ASR::down_cast(ASRUtils::extract_type(x.m_type)); // there seems no direct unary-minus inst in wasm, so subtracting from 0 if (i->m_kind == 4) { m_wa.emit_i32_const(0); @@ -1766,7 +1894,8 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { visit_expr(*x.m_value); return; } - ASR::Real_t *f = ASR::down_cast(x.m_type); + LCOMPILERS_ASSERT(ASR::is_a(*ASRUtils::extract_type(x.m_type))); + ASR::Real_t *f = ASR::down_cast(ASRUtils::extract_type(x.m_type)); if (f->m_kind == 4) { this->visit_expr(*x.m_arg); m_wa.emit_f32_neg(); @@ -1783,7 +1912,8 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { visit_expr(*x.m_value); return; } - ASR::Complex_t *f = ASR::down_cast(x.m_type); + LCOMPILERS_ASSERT(ASR::is_a(*ASRUtils::extract_type(x.m_type))); + ASR::Complex_t *f = ASR::down_cast(ASRUtils::extract_type(x.m_type)); if (f->m_kind == 4) { this->visit_expr(*x.m_arg); m_wa.emit_f32_neg(); @@ -2150,14 +2280,14 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { case ASR::ttypeType::Integer: case ASR::ttypeType::Logical: case ASR::ttypeType::Real: - case ASR::ttypeType::Character: + case ASR::ttypeType::String: case ASR::ttypeType::Complex: { emit_var_get(v); break; } default: throw CodeGenError( - "Only Integer, Float, Bool, Character, Complex " + "Only Integer, Float, Bool, String, Complex " "variable types supported currently"); } } @@ -2398,16 +2528,88 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { m_wa.emit_i32_const(m_string_to_iov_loc_map[x.m_s]); } + void process_ArrayConstant_value(void* data, ASR::ttype_t* type, int i) { + type = ASRUtils::type_get_past_array(type); + int kind = ASRUtils::extract_kind_from_ttype_t(type); + + switch (type->type) { + case ASR::ttypeType::Integer: { + switch (kind) { + case 1: { + int8_t val = ((int8_t*)data)[i]; + m_wa.emit_i32_const(val); break; + } + case 2: { + int16_t val = ((int16_t*)data)[i]; + m_wa.emit_i32_const(val); break; + } + case 4: { + int32_t val = ((int32_t*)data)[i]; + m_wa.emit_i32_const(val); break; + } + case 8: { + int64_t val = ((int64_t*)data)[i]; + m_wa.emit_i32_const(val); break; + } + default: + throw CodeGenError("process_ArrayConstant_value: Integer kind not supported"); + } + break; + } + case ASR::ttypeType::Real: { + switch (kind) { + case 4: { + float val = ((float*)data)[i]; + m_wa.emit_f32_const(val); break; + } + case 8: { + double val = ((double*)data)[i]; + m_wa.emit_f32_const(val); break; + } + default: + throw CodeGenError("process_ArrayConstant_value: Real kind not supported"); + } + break; + } + case ASR::ttypeType::Logical: { + if (kind == 4) { + int32_t val = ((int32_t*)data)[i]; + m_wa.emit_i32_const(val); + } else { + throw CodeGenError("process_ArrayConstant_value: Logical kind not supported"); + } + break; + } + case ASR::ttypeType::String: { + ASR::String_t* char_type = ASR::down_cast(type); + int len = char_type->m_len; + char* data_char = (char*)data + i*len; + // take first len characters + char* new_char = new char[len]; + for (int j = 0; j < len; j++) { + new_char[j] = data_char[j]; + } + std::string str = '\"' + std::string(new_char) + '\"'; + emit_string(str); + m_wa.emit_i32_const(m_string_to_iov_loc_map[str]); + break; + } + default: { + throw CodeGenError("process_ArrayConstant_value: Type not supported"); + } + } + } + void visit_ArrayConstant(const ASR::ArrayConstant_t &x) { // Todo: Add a check here if there is memory available to store the // given string uint32_t cur_mem_loc = avail_mem_loc; - for (size_t i = 0; i < x.n_args; i++) { + for (size_t i = 0; i < (size_t) ASRUtils::get_fixed_size_of_array(x.m_type); i++) { // emit memory location to store array element m_wa.emit_i32_const(avail_mem_loc); - this->visit_expr(*x.m_args[i]); - int element_size_in_bytes = emit_memory_store(x.m_args[i]); + process_ArrayConstant_value(x.m_data, x.m_type, i); + int element_size_in_bytes = emit_memory_store(x.m_type); avail_mem_loc += element_size_in_bytes; } // leave array location in memory on the stack @@ -2477,18 +2679,18 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { } break; } - case ASR::ttypeType::Character: { + case ASR::ttypeType::String: { switch (kind) { case 4: global_var = tmp_reg_i32; break; case 8: global_var = tmp_reg_i64; break; default: throw CodeGenError( - "temp_value_set: Unsupported Character kind"); + "temp_value_set: Unsupported String kind"); } break; } default: { throw CodeGenError("temp_value_set: Type " + - ASRUtils::type_to_str(ttype) + + ASRUtils::type_to_str_fortran(ttype) + " not yet supported"); } } @@ -2526,18 +2728,18 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { } break; } - case ASR::ttypeType::Character: { + case ASR::ttypeType::String: { switch (kind) { case 4: global_var = tmp_reg_i32; break; case 8: global_var = tmp_reg_i64; break; default: throw CodeGenError( - "temp_value_get: Unsupported Character kind"); + "temp_value_get: Unsupported String kind"); } break; } default: { throw CodeGenError("temp_value_get: Type " + - ASRUtils::type_to_str(ttype) + + ASRUtils::type_to_str_fortran(ttype) + " not yet supported"); } } @@ -2763,7 +2965,7 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { } break; } - case (ASR::cast_kindType::CharacterToLogical): { + case (ASR::cast_kindType::StringToLogical): { throw CodeGenError(R"""(STrings are not supported yet)""", x.base.base.loc); break; @@ -2935,30 +3137,21 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { m_wa.emit_drop(); } - template - void handle_print(const T &x) { - for (size_t i = 0; i < x.n_values; i++) { - if (i > 0) { - if (x.m_separator) { - m_wa.emit_i32_const(1); // file type: 1 for stdout - this->visit_expr(*x.m_separator); // iov location - m_wa.emit_i32_const(1); // size of iov vector - m_wa.emit_i32_const(0); // mem_loction to return no. of bytes written - - // call WASI fd_write - m_wa.emit_call(m_import_func_idx_map[fd_write]); - m_wa.emit_drop(); - } else { - emit_call_fd_write(1, " ", 1, 0); - } - } - ASR::expr_t *v = x.m_values[i]; + void visit_StringFormat(const ASR::StringFormat_t &x) { + if(x.m_fmt){ + //TODO :: respect fmt. + } + for (size_t i = 0; i < x.n_args; i++) { + ASR::expr_t *v = x.m_args[i]; ASR::ttype_t *t = ASRUtils::expr_type(v); int a_kind = ASRUtils::extract_kind_from_ttype_t(t); - + if(i > 0){ + emit_call_fd_write(1, " ", 1, 0); + } + // TODO : Support array printing in backend. if (ASRUtils::is_integer(*t) || ASRUtils::is_logical(*t)) { INCLUDE_RUNTIME_FUNC(print_i64); - this->visit_expr(*x.m_values[i]); + this->visit_expr(*v); switch (a_kind) { case 4: { m_wa.emit_i64_extend_i32_s(); @@ -2978,7 +3171,7 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { } else if (ASRUtils::is_real(*t)) { INCLUDE_RUNTIME_FUNC(print_i64); INCLUDE_RUNTIME_FUNC(print_f64); - this->visit_expr(*x.m_values[i]); + this->visit_expr(*v); switch (a_kind) { case 4: { m_wa.emit_f64_promote_f32(); @@ -2997,7 +3190,7 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { } } else if (ASRUtils::is_character(*t)) { m_wa.emit_i32_const(1); // file type: 1 for stdout - this->visit_expr(*x.m_values[i]); // iov location + this->visit_expr(*v); m_wa.emit_i32_const(1); // size of iov vector m_wa.emit_i32_const(0); // mem_loction to return no. of bytes written @@ -3008,7 +3201,7 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { INCLUDE_RUNTIME_FUNC(print_i64); INCLUDE_RUNTIME_FUNC(print_f64); emit_call_fd_write(1, "(", 1, 0); - this->visit_expr(*x.m_values[i]); + this->visit_expr(*v); if (a_kind == 4) { m_wa.emit_f64_promote_f32(); m_wa.emit_global_set(m_compiler_globals[tmp_reg_f64]); @@ -3023,40 +3216,47 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { emit_call_fd_write(1, ")", 1, 0); } } + emit_call_fd_write(1, "\n", 1, 0); + } - // print "\n" newline character - if (x.m_end) { + void visit_Print(const ASR::Print_t &x) { + if( ASR::is_a(*x.m_text)){ // loop on stringformat args only. + this->visit_expr(*x.m_text); + } else if (ASR::is_a(*ASRUtils::expr_type(x.m_text))) { //handle the stringconstant and return. m_wa.emit_i32_const(1); // file type: 1 for stdout - this->visit_expr(*x.m_end); // iov location + this->visit_expr(*x.m_text);// iov location m_wa.emit_i32_const(1); // size of iov vector m_wa.emit_i32_const(0); // mem_loction to return no. of bytes written - // call WASI fd_write m_wa.emit_call(m_import_func_idx_map[fd_write]); m_wa.emit_drop(); - } else { emit_call_fd_write(1, "\n", 1, 0); + return; } } - void visit_Print(const ASR::Print_t &x) { - handle_print(x); - } - - void visit_StringFormat(const ASR::StringFormat_t &x) { - diag.codegen_warning_label( - "StringFormat not implemented yet, ignored for now", - {x.m_fmt->base.loc}, "ignored"); - this->visit_expr(*x.m_fmt); - } - void visit_FileWrite(const ASR::FileWrite_t &x) { if (x.m_unit != nullptr) { diag.codegen_error_label("unit in write() is not implemented yet", {x.m_unit->base.loc}, "not implemented"); throw CodeGenAbort(); } - handle_print(x); + if( x.n_values == 1 && ASR::is_a(*x.m_values[0])){ // loop on stringformat args only. + this->visit_expr(*x.m_values[0]); + } else if (x.n_values == 1 && ASR::is_a(*ASRUtils::expr_type(x.m_values[0]))) { //handle the stringconstant and return. + m_wa.emit_i32_const(1); // file type: 1 for stdout + this->visit_expr(*x.m_values[0]);// iov location + m_wa.emit_i32_const(1); // size of iov vector + m_wa.emit_i32_const(0); // mem_loction to return no. of bytes written + // call WASI fd_write + m_wa.emit_call(m_import_func_idx_map[fd_write]); + m_wa.emit_drop(); + emit_call_fd_write(1, "\n", 1, 0); + return; + } else { + throw CodeGenError("FileWrite: Only stringformat or single character argument are supported", + x.base.base.loc); + } } void visit_FileRead(const ASR::FileRead_t &x) { diff --git a/src/libasr/codegen/asr_to_x86.cpp b/src/libasr/codegen/asr_to_x86.cpp index c4755579fb..d9f2233f07 100644 --- a/src/libasr/codegen/asr_to_x86.cpp +++ b/src/libasr/codegen/asr_to_x86.cpp @@ -1,5 +1,4 @@ #include -#include #include #include @@ -378,8 +377,13 @@ class ASRToX86Visitor : public ASR::BaseVisitor } void visit_Print(const ASR::Print_t &x) { - LCOMPILERS_ASSERT(x.n_values == 1); - ASR::expr_t *e = x.m_values[0]; + LCOMPILERS_ASSERT(x.m_text != nullptr); + ASR::expr_t *e = x.m_text; + //HACKISH way to handle print refactoring (always using stringformat). + // TODO : Implement stringformat visitor. + if(e && ASR::is_a(*e)){ + e = ASR::down_cast(e)->m_args[0]; + } if (e->type == ASR::exprType::StringConstant) { ASR::StringConstant_t *s = down_cast(e); std::string msg = s->m_s; @@ -396,7 +400,7 @@ class ASRToX86Visitor : public ASR::BaseVisitor m_a.asm_add_r32_imm8(X86Reg::esp, 4); } else if (t->type == ASR::ttypeType::Real) { throw LCompilersException("Type not implemented"); - } else if (t->type == ASR::ttypeType::Character) { + } else if (t->type == ASR::ttypeType::String) { throw LCompilersException("Type not implemented"); } else { throw LCompilersException("Type not implemented"); diff --git a/src/libasr/codegen/c_utils.h b/src/libasr/codegen/c_utils.h index 5bd81063b8..aac4f7c01f 100644 --- a/src/libasr/codegen/c_utils.h +++ b/src/libasr/codegen/c_utils.h @@ -276,7 +276,7 @@ namespace CUtils { } break; } - case ASR::ttypeType::Character: { + case ASR::ttypeType::String: { type_src = "char*"; break; } @@ -409,7 +409,7 @@ class CCPPDSUtils { result = func + "(&" + value + ", &" + target + ");"; break; } - case ASR::ttypeType::Character : { + case ASR::ttypeType::String : { if (is_c) { result = "_lfortran_strcpy(&" + target + ", " + value + ", 1);"; } else { @@ -503,7 +503,7 @@ class CCPPDSUtils { case ASR::ttypeType::Logical: { return "%d"; } - case ASR::ttypeType::Character: { + case ASR::ttypeType::String: { return "%s"; } case ASR::ttypeType::CPtr: { @@ -523,7 +523,7 @@ class CCPPDSUtils { return get_print_type(type_ptr->m_type, false); } } - case ASR::ttypeType::Enum: { + case ASR::ttypeType::EnumType: { ASR::ttype_t* enum_underlying_type = ASRUtils::get_contained_type(t); return get_print_type(enum_underlying_type, deref_ptr); } @@ -720,7 +720,7 @@ class CCPPDSUtils { tmp_gen += indent + signature + " {\n"; std::string print_type = get_print_type(t, false); tmp_gen += indent + tab + "printf(\"" + print_type + "\", creal(a), cimag(a));\n"; - } else if (ASR::is_a(*t)) { + } else if (ASR::is_a(*t)) { tmp_gen += indent + signature + " {\n"; std::string print_type = get_print_type(t, false); tmp_gen += indent + tab + "printf(\"'" + print_type + "'\", a);\n"; @@ -777,7 +777,7 @@ class CCPPDSUtils { num + ", " + "b.element_" + num + ");\n"; } tmp_gen += indent + tab + "return ans;\n"; - } else if (ASR::is_a(*t)) { + } else if (ASR::is_a(*t)) { std::string signature = "bool " + cmp_func + "(" + element_type + " a, " + element_type + " b)"; func_decls += indent + "inline " + signature + ";\n"; signature = indent + signature; @@ -851,7 +851,7 @@ class CCPPDSUtils { ASR::symbol_t* member = struct_type_t->m_symtab->get_symbol(mem_name); ASR::ttype_t* member_type_asr = ASRUtils::symbol_type(member); if( CUtils::is_non_primitive_DT(member_type_asr) || - ASR::is_a(*member_type_asr) ) { + ASR::is_a(*member_type_asr) ) { tmp_generated += indent + tab + get_deepcopy(member_type_asr, "&(src->" + mem_name + ")", "&(dest->" + mem_name + ")") + ";\n"; } else if( ASRUtils::is_array(member_type_asr) ) { @@ -1004,7 +1004,7 @@ class CCPPDSUtils { generated_code += indent + signature + " {\n"; std::string list_resize_func = get_list_resize_func(list_type_code); generated_code += indent + tab + list_resize_func + "(x);\n"; - if( ASR::is_a(*m_type) ) { + if( ASR::is_a(*m_type) ) { generated_code += indent + tab + "x->data[x->current_end_point] = NULL;\n"; } generated_code += indent + tab + \ @@ -1039,7 +1039,7 @@ class CCPPDSUtils { generated_code += indent + tab + tab + "pos_ptr++;\n"; generated_code += indent + tab + "}\n\n"; - if( ASR::is_a(*m_type) ) { + if( ASR::is_a(*m_type) ) { generated_code += indent + tab + "x->data[pos] = NULL;\n"; } generated_code += indent + tab + get_deepcopy(m_type, "element", "x->data[pos]") + "\n"; @@ -1176,7 +1176,7 @@ class CCPPDSUtils { tmp_gen += indent + signature + " {\n"; for (size_t i=0; in_type; i++) { std::string n = std::to_string(i); - if (ASR::is_a(*t->m_type[i])) { + if (ASR::is_a(*t->m_type[i])) { tmp_gen += indent + tab + "dest->element_" + n + " = " + \ "NULL;\n"; } @@ -1718,7 +1718,7 @@ namespace BindPyUtils { util_func_decls += indent + signature + ";\n"; std::string body = indent + signature + " {\n"; body += indent + tab + "char *s = (char*)PyUnicode_AsUTF8(pValue);\n"; - body += indent + tab + "return _lfortran_str_copy(s, 1, 0);\n"; + body += indent + tab + "return _lfortran_str_copy(s, 1, 0, -1, -1);\n"; body += indent + "}\n\n"; util_funcs += body; } @@ -1756,7 +1756,7 @@ namespace BindPyUtils { } break; } - case ASR::ttypeType::Character: { + case ASR::ttypeType::String: { type_src = "NPY_STRING"; break; } @@ -1809,7 +1809,7 @@ namespace BindPyUtils { type_src = "PyFloat_FromDouble"; break; } - case ASR::ttypeType::Character: { + case ASR::ttypeType::String: { type_src = "PyUnicode_FromString"; break; } @@ -1863,7 +1863,7 @@ namespace BindPyUtils { type_src = "PyFloat_AsDouble"; break; } - case ASR::ttypeType::Character: { + case ASR::ttypeType::String: { type_src = bind_py_utils_functions->get_conv_py_str_to_c(); break; } diff --git a/src/libasr/codegen/evaluator.cpp b/src/libasr/codegen/evaluator.cpp index 1dff3131ff..50d283afad 100644 --- a/src/libasr/codegen/evaluator.cpp +++ b/src/libasr/codegen/evaluator.cpp @@ -33,10 +33,8 @@ #include #include #include -#include #include #include -#include #include #include #include @@ -53,9 +51,18 @@ #else # include #endif -#include -#include +#if LLVM_VERSION_MAJOR >= 17 + // TODO: removed from LLVM 17 +#else +# include +#endif + +#if LLVM_VERSION_MAJOR < 18 +# include +# include +#endif +#include #include #include #include @@ -63,6 +70,10 @@ #include #include +#ifdef HAVE_LFORTRAN_MLIR +#include +#include +#endif namespace LCompilers { @@ -114,16 +125,10 @@ std::string LLVMModule::get_return_type(const std::string &fn_name) return "real8"; } else if (type->isIntegerTy(1)) { return "logical"; - } else if (type->isIntegerTy(8)) { - return "integer1"; - } else if (type->isIntegerTy(16)) { - return "integer2"; } else if (type->isIntegerTy(32)) { return "integer4"; } else if (type->isIntegerTy(64)) { return "integer8"; - } else if (type->isPointerTy() && type->getPointerElementType()->isIntegerTy(8)) { - return "integer1ptr"; } else if (type->isStructTy()) { llvm::StructType *st = llvm::cast(type); if (st->hasName()) { @@ -131,9 +136,12 @@ std::string LLVMModule::get_return_type(const std::string &fn_name) return "complex4"; } else if (startswith(std::string(st->getName()), "complex_8")) { return "complex8"; + } else { + throw LCompilersException("LLVMModule::get_return_type(): StructType return type `" + std::string(st->getName()) + "` not supported"); } + } else { + throw LCompilersException("LLVMModule::get_return_type(): Noname struct return type not supported"); } - return "struct"; } else if (type->isVectorTy()) { // Used for passing complex_4 on some platforms return "complex4"; @@ -144,6 +152,44 @@ std::string LLVMModule::get_return_type(const std::string &fn_name) } } +#ifdef HAVE_LFORTRAN_MLIR +MLIRModule::MLIRModule(std::unique_ptr m, + std::unique_ptr ctx) { + mlir_m = std::move(m); + mlir_ctx = std::move(ctx); + llvm_ctx = std::make_unique(); +} + +MLIRModule::~MLIRModule() { + llvm_m.reset(); + llvm_ctx.reset(); +}; + +std::string MLIRModule::mlir_str() { + std::string mlir_str; + llvm::raw_string_ostream raw_os(mlir_str); + mlir_m->print(raw_os); + return mlir_str; +} + +std::string MLIRModule::llvm_str() { + std::string mlir_str; + llvm::raw_string_ostream raw_os(mlir_str); + llvm_m->print(raw_os, nullptr); + return mlir_str; +} + +void MLIRModule::mlir_to_llvm(llvm::LLVMContext &ctx) { + std::unique_ptr llvmModule = mlir::translateModuleToLLVMIR( + *mlir_m, ctx); + if (llvmModule) { + llvm_m = std::move(llvmModule); + } else { + throw LCompilersException("Failed to generate LLVM IR"); + } +} +#endif + extern "C" { float _lfortran_stan(float x); @@ -208,12 +254,17 @@ LLVMEvaluator::~LLVMEvaluator() context.reset(); } -std::unique_ptr LLVMEvaluator::parse_module(const std::string &source) +std::unique_ptr LLVMEvaluator::parse_module(const std::string &source, const std::string &filename="") { llvm::SMDiagnostic err; - std::unique_ptr module - = llvm::parseAssemblyString(source, err, *context); + std::unique_ptr module; + if (!filename.empty()) { + module = llvm::parseAssemblyFile(filename, err, *context); + } else { + module = llvm::parseAssemblyString(source, err, *context); + } if (!module) { + err.print("", llvm::errs()); throw LCompilersException("parse_module(): Invalid LLVM IR"); } bool v = llvm::verifyModule(*module); @@ -225,6 +276,10 @@ std::unique_ptr LLVMEvaluator::parse_module(const std::string &sou return module; } +std::unique_ptr LLVMEvaluator::parse_module2(const std::string &source, const std::string &filename="") { + return std::make_unique(parse_module(source, filename)); +} + void LLVMEvaluator::add_module(const std::string &source) { std::unique_ptr module = parse_module(source); // TODO: apply LLVM optimizations here @@ -260,7 +315,12 @@ void LLVMEvaluator::add_module(std::unique_ptr m) { } intptr_t LLVMEvaluator::get_symbol_address(const std::string &name) { - llvm::Expected s = jit->lookup(name); +#if LLVM_VERSION_MAJOR < 17 + llvm::Expected +#else + llvm::Expected +#endif + s = jit->lookup(name); if (!s) { llvm::Error e = s.takeError(); llvm::SmallVector buf; @@ -271,7 +331,11 @@ intptr_t LLVMEvaluator::get_symbol_address(const std::string &name) { throw LCompilersException("lookup() failed to find the symbol '" + name + "', error: " + msg); } +#if LLVM_VERSION_MAJOR < 17 llvm::Expected addr0 = s->getAddress(); +#else + llvm::Expected addr0 = s->getAddress().getValue(); +#endif if (!addr0) { llvm::Error e = addr0.takeError(); llvm::SmallVector buf; @@ -294,7 +358,11 @@ void write_file(const std::string &filename, const std::string &contents) std::string LLVMEvaluator::get_asm(llvm::Module &m) { llvm::legacy::PassManager pass; +#if LLVM_VERSION_MAJOR < 18 llvm::CodeGenFileType ft = llvm::CGFT_AssemblyFile; +#else + llvm::CodeGenFileType ft = llvm::CodeGenFileType::AssemblyFile; +#endif llvm::SmallVector buf; llvm::raw_svector_ostream dest(buf); if (TM->addPassesToEmitFile(pass, dest, nullptr, ft)) { @@ -314,7 +382,11 @@ void LLVMEvaluator::save_object_file(llvm::Module &m, const std::string &filenam m.setDataLayout(TM->createDataLayout()); llvm::legacy::PassManager pass; +#if LLVM_VERSION_MAJOR < 18 llvm::CodeGenFileType ft = llvm::CGFT_ObjectFile; +#else + llvm::CodeGenFileType ft = llvm::CodeGenFileType::ObjectFile; +#endif std::error_code EC; llvm::raw_fd_ostream dest(filename, EC, llvm::sys::fs::OF_None); if (EC) { @@ -343,6 +415,9 @@ void LLVMEvaluator::opt(llvm::Module &m) { llvm::legacy::FunctionPassManager fpm(&m); fpm.add(llvm::createTargetTransformInfoWrapperPass(TM->getTargetIRAnalysis())); +#if LLVM_VERSION_MAJOR >= 17 + // TODO: https://llvm.org/docs/NewPassManager.html +#else int optLevel = 3; int sizeLevel = 0; llvm::PassManagerBuilder builder; @@ -355,6 +430,7 @@ void LLVMEvaluator::opt(llvm::Module &m) { builder.SLPVectorize = true; builder.populateFunctionPassManager(fpm); builder.populateModulePassManager(mpm); +#endif fpm.doInitialization(); for (llvm::Function &func : m) { @@ -379,6 +455,11 @@ void LLVMEvaluator::print_version_message() llvm::cl::PrintVersionMessage(); } +std::string LLVMEvaluator::llvm_version() +{ + return LLVM_VERSION_STRING; +} + llvm::LLVMContext &LLVMEvaluator::get_context() { return *context; @@ -406,7 +487,7 @@ void LLVMEvaluator::print_targets() std::string LLVMEvaluator::get_default_target_triple() { - return llvm::sys::getDefaultTargetTriple(); + return LLVMGetDefaultTargetTriple(); } } // namespace LCompilers diff --git a/src/libasr/codegen/evaluator.h b/src/libasr/codegen/evaluator.h index fa2bf0e5c0..4be563d6d4 100644 --- a/src/libasr/codegen/evaluator.h +++ b/src/libasr/codegen/evaluator.h @@ -26,6 +26,11 @@ namespace llvm { } } +namespace mlir { + class MLIRContext; + class ModuleOp; +} + namespace LCompilers { class LLVMModule @@ -41,6 +46,20 @@ class LLVMModule llvm::GlobalVariable *get_global(const std::string &global_name); }; +class MLIRModule { +public: + std::unique_ptr mlir_m; + std::unique_ptr mlir_ctx; + std::unique_ptr llvm_m; + std::unique_ptr llvm_ctx; + MLIRModule(std::unique_ptr m, + std::unique_ptr ctx); + ~MLIRModule(); + std::string mlir_str(); + std::string llvm_str(); + void mlir_to_llvm(llvm::LLVMContext &ctx); +}; + class LLVMEvaluator { private: @@ -51,7 +70,8 @@ class LLVMEvaluator public: LLVMEvaluator(const std::string &t = ""); ~LLVMEvaluator(); - std::unique_ptr parse_module(const std::string &source); + std::unique_ptr parse_module(const std::string &source, const std::string &filename); + std::unique_ptr parse_module2(const std::string &source, const std::string &filename); void add_module(const std::string &source); void add_module(std::unique_ptr mod); void add_module(std::unique_ptr m); @@ -63,6 +83,7 @@ class LLVMEvaluator void opt(llvm::Module &m); static std::string module_to_string(llvm::Module &m); static void print_version_message(); + static std::string llvm_version(); llvm::LLVMContext &get_context(); const llvm::DataLayout &get_jit_data_layout(); static void print_targets(); diff --git a/src/libasr/codegen/llvm_array_utils.cpp b/src/libasr/codegen/llvm_array_utils.cpp index a38415e125..5c994cc810 100644 --- a/src/libasr/codegen/llvm_array_utils.cpp +++ b/src/libasr/codegen/llvm_array_utils.cpp @@ -12,9 +12,9 @@ namespace LCompilers { llvm::Function *fn = module.getFunction(func_name); if (!fn) { llvm::FunctionType *function_type = llvm::FunctionType::get( - llvm::Type::getInt8PtrTy(context), { + llvm::Type::getInt8Ty(context)->getPointerTo(), { llvm::Type::getInt32Ty(context) - }, true); + }, false); fn = llvm::Function::Create(function_type, llvm::Function::ExternalLinkage, func_name, module); } @@ -28,15 +28,15 @@ namespace LCompilers { llvm::Function *fn = module.getFunction(func_name); if (!fn) { llvm::FunctionType *function_type = llvm::FunctionType::get( - llvm::Type::getInt8PtrTy(context), { - llvm::Type::getInt8PtrTy(context), + llvm::Type::getInt8Ty(context)->getPointerTo(), { + llvm::Type::getInt8Ty(context)->getPointerTo(), llvm::Type::getInt32Ty(context) - }, true); + }, false); fn = llvm::Function::Create(function_type, llvm::Function::ExternalLinkage, func_name, module); } std::vector args = { - builder.CreateBitCast(ptr, llvm::Type::getInt8PtrTy(context)), arg_size}; + builder.CreateBitCast(ptr, llvm::Type::getInt8Ty(context)->getPointerTo()), arg_size}; return builder.CreateCall(fn, args); } @@ -116,16 +116,16 @@ namespace LCompilers { convert_to_argument(llvm::Value* tmp, ASR::ttype_t* asr_arg_type, llvm::Type* arg_type, bool data_only) { if( data_only ) { - return LLVM::CreateLoad(*builder, get_pointer_to_data(tmp)); + return llvm_utils->CreateLoad(get_pointer_to_data(tmp)); } - llvm::Value* arg_struct = builder->CreateAlloca(arg_type, nullptr); + llvm::Value* arg_struct = llvm_utils->CreateAlloca(*builder, arg_type); llvm::Value* first_ele_ptr = nullptr; std::string asr_arg_type_code = ASRUtils::get_type_code(ASRUtils::get_contained_type(asr_arg_type), false, false); llvm::StructType* tmp_struct_type = tkr2array[asr_arg_type_code].first; if( tmp_struct_type->getElementType(0)->isArrayTy() ) { first_ele_ptr = llvm_utils->create_gep(get_pointer_to_data(tmp), 0); } else if( tmp_struct_type->getNumElements() < 5 ) { - first_ele_ptr = LLVM::CreateLoad(*builder, get_pointer_to_data(tmp)); + first_ele_ptr = llvm_utils->CreateLoad(get_pointer_to_data(tmp)); } else if( tmp_struct_type->getNumElements() == 5 ) { return tmp; } @@ -134,7 +134,7 @@ namespace LCompilers { llvm::Value* sec_ele_ptr = get_offset(tmp); llvm::Value* sec_arg_ptr = llvm_utils->create_gep(arg_struct, 1); builder->CreateStore(sec_ele_ptr, sec_arg_ptr); - llvm::Value* third_ele_ptr = LLVM::CreateLoad(*builder, + llvm::Value* third_ele_ptr = llvm_utils->CreateLoad( get_pointer_to_dimension_descriptor_array(tmp)); llvm::Value* third_arg_ptr = llvm_utils->create_gep(arg_struct, 2); builder->CreateStore(third_ele_ptr, third_arg_ptr); @@ -218,7 +218,16 @@ namespace LCompilers { if( !load ) { return dim_des_arr_ptr; } - return LLVM::CreateLoad(*builder, dim_des_arr_ptr); + return llvm_utils->CreateLoad2(dim_des->getPointerTo(), dim_des_arr_ptr); + } + + llvm::Value* SimpleCMODescriptor:: + get_pointer_to_dimension_descriptor_array(llvm::Type* type, llvm::Value* arr, bool load) { + llvm::Value* dim_des_arr_ptr = llvm_utils->create_gep2(type, arr, 2); + if( !load ) { + return dim_des_arr_ptr; + } + return llvm_utils->CreateLoad2(dim_des->getPointerTo(), dim_des_arr_ptr); } llvm::Value* SimpleCMODescriptor:: @@ -227,7 +236,8 @@ namespace LCompilers { if( get_pointer ) { return rank_ptr; } - return LLVM::CreateLoad(*builder, rank_ptr); + llvm::Type *i32 = llvm::Type::getInt32Ty(context); + return llvm_utils->CreateLoad2(i32, rank_ptr); } void SimpleCMODescriptor:: @@ -238,20 +248,22 @@ namespace LCompilers { llvm::Value* SimpleCMODescriptor:: get_dimension_size(llvm::Value* dim_des_arr, llvm::Value* dim, bool load) { - llvm::Value* dim_size = llvm_utils->create_gep(llvm_utils->create_ptr_gep(dim_des_arr, dim), 2); + llvm::Value* dim_size = llvm_utils->create_gep2(dim_des, llvm_utils->create_ptr_gep2(dim_des, dim_des_arr, dim), 2); if( !load ) { return dim_size; } - return LLVM::CreateLoad(*builder, dim_size); + llvm::Type *i32 = llvm::Type::getInt32Ty(context); + return llvm_utils->CreateLoad2(i32, dim_size); } llvm::Value* SimpleCMODescriptor:: - get_dimension_size(llvm::Value* dim_des, bool load) { - llvm::Value* dim_size = llvm_utils->create_gep(dim_des, 2); + get_dimension_size(llvm::Value* dim_des_arr, bool load) { + llvm::Value* dim_size = llvm_utils->create_gep2(dim_des, dim_des_arr, 2); if( !load ) { return dim_size; } - return LLVM::CreateLoad(*builder, dim_size); + llvm::Type *i32 = llvm::Type::getInt32Ty(context); + return llvm_utils->CreateLoad2(i32, dim_size); } void SimpleCMODescriptor::fill_array_details( @@ -262,16 +274,16 @@ namespace LCompilers { builder->CreateStore(llvm::ConstantInt::get(context, llvm::APInt(32, 0)), offset_val); llvm::Value* dim_des_val = llvm_utils->create_gep(arr, 2); llvm::Value* arr_rank = llvm::ConstantInt::get(context, llvm::APInt(32, n_dims)); - llvm::Value* dim_des_first = builder->CreateAlloca(dim_des, arr_rank); + llvm::Value* dim_des_first = llvm_utils->CreateAlloca(*builder, dim_des, arr_rank); builder->CreateStore(dim_des_first, dim_des_val); builder->CreateStore(arr_rank, get_rank(arr, true)); - dim_des_val = LLVM::CreateLoad(*builder, dim_des_val); + dim_des_val = llvm_utils->CreateLoad2(dim_des->getPointerTo(), dim_des_val); llvm::Value* prod = llvm::ConstantInt::get(context, llvm::APInt(32, 1)); for( int r = 0; r < n_dims; r++ ) { - llvm::Value* dim_val = llvm_utils->create_ptr_gep(dim_des_val, r); - llvm::Value* s_val = llvm_utils->create_gep(dim_val, 0); - llvm::Value* l_val = llvm_utils->create_gep(dim_val, 1); - llvm::Value* dim_size_ptr = llvm_utils->create_gep(dim_val, 2); + llvm::Value* dim_val = llvm_utils->create_ptr_gep2(dim_des, dim_des_val, r); + llvm::Value* s_val = llvm_utils->create_gep2(dim_des, dim_val, 0); + llvm::Value* l_val = llvm_utils->create_gep2(dim_des, dim_val, 1); + llvm::Value* dim_size_ptr = llvm_utils->create_gep2(dim_des, dim_val, 2); builder->CreateStore(prod, s_val); builder->CreateStore(llvm_dims[r].first, l_val); llvm::Value* dim_size = llvm_dims[r].second; @@ -283,7 +295,7 @@ namespace LCompilers { return ; } - llvm::Value* llvm_size = builder->CreateAlloca(llvm::Type::getInt32Ty(context), nullptr); + llvm::Value* llvm_size = llvm_utils->CreateAlloca(*builder, llvm::Type::getInt32Ty(context)); builder->CreateStore(prod, llvm_size); llvm::Value* first_ptr = get_pointer_to_data(arr); llvm::Value* arr_first = nullptr; @@ -292,36 +304,40 @@ namespace LCompilers { llvm::DataLayout data_layout(module); uint64_t size = data_layout.getTypeAllocSize(llvm_data_type); builder->CreateStore(builder->CreateMul( - LLVM::CreateLoad(*builder, llvm_size), + llvm_utils->CreateLoad(llvm_size), llvm::ConstantInt::get(context, llvm::APInt(32, size))), llvm_size); llvm::Value* arr_first_i8 = lfortran_malloc( - context, *module, *builder, LLVM::CreateLoad(*builder, llvm_size)); + context, *module, *builder, llvm_utils->CreateLoad(llvm_size)); heap_arrays.push_back(arr_first_i8); arr_first = builder->CreateBitCast( arr_first_i8, llvm_data_type->getPointerTo()); } else { - arr_first = builder->CreateAlloca( - llvm_data_type, LLVM::CreateLoad(*builder, llvm_size)); + arr_first = llvm_utils->CreateAlloca(*builder, + llvm_data_type, llvm_utils->CreateLoad(llvm_size)); } builder->CreateStore(arr_first, first_ptr); } void SimpleCMODescriptor::fill_array_details( llvm::Value* source, llvm::Value* destination, - ASR::ttype_t* /*asr_shape_type*/, bool ignore_data) { + ASR::ttype_t* source_type, ASR::ttype_t* destination_type, llvm::Module* module, bool ignore_data) { if( !ignore_data ) { // TODO: Implement data filling to destination array LCOMPILERS_ASSERT(false); } + llvm::Type *source_array_type = llvm_utils->get_type_from_ttype_t_util(source_type, module); + llvm::Type *dest_array_type = llvm_utils->get_type_from_ttype_t_util(destination_type, module); - llvm::Value* source_offset_val = LLVM::CreateLoad(*builder, llvm_utils->create_gep(source, 1)); - llvm::Value* dest_offset = llvm_utils->create_gep(destination, 1); + llvm::Value* source_offset_val = llvm_utils->CreateLoad2( + llvm::Type::getInt32Ty(context), llvm_utils->create_gep2(source_array_type, source, 1)); + llvm::Value* dest_offset = llvm_utils->create_gep2(dest_array_type, destination, 1); builder->CreateStore(source_offset_val, dest_offset); - llvm::Value* source_dim_des_val = LLVM::CreateLoad(*builder, llvm_utils->create_gep(source, 2)); - llvm::Value* dest_dim_des_ptr = llvm_utils->create_gep(destination, 2); + llvm::Value* source_dim_des_val = llvm_utils->CreateLoad2( + dim_des->getPointerTo(), llvm_utils->create_gep2(source_array_type, source, 2)); + llvm::Value* dest_dim_des_ptr = llvm_utils->create_gep2(dest_array_type, destination, 2); builder->CreateStore(source_dim_des_val, dest_dim_des_ptr); @@ -330,29 +346,31 @@ namespace LCompilers { }; void SimpleCMODescriptor::fill_malloc_array_details( - llvm::Value* arr, llvm::Type* llvm_data_type, int n_dims, + llvm::Value* arr, llvm::Type* arr_type, llvm::Type* llvm_data_type, int n_dims, std::vector>& llvm_dims, llvm::Module* module, bool realloc) { - arr = LLVM::CreateLoad(*builder, arr); + arr = llvm_utils->CreateLoad2(arr_type->getPointerTo(), arr); + llvm_utils->ptr_type[arr] = arr_type; llvm::Value* offset_val = llvm_utils->create_gep(arr, 1); builder->CreateStore(llvm::ConstantInt::get(context, llvm::APInt(32, 0)), offset_val); - llvm::Value* dim_des_val = LLVM::CreateLoad(*builder, llvm_utils->create_gep(arr, 2)); + llvm::Value* dim_des_val = llvm_utils->CreateLoad2(dim_des->getPointerTo(), llvm_utils->create_gep(arr, 2)); llvm::Value* prod = llvm::ConstantInt::get(context, llvm::APInt(32, 1)); for( int r = 0; r < n_dims; r++ ) { - llvm::Value* dim_val = llvm_utils->create_ptr_gep(dim_des_val, r); - llvm::Value* s_val = llvm_utils->create_gep(dim_val, 0); - llvm::Value* l_val = llvm_utils->create_gep(dim_val, 1); - llvm::Value* dim_size_ptr = llvm_utils->create_gep(dim_val, 2); - llvm::Value* first = builder->CreateSExtOrTrunc(llvm_dims[r].first, llvm::Type::getInt32Ty(context)); - llvm::Value* dim_size = builder->CreateSExtOrTrunc(llvm_dims[r].second, llvm::Type::getInt32Ty(context)); + llvm::Type *i32 = llvm::Type::getInt32Ty(context); + llvm::Value* dim_val = llvm_utils->create_ptr_gep2(dim_des, dim_des_val, r); + llvm::Value* s_val = llvm_utils->create_gep2(dim_des, dim_val, 0); + llvm::Value* l_val = llvm_utils->create_gep2(dim_des, dim_val, 1); + llvm::Value* dim_size_ptr = llvm_utils->create_gep2(dim_des, dim_val, 2); + llvm::Value* first = builder->CreateSExtOrTrunc(llvm_dims[r].first, i32); + llvm::Value* dim_size = builder->CreateSExtOrTrunc(llvm_dims[r].second, i32); builder->CreateStore(prod, s_val); builder->CreateStore(first, l_val); builder->CreateStore(dim_size, dim_size_ptr); prod = builder->CreateMul(prod, dim_size); } llvm::Value* ptr2firstptr = get_pointer_to_data(arr); - llvm::AllocaInst *arg_size = builder->CreateAlloca(llvm::Type::getInt32Ty(context), nullptr); + llvm::AllocaInst *arg_size = llvm_utils->CreateAlloca(*builder, llvm::Type::getInt32Ty(context)); llvm::DataLayout data_layout(module); llvm::Type* ptr_type = llvm_data_type->getPointerTo(); uint64_t size = data_layout.getTypeAllocSize(llvm_data_type); @@ -362,23 +380,36 @@ namespace LCompilers { llvm::Value* ptr_as_char_ptr = nullptr; if( realloc ) { ptr_as_char_ptr = lfortran_realloc(context, *module, - *builder, LLVM::CreateLoad(*builder, ptr2firstptr), - LLVM::CreateLoad(*builder, arg_size)); + *builder, llvm_utils->CreateLoad2(llvm_data_type->getPointerTo(), ptr2firstptr), + llvm_utils->CreateLoad(arg_size)); } else { ptr_as_char_ptr = lfortran_malloc(context, *module, - *builder, LLVM::CreateLoad(*builder, arg_size)); + *builder, llvm_utils->CreateLoad(arg_size)); } llvm::Value* first_ptr = builder->CreateBitCast(ptr_as_char_ptr, ptr_type); builder->CreateStore(first_ptr, ptr2firstptr); } void SimpleCMODescriptor::fill_dimension_descriptor( - llvm::Value* arr, int n_dims) { + llvm::Value* arr, int n_dims,llvm::Module* module ,ASR::ttype_t* type ) { llvm::Value* dim_des_val = llvm_utils->create_gep(arr, 2); - llvm::Value* llvm_ndims = builder->CreateAlloca(llvm::Type::getInt32Ty(context), nullptr); + llvm::Value* llvm_ndims = llvm_utils->CreateAlloca(*builder, llvm::Type::getInt32Ty(context)); builder->CreateStore(llvm::ConstantInt::get(context, llvm::APInt(32, n_dims)), llvm_ndims); - llvm::Value* dim_des_first = builder->CreateAlloca(dim_des, - LLVM::CreateLoad(*builder, llvm_ndims)); + llvm::Value* dim_des_first; + if(type && ASR::is_a(*type)){ + std::vector idx_vec = { + llvm::ConstantInt::get(context, llvm::APInt(32, 1))}; + llvm::Value* null_dim_des_ptr = llvm::ConstantPointerNull::get(dim_des->getPointerTo()); + llvm::Value* size_of_dim_des_struct = llvm_utils->CreateGEP2(dim_des, null_dim_des_ptr, idx_vec); + llvm::Value* size_of_dim_des_struct_casted = builder->CreatePtrToInt(size_of_dim_des_struct, llvm::Type::getInt32Ty(context)); //cast to int32 + llvm::Value* size_mul_ndim = builder->CreateMul(size_of_dim_des_struct_casted, llvm::ConstantInt::get(context, llvm::APInt(32, n_dims))); + llvm::Value* struct_ptr = LLVMArrUtils::lfortran_malloc( + context, *module, *builder, size_mul_ndim); + dim_des_first = builder->CreateBitCast(struct_ptr, dim_des->getPointerTo()); + } else { + dim_des_first = llvm_utils->CreateAlloca(*builder, dim_des, + llvm_utils->CreateLoad(llvm_ndims)); + } builder->CreateStore(dim_des_first, dim_des_val); builder->CreateStore(llvm::ConstantInt::get(context, llvm::APInt(32, n_dims)), get_rank(arr, true)); } @@ -387,23 +418,23 @@ namespace LCompilers { llvm::Value* offset_val = llvm_utils->create_gep(arr, 1); builder->CreateStore(llvm::ConstantInt::get(context, llvm::APInt(32, 0)), offset_val); llvm::Value* dim_des_val = llvm_utils->create_gep(arr, 2); - llvm::Value* llvm_ndims = builder->CreateAlloca(llvm::Type::getInt32Ty(context), nullptr); + llvm::Value* llvm_ndims = llvm_utils->CreateAlloca(*builder, llvm::Type::getInt32Ty(context), nullptr); builder->CreateStore(llvm::ConstantInt::get(context, llvm::APInt(32, n_dims)), llvm_ndims); - llvm::Value* dim_des_first = builder->CreateAlloca(dim_des, - LLVM::CreateLoad(*builder, llvm_ndims)); + llvm::Value* dim_des_first = llvm_utils->CreateAlloca(*builder, dim_des, + llvm_utils->CreateLoad(llvm_ndims)); builder->CreateStore(llvm::ConstantInt::get(context, llvm::APInt(32, n_dims)), get_rank(arr, true)); builder->CreateStore(dim_des_first, dim_des_val); - dim_des_val = LLVM::CreateLoad(*builder, dim_des_val); + dim_des_val = llvm_utils->CreateLoad2(dim_des->getPointerTo(), dim_des_val); llvm::Value* source_dim_des_arr = this->get_pointer_to_dimension_descriptor_array(source_arr); for( int r = 0; r < n_dims; r++ ) { - llvm::Value* dim_val = llvm_utils->create_ptr_gep(dim_des_val, r); - llvm::Value* s_val = llvm_utils->create_gep(dim_val, 0); + llvm::Value* dim_val = llvm_utils->create_ptr_gep2(dim_des, dim_des_val, r); + llvm::Value* s_val = llvm_utils->create_gep2(dim_des, dim_val, 0); llvm::Value* stride = this->get_stride( this->get_pointer_to_dimension_descriptor(source_dim_des_arr, llvm::ConstantInt::get(context, llvm::APInt(32, r)))); builder->CreateStore(stride, s_val); - llvm::Value* l_val = llvm_utils->create_gep(dim_val, 1); - llvm::Value* dim_size_ptr = llvm_utils->create_gep(dim_val, 2); + llvm::Value* l_val = llvm_utils->create_gep2(dim_des, dim_val, 1); + llvm::Value* dim_size_ptr = llvm_utils->create_gep2(dim_des, dim_val, 2); builder->CreateStore(llvm::ConstantInt::get(context, llvm::APInt(32, 1)), l_val); llvm::Value* dim_size = this->get_dimension_size( this->get_pointer_to_dimension_descriptor(source_dim_des_arr, @@ -413,11 +444,11 @@ namespace LCompilers { } void SimpleCMODescriptor::fill_descriptor_for_array_section( - llvm::Value* value_desc, llvm::Value* target, + llvm::Value* value_desc, llvm::Type *value_el_type, llvm::Value* target, llvm::Value** lbs, llvm::Value** ubs, llvm::Value** ds, llvm::Value** non_sliced_indices, int value_rank, int target_rank) { - llvm::Value* value_desc_data = LLVM::CreateLoad(*builder, get_pointer_to_data(value_desc)); + llvm::Value* value_desc_data = llvm_utils->CreateLoad2(value_el_type->getPointerTo(), get_pointer_to_data(value_desc)); std::vector section_first_indices; for( int i = 0; i < value_rank; i++ ) { if( ds[i] != nullptr ) { @@ -430,7 +461,7 @@ namespace LCompilers { } llvm::Value* target_offset = cmo_convertor_single_element( value_desc, section_first_indices, value_rank, false); - value_desc_data = llvm_utils->create_ptr_gep(value_desc_data, target_offset); + value_desc_data = llvm_utils->create_ptr_gep2(value_el_type, value_desc_data, target_offset); llvm::Value* target_data = get_pointer_to_data(target); builder->CreateStore(value_desc_data, target_data); @@ -451,8 +482,8 @@ namespace LCompilers { llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), llvm::APInt(32, 1)) ); - llvm::Value* value_dim_des = llvm_utils->create_ptr_gep(value_dim_des_array, i); - llvm::Value* target_dim_des = llvm_utils->create_ptr_gep(target_dim_des_array, j); + llvm::Value* value_dim_des = llvm_utils->create_ptr_gep2(dim_des, value_dim_des_array, i); + llvm::Value* target_dim_des = llvm_utils->create_ptr_gep2(dim_des, target_dim_des_array, j); llvm::Value* value_stride = get_stride(value_dim_des, true); llvm::Value* target_stride = get_stride(target_dim_des, false); builder->CreateStore(builder->CreateMul(value_stride, builder->CreateZExtOrTrunc( @@ -473,7 +504,7 @@ namespace LCompilers { } void SimpleCMODescriptor::fill_descriptor_for_array_section_data_only( - llvm::Value* value_desc, llvm::Value* target, + llvm::Value* value_desc, llvm::Type* value_el_type, llvm::Value* target, llvm::Value** lbs, llvm::Value** ubs, llvm::Value** ds, llvm::Value** non_sliced_indices, llvm::Value** llvm_diminfo, int value_rank, int target_rank) { @@ -489,7 +520,7 @@ namespace LCompilers { } llvm::Value* target_offset = cmo_convertor_single_element_data_only( llvm_diminfo, section_first_indices, value_rank, false); - value_desc = llvm_utils->create_ptr_gep(value_desc, target_offset); + value_desc = llvm_utils->create_ptr_gep2(value_el_type, value_desc, target_offset); builder->CreateStore(value_desc, get_pointer_to_data(target)); builder->CreateStore( @@ -509,7 +540,7 @@ namespace LCompilers { llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), llvm::APInt(32, 1)) ); - llvm::Value* target_dim_des = llvm_utils->create_ptr_gep(target_dim_des_array, j); + llvm::Value* target_dim_des = llvm_utils->create_ptr_gep2(dim_des, target_dim_des_array, j); builder->CreateStore(builder->CreateMul(stride, builder->CreateZExtOrTrunc( ds[i], llvm::Type::getInt32Ty(context))), get_stride(target_dim_des, false)); builder->CreateStore(llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), llvm::APInt(32, 1)), @@ -530,7 +561,7 @@ namespace LCompilers { llvm::Value* SimpleCMODescriptor::get_pointer_to_dimension_descriptor(llvm::Value* dim_des_arr, llvm::Value* dim) { - return llvm_utils->create_ptr_gep(dim_des_arr, dim); + return llvm_utils->create_ptr_gep2(dim_des, dim_des_arr, dim); } llvm::Value* SimpleCMODescriptor::get_pointer_to_data(llvm::Value* arr) { @@ -542,30 +573,34 @@ namespace LCompilers { if( !load ) { return offset; } - return LLVM::CreateLoad(*builder, offset); + llvm::Type *i32 = llvm::Type::getInt32Ty(context); + return llvm_utils->CreateLoad2(i32, offset); } - llvm::Value* SimpleCMODescriptor::get_lower_bound(llvm::Value* dim_des, bool load) { - llvm::Value* lb = llvm_utils->create_gep(dim_des, 1); + llvm::Value* SimpleCMODescriptor::get_lower_bound(llvm::Value* dims, bool load) { + llvm::Value* lb = llvm_utils->create_gep2(dim_des, dims, 1); if( !load ) { return lb; } - return LLVM::CreateLoad(*builder, lb); + llvm::Type *i32 = llvm::Type::getInt32Ty(context); + return llvm_utils->CreateLoad2(i32, lb); } - llvm::Value* SimpleCMODescriptor::get_upper_bound(llvm::Value* dim_des) { - llvm::Value* lb = LLVM::CreateLoad(*builder, llvm_utils->create_gep(dim_des, 1)); - llvm::Value* dim_size = LLVM::CreateLoad(*builder, llvm_utils->create_gep(dim_des, 2)); + llvm::Value* SimpleCMODescriptor::get_upper_bound(llvm::Value* dims) { + llvm::Type *i32 = llvm::Type::getInt32Ty(context); + llvm::Value* lb = llvm_utils->CreateLoad2(i32, llvm_utils->create_gep2(dim_des, dims, 1)); + llvm::Value* dim_size = llvm_utils->CreateLoad2(i32, llvm_utils->create_gep2(dim_des, dims, 2)); return builder->CreateSub(builder->CreateAdd(dim_size, lb), llvm::ConstantInt::get(context, llvm::APInt(32, 1))); } - llvm::Value* SimpleCMODescriptor::get_stride(llvm::Value* dim_des, bool load) { - llvm::Value* stride = llvm_utils->create_gep(dim_des, 0); + llvm::Value* SimpleCMODescriptor::get_stride(llvm::Value* dims, bool load) { + llvm::Value* stride = llvm_utils->create_gep2(dim_des, dims, 0); if( !load ) { return stride; } - return LLVM::CreateLoad(*builder, stride); + llvm::Type *i32 = llvm::Type::getInt32Ty(context); + return llvm_utils->CreateLoad2(i32, stride); } // TODO: Uncomment and implement later @@ -575,22 +610,23 @@ namespace LCompilers { llvm::Value* SimpleCMODescriptor::cmo_convertor_single_element( llvm::Value* arr, std::vector& m_args, int n_args, bool check_for_bounds) { - llvm::Value* dim_des_arr_ptr = LLVM::CreateLoad(*builder, llvm_utils->create_gep(arr, 2)); + llvm::Value* dim_des_arr_ptr = llvm_utils->CreateLoad2(dim_des->getPointerTo(), llvm_utils->create_gep(arr, 2)); llvm::Value* idx = llvm::ConstantInt::get(context, llvm::APInt(32, 0)); + llvm::Type *i32 = llvm::Type::getInt32Ty(context); for( int r = 0; r < n_args; r++ ) { llvm::Value* curr_llvm_idx = m_args[r]; - llvm::Value* dim_des_ptr = llvm_utils->create_ptr_gep(dim_des_arr_ptr, r); - llvm::Value* lval = LLVM::CreateLoad(*builder, llvm_utils->create_gep(dim_des_ptr, 1)); + llvm::Value* dim_des_ptr = llvm_utils->create_ptr_gep2(dim_des, dim_des_arr_ptr, r); + llvm::Value* lval = llvm_utils->CreateLoad2(i32, llvm_utils->create_gep2(dim_des, dim_des_ptr, 1)); // first cast curr_llvm_idx to 32 bit curr_llvm_idx = builder->CreateSExtOrTrunc(curr_llvm_idx, llvm::Type::getInt32Ty(context)); curr_llvm_idx = builder->CreateSub(curr_llvm_idx, lval); if( check_for_bounds ) { // check_single_element(curr_llvm_idx, arr); TODO: To be implemented } - llvm::Value* stride = LLVM::CreateLoad(*builder, llvm_utils->create_gep(dim_des_ptr, 0)); + llvm::Value* stride = llvm_utils->CreateLoad2(i32, llvm_utils->create_gep2(dim_des, dim_des_ptr, 0)); idx = builder->CreateAdd(idx, builder->CreateMul(stride, curr_llvm_idx)); } - llvm::Value* offset_val = LLVM::CreateLoad(*builder, llvm_utils->create_gep(arr, 1)); + llvm::Value* offset_val = llvm_utils->CreateLoad2(i32, llvm_utils->create_gep(arr, 1)); return builder->CreateAdd(idx, offset_val); } @@ -620,7 +656,7 @@ namespace LCompilers { return idx; } - llvm::Value* SimpleCMODescriptor::get_single_element(llvm::Value* array, + llvm::Value* SimpleCMODescriptor::get_single_element(llvm::Type *type, llvm::Value* array, std::vector& m_args, int n_args, bool data_only, bool is_fixed_size, llvm::Value** llvm_diminfo, bool polymorphic, llvm::Type* polymorphic_type, bool is_unbounded_pointer_to_data) { @@ -633,19 +669,19 @@ namespace LCompilers { LCOMPILERS_ASSERT(llvm_diminfo); idx = cmo_convertor_single_element_data_only(llvm_diminfo, m_args, n_args, check_for_bounds, is_unbounded_pointer_to_data); if( is_fixed_size ) { - tmp = llvm_utils->create_gep(array, idx); + tmp = llvm_utils->create_gep2(type, array, idx); } else { - tmp = llvm_utils->create_ptr_gep(array, idx); + tmp = llvm_utils->create_ptr_gep2(type, array, idx); } } else { idx = cmo_convertor_single_element(array, m_args, n_args, check_for_bounds); llvm::Value* full_array = get_pointer_to_data(array); if( polymorphic ) { - full_array = llvm_utils->create_gep(LLVM::CreateLoad(*builder, full_array), 1); - full_array = builder->CreateBitCast(LLVM::CreateLoad(*builder, full_array), polymorphic_type); - tmp = llvm_utils->create_ptr_gep(full_array, idx); + full_array = llvm_utils->create_gep2(type, llvm_utils->CreateLoad2(type->getPointerTo(), full_array), 1); + full_array = builder->CreateBitCast(llvm_utils->CreateLoad2(llvm::Type::getVoidTy(context)->getPointerTo(), full_array), polymorphic_type->getPointerTo()); + tmp = llvm_utils->create_ptr_gep2(polymorphic_type, full_array, idx); } else { - tmp = llvm_utils->create_ptr_gep(LLVM::CreateLoad(*builder, full_array), idx); + tmp = llvm_utils->create_ptr_gep2(type, llvm_utils->CreateLoad2(type->getPointerTo(), full_array), idx); } } return tmp; @@ -654,7 +690,7 @@ namespace LCompilers { llvm::Value* SimpleCMODescriptor::get_is_allocated_flag(llvm::Value* array, llvm::Type* llvm_data_type) { return builder->CreateICmpNE( - builder->CreatePtrToInt(LLVM::CreateLoad(*builder, get_pointer_to_data(array)), + builder->CreatePtrToInt(llvm_utils->CreateLoad2(llvm_data_type->getPointerTo(), get_pointer_to_data(array)), llvm::Type::getInt64Ty(context)), builder->CreatePtrToInt(llvm::ConstantPointerNull::get(llvm_data_type->getPointerTo()), llvm::Type::getInt64Ty(context)) @@ -678,28 +714,25 @@ namespace LCompilers { tmp = builder->CreateSExtOrTrunc(tmp, llvm_utils->getIntType(kind)); return tmp; } - llvm::BasicBlock &entry_block = builder->GetInsertBlock()->getParent()->getEntryBlock(); - llvm::IRBuilder<> builder0(context); - builder0.SetInsertPoint(&entry_block, entry_block.getFirstInsertionPt()); llvm::Value* rank = this->get_rank(array); - llvm::Value* llvm_size = builder0.CreateAlloca(llvm_utils->getIntType(kind), nullptr); + llvm::Value* llvm_size = llvm_utils->CreateAlloca(llvm_utils->getIntType(kind)); builder->CreateStore(llvm::ConstantInt::get(context, llvm::APInt(kind * 8, 1)), llvm_size); llvm::BasicBlock *loophead = llvm::BasicBlock::Create(context, "loop.head"); llvm::BasicBlock *loopbody = llvm::BasicBlock::Create(context, "loop.body"); llvm::BasicBlock *loopend = llvm::BasicBlock::Create(context, "loop.end"); - llvm::Value* r = builder0.CreateAlloca(llvm_utils->getIntType(4), nullptr); + llvm::Value* r = llvm_utils->CreateAlloca(llvm_utils->getIntType(4)); builder->CreateStore(llvm::ConstantInt::get(context, llvm::APInt(32, 0)), r); // head llvm_utils->start_new_block(loophead); - llvm::Value *cond = builder->CreateICmpSLT(LLVM::CreateLoad(*builder, r), rank); + llvm::Value *cond = builder->CreateICmpSLT(llvm_utils->CreateLoad(r), rank); builder->CreateCondBr(cond, loopbody, loopend); // body llvm_utils->start_new_block(loopbody); - llvm::Value* r_val = LLVM::CreateLoad(*builder, r); - llvm::Value* ret_val = LLVM::CreateLoad(*builder, llvm_size); + llvm::Value* r_val = llvm_utils->CreateLoad(r); + llvm::Value* ret_val = llvm_utils->CreateLoad(llvm_size); llvm::Value* dim_size = this->get_dimension_size(dim_des_val, r_val); dim_size = builder->CreateSExtOrTrunc(dim_size, llvm_utils->getIntType(kind)); ret_val = builder->CreateMul(ret_val, dim_size); @@ -711,20 +744,25 @@ namespace LCompilers { // end llvm_utils->start_new_block(loopend); - tmp = LLVM::CreateLoad(*builder, llvm_size); + tmp = llvm_utils->CreateLoad(llvm_size); return tmp; } llvm::Value* SimpleCMODescriptor::reshape(llvm::Value* array, llvm::Type* llvm_data_type, llvm::Value* shape, ASR::ttype_t* asr_shape_type, llvm::Module* module) { - llvm::Value* reshaped = builder->CreateAlloca(array->getType()->getContainedType(0), nullptr, "reshaped"); +#if LLVM_VERSION_MAJOR > 16 + llvm::Type *arr_type = llvm_utils->ptr_type[array]; +#else + llvm::Type *arr_type = array->getType()->getContainedType(0); +#endif + llvm::Value* reshaped = llvm_utils->CreateAlloca(*builder, arr_type, nullptr, "reshaped"); // Deep copy data from array to reshaped. llvm::Value* num_elements = this->get_array_size(array, nullptr, 4); llvm::Value* first_ptr = this->get_pointer_to_data(reshaped); - llvm::Value* arr_first = builder->CreateAlloca(llvm_data_type, num_elements); + llvm::Value* arr_first = llvm_utils->CreateAlloca(*builder, llvm_data_type, num_elements); builder->CreateStore(arr_first, first_ptr); llvm::Value* ptr2firstptr = this->get_pointer_to_data(array); @@ -732,8 +770,8 @@ namespace LCompilers { uint64_t size = data_layout.getTypeAllocSize(llvm_data_type); llvm::Value* llvm_size = llvm::ConstantInt::get(context, llvm::APInt(32, size)); num_elements = builder->CreateMul(num_elements, llvm_size); - builder->CreateMemCpy(LLVM::CreateLoad(*builder, first_ptr), llvm::MaybeAlign(), - LLVM::CreateLoad(*builder, ptr2firstptr), llvm::MaybeAlign(), + builder->CreateMemCpy(llvm_utils->CreateLoad2(llvm_data_type->getPointerTo(), first_ptr), llvm::MaybeAlign(), + llvm_utils->CreateLoad2(llvm_data_type->getPointerTo(), ptr2firstptr), llvm::MaybeAlign(), num_elements); builder->CreateStore( @@ -741,39 +779,40 @@ namespace LCompilers { this->get_offset(reshaped, false)); if( this->is_array(asr_shape_type) ) { - builder->CreateStore(LLVM::CreateLoad(*builder, llvm_utils->create_gep(array, 1)), + llvm::Type *i32 = llvm::Type::getInt32Ty(context); + builder->CreateStore(llvm_utils->CreateLoad2(i32, llvm_utils->create_gep(array, 1)), llvm_utils->create_gep(reshaped, 1)); llvm::Value* n_dims = this->get_array_size(shape, nullptr, 4); - llvm::Value* shape_data = LLVM::CreateLoad(*builder, this->get_pointer_to_data(shape)); + llvm::Value* shape_data = llvm_utils->CreateLoad2(i32->getPointerTo(), this->get_pointer_to_data(shape)); llvm::Value* dim_des_val = llvm_utils->create_gep(reshaped, 2); - llvm::Value* dim_des_first = builder->CreateAlloca(dim_des, n_dims); + llvm::Value* dim_des_first = llvm_utils->CreateAlloca(*builder, dim_des, n_dims); builder->CreateStore(n_dims, this->get_rank(reshaped, true)); builder->CreateStore(dim_des_first, dim_des_val); - llvm::Value* prod = builder->CreateAlloca(llvm_utils->getIntType(4)); + llvm::Value* prod = llvm_utils->CreateAlloca(*builder, llvm_utils->getIntType(4)); builder->CreateStore(llvm::ConstantInt::get(context, llvm::APInt(32, 1)), prod); - dim_des_val = LLVM::CreateLoad(*builder, dim_des_val); + dim_des_val = llvm_utils->CreateLoad2(dim_des->getPointerTo(), dim_des_val); llvm::BasicBlock *loophead = llvm::BasicBlock::Create(context, "loop.head"); llvm::BasicBlock *loopbody = llvm::BasicBlock::Create(context, "loop.body"); llvm::BasicBlock *loopend = llvm::BasicBlock::Create(context, "loop.end"); - llvm::Value* r = builder->CreateAlloca(llvm_utils->getIntType(4), nullptr); + llvm::Value* r = llvm_utils->CreateAlloca(*builder, llvm_utils->getIntType(4)); builder->CreateStore(llvm::ConstantInt::get(context, llvm::APInt(32, 0)), r); // head llvm_utils->start_new_block(loophead); - llvm::Value *cond = builder->CreateICmpSLT(LLVM::CreateLoad(*builder, r), n_dims); + llvm::Value *cond = builder->CreateICmpSLT(llvm_utils->CreateLoad(r), n_dims); builder->CreateCondBr(cond, loopbody, loopend); // body llvm_utils->start_new_block(loopbody); - llvm::Value* r_val = LLVM::CreateLoad(*builder, r); - llvm::Value* dim_val = llvm_utils->create_ptr_gep(dim_des_val, r_val); - llvm::Value* s_val = llvm_utils->create_gep(dim_val, 0); - llvm::Value* l_val = llvm_utils->create_gep(dim_val, 1); - llvm::Value* dim_size_ptr = llvm_utils->create_gep(dim_val, 2); + llvm::Value* r_val = llvm_utils->CreateLoad(r); + llvm::Value* dim_val = llvm_utils->create_ptr_gep2(dim_des, dim_des_val, r_val); + llvm::Value* s_val = llvm_utils->create_gep2(dim_des, dim_val, 0); + llvm::Value* l_val = llvm_utils->create_gep2(dim_des, dim_val, 1); + llvm::Value* dim_size_ptr = llvm_utils->create_gep2(dim_des, dim_val, 2); builder->CreateStore(llvm::ConstantInt::get(context, llvm::APInt(32, 1)), l_val); - builder->CreateStore(LLVM::CreateLoad(*builder, prod), s_val); - llvm::Value* dim_size = LLVM::CreateLoad(*builder, llvm_utils->create_ptr_gep(shape_data, r_val)); - builder->CreateStore(builder->CreateMul(LLVM::CreateLoad(*builder, prod), dim_size), prod); + builder->CreateStore(llvm_utils->CreateLoad(prod), s_val); + llvm::Value* dim_size = builder->CreateSExtOrTrunc(llvm_utils->CreateLoad2(i32, llvm_utils->create_ptr_gep2(i32, shape_data, r_val)), i32); + builder->CreateStore(builder->CreateMul(llvm_utils->CreateLoad(prod), dim_size), prod); builder->CreateStore(dim_size, dim_size_ptr); r_val = builder->CreateAdd(r_val, llvm::ConstantInt::get(context, llvm::APInt(32, 1))); builder->CreateStore(r_val, r); @@ -787,15 +826,14 @@ namespace LCompilers { // Shallow copies source array descriptor to destination descriptor void SimpleCMODescriptor::copy_array(llvm::Value* src, llvm::Value* dest, - llvm::Module* module, ASR::ttype_t* asr_data_type, bool create_dim_des_array, - bool reserve_memory) { + llvm::Module* module, ASR::ttype_t* asr_data_type, bool reserve_memory) { llvm::Value* num_elements = this->get_array_size(src, nullptr, 4); llvm::Value* first_ptr = this->get_pointer_to_data(dest); llvm::Type* llvm_data_type = tkr2array[ASRUtils::get_type_code(ASRUtils::type_get_past_pointer( ASRUtils::type_get_past_allocatable(asr_data_type)), false, false)].second; if( reserve_memory ) { - llvm::Value* arr_first = builder->CreateAlloca(llvm_data_type, num_elements); + llvm::Value* arr_first = llvm_utils->CreateAlloca(*builder, llvm_data_type, num_elements); builder->CreateStore(arr_first, first_ptr); } @@ -804,59 +842,36 @@ namespace LCompilers { uint64_t size = data_layout.getTypeAllocSize(llvm_data_type); llvm::Value* llvm_size = llvm::ConstantInt::get(context, llvm::APInt(32, size)); num_elements = builder->CreateMul(num_elements, llvm_size); - builder->CreateMemCpy(LLVM::CreateLoad(*builder, first_ptr), llvm::MaybeAlign(), - LLVM::CreateLoad(*builder, ptr2firstptr), llvm::MaybeAlign(), + builder->CreateMemCpy(llvm_utils->CreateLoad2(llvm_data_type->getPointerTo(), first_ptr), llvm::MaybeAlign(), + llvm_utils->CreateLoad2(llvm_data_type->getPointerTo(), ptr2firstptr), llvm::MaybeAlign(), num_elements); llvm::Value* src_dim_des_val = this->get_pointer_to_dimension_descriptor_array(src, true); llvm::Value* n_dims = this->get_rank(src, false); llvm::Value* dest_dim_des_val = nullptr; - if( !create_dim_des_array ) { - dest_dim_des_val = this->get_pointer_to_dimension_descriptor_array(dest, true); - } else { - llvm::Value* src_offset_ptr = LLVM::CreateLoad(*builder, llvm_utils->create_gep(src, 1)); - builder->CreateStore(src_offset_ptr, llvm_utils->create_gep(dest, 1)); - llvm::Value* dest_dim_des_ptr = this->get_pointer_to_dimension_descriptor_array(dest, false); - dest_dim_des_val = builder->CreateAlloca(dim_des, n_dims); - builder->CreateStore(dest_dim_des_val, dest_dim_des_ptr); - } + dest_dim_des_val = this->get_pointer_to_dimension_descriptor_array(dest, true); llvm::BasicBlock *loophead = llvm::BasicBlock::Create(context, "loop.head"); llvm::BasicBlock *loopbody = llvm::BasicBlock::Create(context, "loop.body"); llvm::BasicBlock *loopend = llvm::BasicBlock::Create(context, "loop.end"); - llvm::Value* r = builder->CreateAlloca(llvm_utils->getIntType(4), nullptr); + + // Loop to copy `dimension_descriptor` from src to dest + llvm::Value* r = llvm_utils->CreateAlloca(*builder, llvm_utils->getIntType(4)); builder->CreateStore(llvm::ConstantInt::get(context, llvm::APInt(32, 0)), r); // head llvm_utils->start_new_block(loophead); - llvm::Value *cond = builder->CreateICmpSLT(LLVM::CreateLoad(*builder, r), n_dims); + llvm::Value *cond = builder->CreateICmpSLT(llvm_utils->CreateLoad(r), n_dims); builder->CreateCondBr(cond, loopbody, loopend); // body llvm_utils->start_new_block(loopbody); - llvm::Value* r_val = LLVM::CreateLoad(*builder, r); - llvm::Value* src_dim_val = llvm_utils->create_ptr_gep(src_dim_des_val, r_val); - llvm::Value* src_l_val = nullptr; - llvm::Value* src_s_val = nullptr; - if( create_dim_des_array ) { - src_s_val = llvm_utils->create_gep(src_dim_val, 0); - src_l_val = llvm_utils->create_gep(src_dim_val, 1); - } - llvm::Value* src_dim_size_ptr = llvm_utils->create_gep(src_dim_val, 2); - llvm::Value* dest_dim_val = llvm_utils->create_ptr_gep(dest_dim_des_val, r_val); - llvm::Value* dest_s_val = nullptr; - llvm::Value* dest_l_val = nullptr; - llvm::Value* dest_dim_size_ptr = nullptr; - if( create_dim_des_array ) { - dest_s_val = llvm_utils->create_gep(dest_dim_val, 0); - dest_l_val = llvm_utils->create_gep(dest_dim_val, 1); - dest_dim_size_ptr = llvm_utils->create_gep(dest_dim_val, 2); - } - - if( create_dim_des_array ) { - builder->CreateStore(LLVM::CreateLoad(*builder, src_l_val), dest_l_val); - builder->CreateStore(LLVM::CreateLoad(*builder, src_s_val), dest_s_val); - builder->CreateStore(LLVM::CreateLoad(*builder, src_dim_size_ptr), dest_dim_size_ptr); - } + llvm::Value* r_val = llvm_utils->CreateLoad(r); + llvm::Value* src_dim_val = llvm_utils->create_ptr_gep2(dim_des, src_dim_des_val, r_val); + llvm::Value* dest_dim_val = llvm_utils->create_ptr_gep2(dim_des, dest_dim_des_val, r_val); + builder->CreateMemCpy(dest_dim_val, llvm::MaybeAlign(), + src_dim_val, llvm::MaybeAlign(), + llvm::ConstantInt::get( + context, llvm::APInt(32, data_layout.getTypeAllocSize(dim_des)))); r_val = builder->CreateAdd(r_val, llvm::ConstantInt::get(context, llvm::APInt(32, 1))); builder->CreateStore(r_val, r); builder->CreateBr(loophead); diff --git a/src/libasr/codegen/llvm_array_utils.h b/src/libasr/codegen/llvm_array_utils.h index 155225b57e..7b144f2427 100644 --- a/src/libasr/codegen/llvm_array_utils.h +++ b/src/libasr/codegen/llvm_array_utils.h @@ -141,7 +141,7 @@ namespace LCompilers { virtual void fill_array_details( llvm::Value* source, llvm::Value* destination, - ASR::ttype_t* asr_shape_type, bool ignore_data) = 0; + ASR::ttype_t* source_array_type, ASR::ttype_t* dest_array_type, llvm::Module* module, bool ignore_data) = 0; /* * Fills the elements of the input array descriptor @@ -149,13 +149,13 @@ namespace LCompilers { */ virtual void fill_malloc_array_details( - llvm::Value* arr, llvm::Type* llvm_data_type, int n_dims, + llvm::Value* arr, llvm::Type *arr_type, llvm::Type* llvm_data_type, int n_dims, std::vector>& llvm_dims, llvm::Module* module, bool realloc=false) = 0; virtual void fill_dimension_descriptor( - llvm::Value* arr, int n_dims) = 0; + llvm::Value* arr, int n_dims, llvm::Module* module,ASR::ttype_t* type) = 0; virtual void reset_array_details( @@ -163,14 +163,14 @@ namespace LCompilers { virtual void fill_descriptor_for_array_section( - llvm::Value* value_desc, llvm::Value* target, + llvm::Value* value_desc, llvm::Type* value_el_type, llvm::Value* target, llvm::Value** lbs, llvm::Value** ubs, llvm::Value** ds, llvm::Value** non_sliced_indices, int value_rank, int target_rank) = 0; virtual void fill_descriptor_for_array_section_data_only( - llvm::Value* value_desc, llvm::Value* target, + llvm::Value* value_desc, llvm::Type* value_el_type, llvm::Value* target, llvm::Value** lbs, llvm::Value** ubs, llvm::Value** ds, llvm::Value** non_sliced_indices, llvm::Value** llvm_diminfo, int value_rank, int target_rank) = 0; @@ -232,7 +232,7 @@ namespace LCompilers { llvm::Value* dim, bool load=true) = 0; virtual - llvm::Value* get_dimension_size(llvm::Value* dim_des, + llvm::Value* get_dimension_size(llvm::Value* dim_des_arr, bool load=true) = 0; virtual @@ -246,6 +246,9 @@ namespace LCompilers { * in the input array descriptor according to the rules * implemented by current class. */ + virtual + llvm::Value* get_pointer_to_dimension_descriptor_array(llvm::Type *type, llvm::Value* arr, bool load=true) = 0; + virtual llvm::Value* get_pointer_to_dimension_descriptor_array(llvm::Value* arr, bool load=true) = 0; @@ -264,7 +267,7 @@ namespace LCompilers { * to the rules implemented by current class. */ virtual - llvm::Value* get_single_element(llvm::Value* array, + llvm::Value* get_single_element(llvm::Type *type, llvm::Value* array, std::vector& m_args, int n_args, bool data_only=false, bool is_fixed_size=false, llvm::Value** llvm_diminfo=nullptr, @@ -285,7 +288,7 @@ namespace LCompilers { virtual void copy_array(llvm::Value* src, llvm::Value* dest, llvm::Module* module, ASR::ttype_t* asr_data_type, - bool create_dim_des_array, bool reserve_memory) = 0; + bool reserve_memory) = 0; virtual void copy_array_data_only(llvm::Value* src, llvm::Value* dest, @@ -362,17 +365,17 @@ namespace LCompilers { virtual void fill_array_details( llvm::Value* source, llvm::Value* destination, - ASR::ttype_t* asr_shape_type, bool ignore_data); + ASR::ttype_t* source_array_type, ASR::ttype_t* dest_array_type, llvm::Module* module, bool ignore_data); virtual void fill_malloc_array_details( - llvm::Value* arr, llvm::Type* llvm_data_type, int n_dims, + llvm::Value* arr, llvm::Type *arr_type, llvm::Type* llvm_data_type, int n_dims, std::vector>& llvm_dims, llvm::Module* module, bool realloc=false); virtual void fill_dimension_descriptor( - llvm::Value* arr, int n_dims); + llvm::Value* arr, int n_dims, llvm::Module* module, ASR::ttype_t* type); virtual void reset_array_details( @@ -380,14 +383,14 @@ namespace LCompilers { virtual void fill_descriptor_for_array_section( - llvm::Value* value_desc, llvm::Value* target, + llvm::Value* value_desc, llvm::Type* value_el_type, llvm::Value* target, llvm::Value** lbs, llvm::Value** ubs, llvm::Value** ds, llvm::Value** non_sliced_indices, int value_rank, int target_rank); virtual void fill_descriptor_for_array_section_data_only( - llvm::Value* value_desc, llvm::Value* target, + llvm::Value* value_desc, llvm::Type* value_el_type, llvm::Value* target, llvm::Value** lbs, llvm::Value** ubs, llvm::Value** ds, llvm::Value** non_sliced_indices, llvm::Value** llvm_diminfo, int value_rank, int target_rank); @@ -418,9 +421,12 @@ namespace LCompilers { llvm::Value* dim, bool load=true); virtual - llvm::Value* get_dimension_size(llvm::Value* dim_des, + llvm::Value* get_dimension_size(llvm::Value* dim_des_arr, bool load=true); + virtual + llvm::Value* get_pointer_to_dimension_descriptor_array(llvm::Type* type, llvm::Value* arr, bool load=true); + virtual llvm::Value* get_pointer_to_dimension_descriptor_array(llvm::Value* arr, bool load=true); @@ -432,7 +438,7 @@ namespace LCompilers { llvm::Value* get_stride(llvm::Value* dim_des, bool load=true); virtual - llvm::Value* get_single_element(llvm::Value* array, + llvm::Value* get_single_element(llvm::Type *type, llvm::Value* array, std::vector& m_args, int n_args, bool data_only=false, bool is_fixed_size=false, llvm::Value** llvm_diminfo=nullptr, @@ -452,7 +458,7 @@ namespace LCompilers { virtual void copy_array(llvm::Value* src, llvm::Value* dest, llvm::Module* module, ASR::ttype_t* asr_data_type, - bool create_dim_des_array, bool reserve_memory); + bool reserve_memory); virtual void copy_array_data_only(llvm::Value* src, llvm::Value* dest, diff --git a/src/libasr/codegen/llvm_utils.cpp b/src/libasr/codegen/llvm_utils.cpp index dde91aa6d9..2e48a92625 100644 --- a/src/libasr/codegen/llvm_utils.cpp +++ b/src/libasr/codegen/llvm_utils.cpp @@ -1,5 +1,3 @@ -#include "llvm_utils.h" -#include #include #include #include @@ -9,42 +7,20 @@ namespace LCompilers { namespace LLVM { - llvm::Value* CreateLoad(llvm::IRBuilder<> &builder, llvm::Value *x) { - llvm::Type *t = x->getType(); - LCOMPILERS_ASSERT(t->isPointerTy()); - llvm::Type *t2 = t->getContainedType(0); - return builder.CreateLoad(t2, x); - } - llvm::Value* CreateStore(llvm::IRBuilder<> &builder, llvm::Value *x, llvm::Value *y) { LCOMPILERS_ASSERT(y->getType()->isPointerTy()); return builder.CreateStore(x, y); } - - llvm::Value* CreateGEP(llvm::IRBuilder<> &builder, llvm::Value *x, std::vector &idx) { - llvm::Type *t = x->getType(); - LCOMPILERS_ASSERT(t->isPointerTy()); - llvm::Type *t2 = t->getContainedType(0); - return builder.CreateGEP(t2, x, idx); - } - - llvm::Value* CreateInBoundsGEP(llvm::IRBuilder<> &builder, llvm::Value *x, std::vector &idx) { - llvm::Type *t = x->getType(); - LCOMPILERS_ASSERT(t->isPointerTy()); - llvm::Type *t2 = t->getContainedType(0); - return builder.CreateInBoundsGEP(t2, x, idx); - } - llvm::Value* lfortran_malloc(llvm::LLVMContext &context, llvm::Module &module, llvm::IRBuilder<> &builder, llvm::Value* arg_size) { std::string func_name = "_lfortran_malloc"; llvm::Function *fn = module.getFunction(func_name); if (!fn) { llvm::FunctionType *function_type = llvm::FunctionType::get( - llvm::Type::getInt8PtrTy(context), { + llvm::Type::getInt8Ty(context)->getPointerTo(), { llvm::Type::getInt32Ty(context) - }, true); + }, false); fn = llvm::Function::Create(function_type, llvm::Function::ExternalLinkage, func_name, module); } @@ -58,10 +34,10 @@ namespace LCompilers { llvm::Function *fn = module.getFunction(func_name); if (!fn) { llvm::FunctionType *function_type = llvm::FunctionType::get( - llvm::Type::getInt8PtrTy(context), { + llvm::Type::getInt8Ty(context)->getPointerTo(), { llvm::Type::getInt32Ty(context), llvm::Type::getInt32Ty(context) - }, true); + }, false); fn = llvm::Function::Create(function_type, llvm::Function::ExternalLinkage, func_name, module); } @@ -75,15 +51,15 @@ namespace LCompilers { llvm::Function *fn = module.getFunction(func_name); if (!fn) { llvm::FunctionType *function_type = llvm::FunctionType::get( - llvm::Type::getInt8PtrTy(context), { - llvm::Type::getInt8PtrTy(context), + llvm::Type::getInt8Ty(context)->getPointerTo(), { + llvm::Type::getInt8Ty(context)->getPointerTo(), llvm::Type::getInt32Ty(context) - }, true); + }, false); fn = llvm::Function::Create(function_type, llvm::Function::ExternalLinkage, func_name, module); } std::vector args = { - builder.CreateBitCast(ptr, llvm::Type::getInt8PtrTy(context)), + builder.CreateBitCast(ptr, llvm::Type::getInt8Ty(context)->getPointerTo()), arg_size }; return builder.CreateCall(fn, args); @@ -96,13 +72,13 @@ namespace LCompilers { if (!fn) { llvm::FunctionType *function_type = llvm::FunctionType::get( llvm::Type::getVoidTy(context), { - llvm::Type::getInt8PtrTy(context) - }, true); + llvm::Type::getInt8Ty(context)->getPointerTo() + }, false); fn = llvm::Function::Create(function_type, llvm::Function::ExternalLinkage, func_name, module); } std::vector args = { - builder.CreateBitCast(ptr, llvm::Type::getInt8PtrTy(context)), + builder.CreateBitCast(ptr, llvm::Type::getInt8Ty(context)->getPointerTo()), }; return builder.CreateCall(fn, args); } @@ -117,12 +93,13 @@ namespace LCompilers { std::map>& name2memidx_, CompilerOptions &compiler_options_, std::unordered_map>& arr_arg_type_cache_, - std::map>& fname2arg_type_): + std::map>& fname2arg_type_, + std::map &ptr_type_): context(context), builder(std::move(_builder)), str_cmp_itr(nullptr), der_type_name(der_type_name_), name2dertype(name2dertype_), name2dercontext(name2dercontext_), struct_type_stack(struct_type_stack_), dertype2parent(dertype2parent_), name2memidx(name2memidx_), arr_arg_type_cache(arr_arg_type_cache_), fname2arg_type(fname2arg_type_), - dict_api_lp(nullptr), dict_api_sc(nullptr), + ptr_type(ptr_type_), dict_api_lp(nullptr), dict_api_sc(nullptr), set_api_lp(nullptr), set_api_sc(nullptr), compiler_options(compiler_options_) { std::vector els_4 = { llvm::Type::getFloatTy(context), @@ -131,16 +108,22 @@ namespace LCompilers { llvm::Type::getDoubleTy(context), llvm::Type::getDoubleTy(context)}; std::vector els_4_ptr = { - llvm::Type::getFloatPtrTy(context), - llvm::Type::getFloatPtrTy(context)}; + llvm::Type::getFloatTy(context)->getPointerTo(), + llvm::Type::getFloatTy(context)->getPointerTo()}; std::vector els_8_ptr = { - llvm::Type::getDoublePtrTy(context), - llvm::Type::getDoublePtrTy(context)}; + llvm::Type::getDoubleTy(context)->getPointerTo(), + llvm::Type::getDoubleTy(context)->getPointerTo()}; + std::vector string_descriptor_members { + llvm::Type::getInt8Ty(context)->getPointerTo(), // char_pointer + llvm::Type::getInt64Ty(context), // size + llvm::Type::getInt64Ty(context) // capacity + }; complex_type_4 = llvm::StructType::create(context, els_4, "complex_4"); complex_type_8 = llvm::StructType::create(context, els_8, "complex_8"); complex_type_4_ptr = llvm::StructType::create(context, els_4_ptr, "complex_4_ptr"); complex_type_8_ptr = llvm::StructType::create(context, els_8_ptr, "complex_8_ptr"); - character_type = llvm::Type::getInt8PtrTy(context); + character_type = llvm::Type::getInt8Ty(context)->getPointerTo(); + string_descriptor = llvm::StructType::create(context,string_descriptor_members, "string_descriptor"); } void LLVMUtils::set_module(llvm::Module* module_) { @@ -165,12 +148,12 @@ namespace LCompilers { llvm_mem_type = getStructType(mem_type, module); break; } - case ASR::ttypeType::Enum: { + case ASR::ttypeType::EnumType: { llvm_mem_type = llvm::Type::getInt32Ty(context); break ; } - case ASR::ttypeType::Union: { - llvm_mem_type = getUnionType(mem_type, module); + case ASR::ttypeType::UnionType: { + llvm_mem_type = getUnion(mem_type, module); break; } case ASR::ttypeType::Allocatable: { @@ -188,7 +171,7 @@ namespace LCompilers { llvm_mem_type = getComplexType(a_kind); break; } - case ASR::ttypeType::Character: { + case ASR::ttypeType::String: { llvm_mem_type = character_type; break; } @@ -277,8 +260,8 @@ namespace LCompilers { ASR::StructType_t* der = ASR::down_cast(_type); ASR::symbol_t* der_sym = ASRUtils::symbol_get_past_external(der->m_derived_type); der_type = ASR::down_cast(der_sym); - } else if( ASR::is_a(*_type) ) { - ASR::Class_t* der = ASR::down_cast(_type); + } else if( ASR::is_a(*_type) ) { + ASR::ClassType_t* der = ASR::down_cast(_type); ASR::symbol_t* der_sym = ASRUtils::symbol_get_past_external(der->m_class_type); der_type = ASR::down_cast(der_sym); } else { @@ -290,7 +273,7 @@ namespace LCompilers { return type; } - llvm::Type* LLVMUtils::getUnionType(ASR::UnionType_t* union_type, + llvm::Type* LLVMUtils::getUnion(ASR::Union_t* union_type, llvm::Module* module, bool is_pointer) { std::string union_type_name = std::string(union_type->m_name); llvm::StructType* union_type_llvm = nullptr; @@ -319,14 +302,14 @@ namespace LCompilers { return (llvm::Type*) union_type_llvm; } - llvm::Type* LLVMUtils::getUnionType(ASR::ttype_t* _type, llvm::Module* module, bool is_pointer) { - ASR::Union_t* union_ = ASR::down_cast(_type); + llvm::Type* LLVMUtils::getUnion(ASR::ttype_t* _type, llvm::Module* module, bool is_pointer) { + ASR::UnionType_t* union_ = ASR::down_cast(_type); ASR::symbol_t* union_sym = ASRUtils::symbol_get_past_external(union_->m_union_type); - ASR::UnionType_t* union_type = ASR::down_cast(union_sym); - return getUnionType(union_type, module, is_pointer); + ASR::Union_t* union_type = ASR::down_cast(union_sym); + return getUnion(union_type, module, is_pointer); } - llvm::Type* LLVMUtils::getClassType(ASR::ClassType_t* der_type, bool is_pointer) { + llvm::Type* LLVMUtils::getClassType(ASR::Class_t* der_type, bool is_pointer) { const std::map& scope = der_type->m_symtab->get_scope(); std::vector member_types; int member_idx = 0; @@ -347,7 +330,7 @@ namespace LCompilers { mem_type = getFPType(a_kind); break; } - case ASR::ttypeType::Class: { + case ASR::ttypeType::ClassType: { mem_type = getClassType(member->m_type); break; } @@ -389,7 +372,7 @@ namespace LCompilers { } llvm::Type* LLVMUtils::getClassType(ASR::ttype_t* _type, bool is_pointer) { - ASR::Class_t* der = ASR::down_cast(_type); + ASR::ClassType_t* der = ASR::down_cast(_type); ASR::symbol_t* der_sym = ASRUtils::symbol_get_past_external(der->m_class_type); std::string der_sym_name = ASRUtils::symbol_name(der_sym); std::string der_type_name = der_sym_name + std::string("_polymorphic"); @@ -401,8 +384,8 @@ namespace LCompilers { member_types.push_back(getIntType(8)); if( der_sym_name == "~abstract_type" ) { member_types.push_back(llvm::Type::getVoidTy(context)->getPointerTo()); - } else if( ASR::is_a(*der_sym) ) { - ASR::ClassType_t* class_type_t = ASR::down_cast(der_sym); + } else if( ASR::is_a(*der_sym) ) { + ASR::Class_t* class_type_t = ASR::down_cast(der_sym); member_types.push_back(getClassType(class_type_t, is_pointer)); } else if( ASR::is_a(*der_sym) ) { ASR::Struct_t* struct_type_t = ASR::down_cast(der_sym); @@ -421,10 +404,10 @@ namespace LCompilers { switch(a_kind) { case 4: - type_ptr = llvm::Type::getFloatPtrTy(context); + type_ptr = llvm::Type::getFloatTy(context)->getPointerTo(); break; case 8: - type_ptr = llvm::Type::getDoublePtrTy(context); + type_ptr = llvm::Type::getDoubleTy(context)->getPointerTo(); break; default: throw CodeGenError("Only 32 and 64 bits real kinds are supported."); @@ -497,15 +480,15 @@ namespace LCompilers { el_type = getStructType(m_type_, module); break; } - case ASR::ttypeType::Union: { - el_type = getUnionType(m_type_, module); + case ASR::ttypeType::UnionType: { + el_type = getUnion(m_type_, module); break; } - case ASR::ttypeType::Class: { + case ASR::ttypeType::ClassType: { el_type = getClassType(m_type_); break; } - case ASR::ttypeType::Character: { + case ASR::ttypeType::String: { el_type = character_type; break; } @@ -519,7 +502,7 @@ namespace LCompilers { int32_t get_type_size(ASR::ttype_t* asr_type, llvm::Type* llvm_type, int32_t a_kind, llvm::Module* module) { if( LLVM::is_llvm_struct(asr_type) || - ASR::is_a(*asr_type) || + ASR::is_a(*asr_type) || ASR::is_a(*asr_type) ) { llvm::DataLayout data_layout(module); return data_layout.getTypeAllocSize(llvm_type); @@ -578,8 +561,8 @@ namespace LCompilers { bool get_pointer) { llvm::Type* type = nullptr; - #define handle_llvm_pointers2() bool is_pointer_ = ASR::is_a(*t2) || \ - (ASR::is_a(*t2) && arg_m_abi != ASR::abiType::BindC); \ + #define handle_llvm_pointers2() bool is_pointer_ = ASR::is_a(*t2) || \ + (ASR::is_a(*t2) && arg_m_abi != ASR::abiType::BindC); \ type = get_arg_type_from_ttype_t(t2, nullptr, m_abi, arg_m_abi, \ m_storage, arg_m_value_attr, n_dims, a_kind, \ is_array_type, arg_intent, module, get_pointer); \ @@ -629,7 +612,7 @@ namespace LCompilers { v_type->m_dims, v_type->n_dims))->getPointerTo(); break; } - case ASR::array_physical_typeType::CharacterArraySinglePointer: { + case ASR::array_physical_typeType::StringArraySinglePointer: { // type = character_type->getPointerTo(); // is_array_type = true; // llvm::Type* el_type = get_el_type(v_type->m_type, module); @@ -708,7 +691,8 @@ namespace LCompilers { case (ASR::ttypeType::Complex) : { ASR::Complex_t* v_type = ASR::down_cast(asr_type); a_kind = v_type->m_kind; - if (m_abi != ASR::abiType::BindC) { + if (m_abi != ASR::abiType::BindC + || startswith(compiler_options.target, "wasm")) { type = getComplexType(a_kind, true); } else { if (arg_m_abi == ASR::abiType::BindC @@ -743,11 +727,13 @@ namespace LCompilers { } break; } - case (ASR::ttypeType::Character) : { - ASR::Character_t* v_type = ASR::down_cast(asr_type); + case (ASR::ttypeType::String) : { + ASR::String_t* v_type = ASR::down_cast(asr_type); a_kind = v_type->m_kind; if (arg_m_abi == ASR::abiType::BindC) { type = character_type; + } else if (v_type->m_physical_type == ASR::string_physical_typeType::DescriptorString) { + type = string_descriptor->getPointerTo(); } else { type = character_type->getPointerTo(); } @@ -760,7 +746,7 @@ namespace LCompilers { && arg_m_value_attr) { type = llvm::Type::getInt1Ty(context); } else { - type = llvm::Type::getInt1PtrTy(context); + type = llvm::Type::getInt1Ty(context)->getPointerTo(); } break; } @@ -768,7 +754,7 @@ namespace LCompilers { type = getStructType(asr_type, module, true); break; } - case (ASR::ttypeType::Class) : { + case (ASR::ttypeType::ClassType) : { type = getClassType(asr_type, true)->getPointerTo(); break; } @@ -792,7 +778,7 @@ namespace LCompilers { a_kind, module, m_abi); int32_t type_size = -1; if( LLVM::is_llvm_struct(asr_list->m_type) || - ASR::is_a(*asr_list->m_type) || + ASR::is_a(*asr_list->m_type) || ASR::is_a(*asr_list->m_type) ) { llvm::DataLayout data_layout(module); type_size = data_layout.getTypeAllocSize(el_llvm_type); @@ -803,12 +789,12 @@ namespace LCompilers { type = list_api->get_list_type(el_llvm_type, el_type_code, type_size)->getPointerTo(); break; } - case ASR::ttypeType::Enum: { + case ASR::ttypeType::EnumType: { if (arg_m_abi == ASR::abiType::BindC && arg_m_value_attr) { type = llvm::Type::getInt32Ty(context); } else { - type = llvm::Type::getInt32PtrTy(context); + type = llvm::Type::getInt32Ty(context)->getPointerTo(); } break ; } @@ -868,7 +854,7 @@ namespace LCompilers { } void LLVMUtils::set_dict_api(ASR::Dict_t* dict_type) { - if( ASR::is_a(*dict_type->m_key_type) ) { + if( ASR::is_a(*dict_type->m_key_type) ) { dict_api = dict_api_sc; } else { dict_api = dict_api_lp; @@ -888,7 +874,7 @@ namespace LCompilers { if (ASR::is_a(*ASRUtils::symbol_get_past_external( ASR::down_cast(x.m_args[i])->m_v))) { ASR::Variable_t *arg = ASRUtils::EXPR2VAR(x.m_args[i]); - LCOMPILERS_ASSERT(ASRUtils::is_arg_dummy(arg->m_intent)); + LCOMPILERS_ASSERT(ASRUtils::is_arg_dummy(arg->m_intent) || arg->m_intent == ASR::intentType::Local); // We pass all arguments as pointers for now, // except bind(C) value arguments that are passed by value llvm::Type *type = nullptr, *type_original = nullptr; @@ -905,7 +891,7 @@ namespace LCompilers { } else { type = type_original; } - if( arg->m_intent == ASRUtils::intent_out && + if( (arg->m_intent == ASRUtils::intent_out || (arg->m_intent == ASRUtils::intent_unspecified && !arg->m_value_attr)) && ASR::is_a(*arg->m_type) ) { type = type->getPointerTo(); } @@ -1002,7 +988,7 @@ namespace LCompilers { } break; } - case (ASR::ttypeType::Character) : + case (ASR::ttypeType::String) : return_type = character_type; break; case (ASR::ttypeType::Logical) : @@ -1021,7 +1007,7 @@ namespace LCompilers { break; } case (ASR::ttypeType::StructType) : - throw CodeGenError("Struct return type not implemented yet"); + throw CodeGenError("StructType return type not implemented yet"); break; case (ASR::ttypeType::Tuple) : { ASR::Tuple_t* asr_tuple = ASR::down_cast(return_var_type0); @@ -1054,7 +1040,7 @@ namespace LCompilers { is_array_type, is_malloc_array_type, is_list, m_dims, n_dims, a_kind, module); int32_t type_size = -1; if( LLVM::is_llvm_struct(asr_list->m_type) || - ASR::is_a(*asr_list->m_type) || + ASR::is_a(*asr_list->m_type) || ASR::is_a(*asr_list->m_type) ) { llvm::DataLayout data_layout(module); type_size = data_layout.getTypeAllocSize(el_llvm_type); @@ -1111,7 +1097,7 @@ namespace LCompilers { break; } default : - throw CodeGenError("Type not implemented " + std::to_string(return_var_type)); + throw CodeGenError("Type not implemented " + ASRUtils::type_to_str_python(return_var_type0)); } } else { return_type = llvm::Type::getVoidTy(context); @@ -1200,7 +1186,7 @@ namespace LCompilers { } break; } - case (ASR::ttypeType::Character) : + case (ASR::ttypeType::String) : return_type = character_type; break; case (ASR::ttypeType::Logical) : @@ -1219,7 +1205,7 @@ namespace LCompilers { break; } case (ASR::ttypeType::StructType) : - throw CodeGenError("Struct return type not implemented yet"); + throw CodeGenError("StructType return type not implemented yet"); break; case (ASR::ttypeType::Tuple) : { ASR::Tuple_t* asr_tuple = ASR::down_cast(return_var_type0); @@ -1252,7 +1238,7 @@ namespace LCompilers { is_array_type, is_malloc_array_type, is_list, m_dims, n_dims, a_kind, module); int32_t type_size = -1; if( LLVM::is_llvm_struct(asr_list->m_type) || - ASR::is_a(*asr_list->m_type) || + ASR::is_a(*asr_list->m_type) || ASR::is_a(*asr_list->m_type) ) { llvm::DataLayout data_layout(module); type_size = data_layout.getTypeAllocSize(el_llvm_type); @@ -1309,7 +1295,7 @@ namespace LCompilers { break; } default : - throw CodeGenError("Type not implemented " + std::to_string(return_var_type)); + throw CodeGenError("Type not implemented " + ASRUtils::type_to_str_python(return_var_type0)); } } else { return_type = llvm::Type::getVoidTy(context); @@ -1328,8 +1314,12 @@ namespace LCompilers { llvm::Type* llvm_type = nullptr; #define handle_llvm_pointers1() \ - if (n_dims == 0 && ASR::is_a(*t2)) { \ - llvm_type = character_type; \ + if (n_dims == 0 && ASR::is_a(*t2)) { \ + if(ASRUtils::is_descriptorString(t2)) { \ + llvm_type = string_descriptor; \ + } else { \ + llvm_type = character_type; \ + } \ } else { \ llvm_type = get_type_from_ttype_t(t2, nullptr, m_storage, \ is_array_type, is_malloc_array_type, is_list, m_dims, \ @@ -1352,7 +1342,8 @@ namespace LCompilers { llvm_type = arr_api->get_array_type(asr_type, el_type); break; } - case ASR::array_physical_typeType::PointerToDataArray: { + case ASR::array_physical_typeType::PointerToDataArray: + case ASR::array_physical_typeType::UnboundedPointerToDataArray : { llvm_type = get_el_type(v_type->m_type, module)->getPointerTo(); break; } @@ -1368,7 +1359,7 @@ namespace LCompilers { ASRUtils::get_fixed_size_of_array(v_type->m_dims, v_type->n_dims), false); break; } - case ASR::array_physical_typeType::CharacterArraySinglePointer: { + case ASR::array_physical_typeType::StringArraySinglePointer: { if (ASRUtils::is_fixed_size_array(v_type->m_dims, v_type->n_dims)) { llvm_type = llvm::ArrayType::get(character_type, ASRUtils::get_fixed_size_of_array(v_type->m_dims, v_type->n_dims)); @@ -1416,10 +1407,14 @@ namespace LCompilers { llvm_type = getComplexType(a_kind); break; } - case (ASR::ttypeType::Character) : { - ASR::Character_t* v_type = ASR::down_cast(asr_type); + case (ASR::ttypeType::String) : { + ASR::String_t* v_type = ASR::down_cast(asr_type); a_kind = v_type->m_kind; - llvm_type = character_type; + if(v_type->m_physical_type == ASR::string_physical_typeType::DescriptorString){ + llvm_type = string_descriptor; + } else { + llvm_type = character_type; + } break; } case (ASR::ttypeType::Logical) : { @@ -1432,25 +1427,25 @@ namespace LCompilers { llvm_type = getStructType(asr_type, module, false); break; } - case (ASR::ttypeType::Class) : { + case (ASR::ttypeType::ClassType) : { llvm_type = getClassType(asr_type, is_pointer); break; } - case (ASR::ttypeType::Union) : { - llvm_type = getUnionType(asr_type, module, false); + case (ASR::ttypeType::UnionType) : { + llvm_type = getUnion(asr_type, module, false); break; } case (ASR::ttypeType::Pointer) : { ASR::ttype_t *t2 = ASR::down_cast(asr_type)->m_type; - bool is_pointer_ = ( ASR::is_a(*t2) || - (ASR::is_a(*t2) && m_abi != ASR::abiType::BindC) ); + bool is_pointer_ = ( ASR::is_a(*t2) || + (ASR::is_a(*t2) && m_abi != ASR::abiType::BindC) ); is_malloc_array_type = ASRUtils::is_array(t2); handle_llvm_pointers1() break; } case (ASR::ttypeType::Allocatable) : { ASR::ttype_t *t2 = ASR::down_cast(asr_type)->m_type; - bool is_pointer_ = (ASR::is_a(*t2) + bool is_pointer_ = (ASR::is_a(*t2) && m_abi != ASR::abiType::BindC); is_malloc_array_type = ASRUtils::is_array(t2); handle_llvm_pointers1() @@ -1466,7 +1461,7 @@ namespace LCompilers { std::string el_type_code = ASRUtils::get_type_code(asr_list->m_type); int32_t type_size = -1; if( LLVM::is_llvm_struct(asr_list->m_type) || - ASR::is_a(*asr_list->m_type) || + ASR::is_a(*asr_list->m_type) || ASR::is_a(*asr_list->m_type) ) { llvm::DataLayout data_layout(module); type_size = data_layout.getTypeAllocSize(el_llvm_type); @@ -1508,7 +1503,7 @@ namespace LCompilers { llvm_type = llvm::Type::getVoidTy(context)->getPointerTo(); break; } - case (ASR::ttypeType::Enum) : { + case (ASR::ttypeType::EnumType) : { llvm_type = llvm::Type::getInt32Ty(context); break ; } @@ -1524,7 +1519,7 @@ namespace LCompilers { break; } default : - throw CodeGenError("Support for type " + ASRUtils::type_to_str(asr_type) + + throw CodeGenError("Support for type " + ASRUtils::type_to_str_fortran(asr_type) + " not yet implemented."); } return llvm_type; @@ -1536,7 +1531,7 @@ namespace LCompilers { bool is_array_type_local, is_malloc_array_type_local; bool is_list_local; ASR::dimension_t* m_dims_local; - int n_dims_local, a_kind_local; + int n_dims_local = 0, a_kind_local = 0; return get_type_from_ttype_t(asr_type, nullptr, m_storage_local, is_array_type_local, is_malloc_array_type_local, is_list_local, m_dims_local, n_dims_local, a_kind_local, module, asr_abi); @@ -1546,25 +1541,234 @@ namespace LCompilers { std::vector idx_vec = { llvm::ConstantInt::get(context, llvm::APInt(32, 0)), llvm::ConstantInt::get(context, llvm::APInt(32, idx))}; - return LLVM::CreateGEP(*builder, ds, idx_vec); + return LLVMUtils::CreateGEP(ds, idx_vec); + } + + llvm::Value* LLVMUtils::create_gep2(llvm::Type *t, llvm::Value* ds, int idx) { + std::vector idx_vec = { + llvm::ConstantInt::get(context, llvm::APInt(32, 0)), + llvm::ConstantInt::get(context, llvm::APInt(32, idx))}; + return LLVMUtils::CreateGEP2(t, ds, idx_vec); } llvm::Value* LLVMUtils::create_gep(llvm::Value* ds, llvm::Value* idx) { std::vector idx_vec = { llvm::ConstantInt::get(context, llvm::APInt(32, 0)), idx}; - return LLVM::CreateGEP(*builder, ds, idx_vec); + return LLVMUtils::CreateGEP(ds, idx_vec); + } + + llvm::Value* LLVMUtils::create_gep2(llvm::Type *t, llvm::Value* ds, llvm::Value* idx) { + std::vector idx_vec = { + llvm::ConstantInt::get(context, llvm::APInt(32, 0)), + idx}; + return LLVMUtils::CreateGEP2(t, ds, idx_vec); } llvm::Value* LLVMUtils::create_ptr_gep(llvm::Value* ptr, int idx) { std::vector idx_vec = { llvm::ConstantInt::get(context, llvm::APInt(32, idx))}; - return LLVM::CreateInBoundsGEP(*builder, ptr, idx_vec); + return LLVMUtils::CreateInBoundsGEP(ptr, idx_vec); + } + + llvm::Value* LLVMUtils::create_ptr_gep2(llvm::Type* type, llvm::Value* ptr, int idx) { + std::vector idx_vec = { + llvm::ConstantInt::get(context, llvm::APInt(32, idx))}; + return LLVMUtils::CreateInBoundsGEP2(type, ptr, idx_vec); } llvm::Value* LLVMUtils::create_ptr_gep(llvm::Value* ptr, llvm::Value* idx) { std::vector idx_vec = {idx}; - return LLVM::CreateInBoundsGEP(*builder, ptr, idx_vec); + return LLVMUtils::CreateInBoundsGEP(ptr, idx_vec); + } + + llvm::Value* LLVMUtils::create_ptr_gep2(llvm::Type* type, llvm::Value* ptr, llvm::Value* idx) { + std::vector idx_vec = {idx}; + return LLVMUtils::CreateInBoundsGEP2(type, ptr, idx_vec); + } + + llvm::AllocaInst* LLVMUtils::CreateAlloca(llvm::Type* type, + llvm::Value* size, std::string Name, bool +#if LLVM_VERSION_MAJOR > 16 + is_llvm_ptr +#else + /*is_llvm_ptr*/ +#endif + ) { + llvm::BasicBlock &entry_block = builder->GetInsertBlock()->getParent()->getEntryBlock(); + llvm::IRBuilder<> builder0(context); + builder0.SetInsertPoint(&entry_block, entry_block.getFirstInsertionPt()); + llvm::AllocaInst *alloca; +#if LLVM_VERSION_MAJOR > 16 + llvm::Type *type_ = is_llvm_ptr ? type->getPointerTo() : type; +#else + llvm::Type *type_ = type; +#endif + if (Name != "") { + alloca = builder0.CreateAlloca(type_, size, Name); + } else { + alloca = builder0.CreateAlloca(type_, size); + } +#if LLVM_VERSION_MAJOR > 16 + ptr_type[alloca] = type; +#endif + return alloca; + } + + llvm::AllocaInst* LLVMUtils::CreateAlloca(llvm::IRBuilder<> &builder, + llvm::Type* type, llvm::Value* size, std::string Name, bool +#if LLVM_VERSION_MAJOR > 16 + is_llvm_ptr +#else + /*is_llvm_ptr*/ +#endif + ) { + llvm::AllocaInst *alloca; +#if LLVM_VERSION_MAJOR > 16 + llvm::Type *type_ = is_llvm_ptr ? type->getPointerTo() : type; +#else + llvm::Type *type_ = type; +#endif + if (Name != "") { + alloca = builder.CreateAlloca(type_, size, Name); + } else { + alloca = builder.CreateAlloca(type_, size); + } +#if LLVM_VERSION_MAJOR > 16 + ptr_type[alloca] = type; +#endif + return alloca; + } + + llvm::Value *LLVMUtils::CreateLoad(llvm::Value *x) { +#if LLVM_VERSION_MAJOR <= 16 + llvm::Type *t = x->getType(); + LCOMPILERS_ASSERT(t->isPointerTy()); + LCOMPILERS_ASSERT(t->getNumContainedTypes() > 0); + llvm::Type *t2 = t->getContainedType(0); + return builder->CreateLoad(t2, x); +#else + llvm::Type *type = nullptr, *type_copy = nullptr; + bool is_type_pointer = false; + if (ptr_type.find(x) != ptr_type.end()) { + type_copy = type = ptr_type[x]; + } + LCOMPILERS_ASSERT(type); + // getPointerTo() is used for allocatable or pointer + if (type != character_type && (llvm::isa(x) && + llvm::dyn_cast(x)->getAllocatedType()->isPointerTy())) { + // AllocaInst + type = type->getPointerTo(); + is_type_pointer = true; + } else if (llvm::StructType *arr_type = llvm::dyn_cast(type)) { + // Function arguments + if (arr_type->getName() == "array" || LCompilers::startswith( + std::string(arr_type->getName()), "array.")) { + type = type->getPointerTo(); + is_type_pointer = true; + } + } + + if ( llvm::GetElementPtrInst * + gep = llvm::dyn_cast(x) ) { + // GetElementPtrInst + llvm::Type *src_type = gep->getSourceElementType(); + LCOMPILERS_ASSERT(llvm::isa(src_type)); + std::string s_name = std::string(llvm::dyn_cast( + gep->getSourceElementType())->getName()); + if ( name2dertype.find(s_name) != name2dertype.end() ) { + type = type->getPointerTo(); + is_type_pointer = true; + } + } + + llvm::Value *load = builder->CreateLoad(type, x); + if (is_type_pointer) { + ptr_type[load] = type_copy; + } + return load; +#endif + } + + llvm::Value *LLVMUtils::CreateLoad2(llvm::Type *t, llvm::Value *x) { + return builder->CreateLoad(t, x); + } + + llvm::Value* LLVMUtils::CreateLoad2(ASR::ttype_t *type, llvm::Value *x) { +#if LLVM_VERSION_MAJOR <= 16 + llvm::Type* el_type = LLVMUtils::get_type_from_ttype_t_util(type, module); + return builder->CreateLoad(el_type, x); +#else + llvm::Type* el_type = LLVMUtils::get_type_from_ttype_t_util( + ASRUtils::type_get_past_pointer(ASRUtils::type_get_past_allocatable( + type)), module); + llvm::Type* el_type_copy = el_type; + bool is_llvm_ptr = LLVM::is_llvm_pointer(*type); + if (is_llvm_ptr && !ASRUtils::is_descriptorString(type)) { + el_type_copy = el_type_copy->getPointerTo(); + } + llvm::Value* load = builder->CreateLoad(el_type_copy, x); + if (is_llvm_ptr) { + ptr_type[load] = el_type; + } + return load; +#endif + } + + llvm::Value* LLVMUtils::CreateGEP(llvm::Value *x, + std::vector &idx) { +#if LLVM_VERSION_MAJOR <= 16 + llvm::Type *t = x->getType(); + LCOMPILERS_ASSERT(t->isPointerTy()); + LCOMPILERS_ASSERT(t->getNumContainedTypes() > 0); + llvm::Type *t2 = t->getContainedType(0); + return builder->CreateGEP(t2, x, idx); +#else + llvm::Type *type = nullptr; + if (ptr_type.find(x) != ptr_type.end()) { + type = ptr_type[x]; + } + LCOMPILERS_ASSERT(type); + return builder->CreateGEP(type, x, idx); +#endif + } + + llvm::Value* LLVMUtils::CreateGEP2(llvm::Type *t, llvm::Value *x, + std::vector &idx) { + return builder->CreateGEP(t, x, idx); + } + + llvm::Value* LLVMUtils::CreateGEP2(ASR::ttype_t *type, + llvm::Value *x, int idx) { + std::vector idx_vec = { + llvm::ConstantInt::get(context, llvm::APInt(32, 0)), + llvm::ConstantInt::get(context, llvm::APInt(32, idx))}; + llvm::Type* llvm_type = LLVMUtils::get_type_from_ttype_t_util(type, + module); + return LLVMUtils::CreateGEP2(llvm_type, x, idx_vec); + } + + llvm::Value* LLVMUtils::CreateInBoundsGEP(llvm::Value *x, + std::vector &idx) { +#if LLVM_VERSION_MAJOR <= 16 + llvm::Type *t = x->getType(); + LCOMPILERS_ASSERT(t->isPointerTy()); + LCOMPILERS_ASSERT(t->getNumContainedTypes() > 0); + llvm::Type *t2 = t->getContainedType(0); + return builder->CreateInBoundsGEP(t2, x, idx); +#else + llvm::Type *type = nullptr; + if (ptr_type.find(x) != ptr_type.end()) { + type = ptr_type[x]; + } + LCOMPILERS_ASSERT(type); + return builder->CreateInBoundsGEP(type, x, idx); +#endif + } + + llvm::Value* LLVMUtils::CreateInBoundsGEP2(llvm::Type *t, + llvm::Value *x, std::vector &idx) { + return builder->CreateInBoundsGEP(t, x, idx); } llvm::Type* LLVMUtils::getIntType(int a_kind, bool get_pointer) { @@ -1573,16 +1777,16 @@ namespace LCompilers { switch(a_kind) { case 1: - type_ptr = llvm::Type::getInt8PtrTy(context); + type_ptr = llvm::Type::getInt8Ty(context)->getPointerTo(); break; case 2: - type_ptr = llvm::Type::getInt16PtrTy(context); + type_ptr = llvm::Type::getInt16Ty(context)->getPointerTo(); break; case 4: - type_ptr = llvm::Type::getInt32PtrTy(context); + type_ptr = llvm::Type::getInt32Ty(context)->getPointerTo(); break; case 8: - type_ptr = llvm::Type::getInt64PtrTy(context); + type_ptr = llvm::Type::getInt64Ty(context)->getPointerTo(); break; default: LCOMPILERS_ASSERT(false); @@ -1629,7 +1833,7 @@ namespace LCompilers { llvm::Value* LLVMUtils::lfortran_str_cmp(llvm::Value* left_arg, llvm::Value* right_arg, std::string runtime_func_name, llvm::Module& module) { - llvm::Type* character_type = llvm::Type::getInt8PtrTy(context); + llvm::Type* character_type = llvm::Type::getInt8Ty(context)->getPointerTo(); llvm::Function *fn = module.getFunction(runtime_func_name); if(!fn) { llvm::FunctionType *function_type = llvm::FunctionType::get( @@ -1640,10 +1844,9 @@ namespace LCompilers { fn = llvm::Function::Create(function_type, llvm::Function::ExternalLinkage, runtime_func_name, module); } - get_builder0() - llvm::AllocaInst *pleft_arg = builder0.CreateAlloca(character_type, nullptr); + llvm::AllocaInst *pleft_arg = LLVMUtils::CreateAlloca(character_type); LLVM::CreateStore(*builder, left_arg, pleft_arg); - llvm::AllocaInst *pright_arg = builder0.CreateAlloca(character_type, nullptr); + llvm::AllocaInst *pright_arg = LLVMUtils::CreateAlloca(character_type); LLVM::CreateStore(*builder, right_arg, pright_arg); std::vector args = {pleft_arg, pright_arg}; return builder->CreateCall(fn, args); @@ -1663,9 +1866,8 @@ namespace LCompilers { case ASR::ttypeType::Real: { return builder->CreateFCmpOEQ(left, right); } - case ASR::ttypeType::Character: { - get_builder0() - str_cmp_itr = builder0.CreateAlloca(llvm::Type::getInt32Ty(context), nullptr); + case ASR::ttypeType::String: { + str_cmp_itr = LLVMUtils::CreateAlloca(llvm::Type::getInt32Ty(context)); llvm::Value* null_char = llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), llvm::APInt(8, '\0')); llvm::Value* idx = str_cmp_itr; @@ -1679,9 +1881,9 @@ namespace LCompilers { // head start_new_block(loophead); { - llvm::Value* i = LLVM::CreateLoad(*builder, idx); - llvm::Value* l = LLVM::CreateLoad(*builder, create_ptr_gep(left, i)); - llvm::Value* r = LLVM::CreateLoad(*builder, create_ptr_gep(right, i)); + llvm::Value* i = LLVMUtils::CreateLoad(idx); + llvm::Value* l = LLVMUtils::CreateLoad(create_ptr_gep(left, i)); + llvm::Value* r = LLVMUtils::CreateLoad(create_ptr_gep(right, i)); llvm::Value *cond = builder->CreateAnd( builder->CreateICmpNE(l, null_char), builder->CreateICmpNE(r, null_char) @@ -1693,7 +1895,7 @@ namespace LCompilers { // body start_new_block(loopbody); { - llvm::Value* i = LLVM::CreateLoad(*builder, idx); + llvm::Value* i = LLVMUtils::CreateLoad(idx); i = builder->CreateAdd(i, llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), llvm::APInt(32, 1))); LLVM::CreateStore(*builder, i, idx); @@ -1703,9 +1905,9 @@ namespace LCompilers { // end start_new_block(loopend); - llvm::Value* i = LLVM::CreateLoad(*builder, idx); - llvm::Value* l = LLVM::CreateLoad(*builder, create_ptr_gep(left, i)); - llvm::Value* r = LLVM::CreateLoad(*builder, create_ptr_gep(right, i)); + llvm::Value* i = LLVMUtils::CreateLoad(idx); + llvm::Value* l = LLVMUtils::CreateLoad(create_ptr_gep(left, i)); + llvm::Value* r = LLVMUtils::CreateLoad(create_ptr_gep(right, i)); return builder->CreateICmpEQ(l, r); } case ASR::ttypeType::Tuple: { @@ -1791,9 +1993,8 @@ namespace LCompilers { } return builder->CreateFCmp(pred, left, right); } - case ASR::ttypeType::Character: { - get_builder0() - str_cmp_itr = builder0.CreateAlloca(llvm::Type::getInt32Ty(context), nullptr); + case ASR::ttypeType::String: { + str_cmp_itr = LLVMUtils::CreateAlloca(llvm::Type::getInt32Ty(context)); llvm::Value* null_char = llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), llvm::APInt(8, '\0')); llvm::Value* idx = str_cmp_itr; @@ -1807,9 +2008,9 @@ namespace LCompilers { // head start_new_block(loophead); { - llvm::Value* i = LLVM::CreateLoad(*builder, idx); - llvm::Value* l = LLVM::CreateLoad(*builder, create_ptr_gep(left, i)); - llvm::Value* r = LLVM::CreateLoad(*builder, create_ptr_gep(right, i)); + llvm::Value* i = LLVMUtils::CreateLoad(idx); + llvm::Value* l = LLVMUtils::CreateLoad(create_ptr_gep(left, i)); + llvm::Value* r = LLVMUtils::CreateLoad(create_ptr_gep(right, i)); llvm::Value *cond = builder->CreateAnd( builder->CreateICmpNE(l, null_char), builder->CreateICmpNE(r, null_char) @@ -1842,7 +2043,7 @@ namespace LCompilers { // body start_new_block(loopbody); { - llvm::Value* i = LLVM::CreateLoad(*builder, idx); + llvm::Value* i = LLVMUtils::CreateLoad(idx); i = builder->CreateAdd(i, llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), llvm::APInt(32, 1))); LLVM::CreateStore(*builder, i, idx); @@ -1852,9 +2053,9 @@ namespace LCompilers { // end start_new_block(loopend); - llvm::Value* i = LLVM::CreateLoad(*builder, idx); - llvm::Value* l = LLVM::CreateLoad(*builder, create_ptr_gep(left, i)); - llvm::Value* r = LLVM::CreateLoad(*builder, create_ptr_gep(right, i)); + llvm::Value* i = LLVMUtils::CreateLoad(idx); + llvm::Value* l = LLVMUtils::CreateLoad(create_ptr_gep(left, i)); + llvm::Value* r = LLVMUtils::CreateLoad(create_ptr_gep(right, i)); return builder->CreateICmpULT(l, r); } case ASR::ttypeType::Tuple: { @@ -1888,12 +2089,14 @@ namespace LCompilers { ASR::array_physical_typeType physical_type = ASRUtils::extract_physical_type(asr_type); switch( physical_type ) { case ASR::array_physical_typeType::DescriptorArray: { - arr_api->copy_array(src, dest, module, asr_type, false, false); + arr_api->copy_array(src, dest, module, asr_type, false); break; } case ASR::array_physical_typeType::FixedSizeArray: { - src = create_gep(src, 0); - dest = create_gep(dest, 0); + llvm::Type* llvm_array_type = get_type_from_ttype_t_util( + ASRUtils::type_get_past_allocatable(ASRUtils::type_get_past_pointer(asr_type)), module); + src = create_gep2(llvm_array_type, src, 0); + dest = create_gep2(llvm_array_type, dest, 0); ASR::dimension_t* asr_dims = nullptr; size_t asr_n_dims = ASRUtils::extract_dimensions_from_ttype(asr_type, asr_dims); int64_t size = ASRUtils::get_fixed_size_of_array(asr_dims, asr_n_dims); @@ -1916,7 +2119,7 @@ namespace LCompilers { } break ; }; - case ASR::ttypeType::Character: + case ASR::ttypeType::String: case ASR::ttypeType::FunctionType: case ASR::ttypeType::CPtr: { LLVM::CreateStore(*builder, src, dest); @@ -1924,9 +2127,13 @@ namespace LCompilers { } case ASR::ttypeType::Allocatable: { ASR::Allocatable_t* alloc_type = ASR::down_cast(asr_type); - if( ASR::is_a(*alloc_type->m_type) ) { - lfortran_str_copy(dest, src, true, *module, *builder, context); + if( ASR::is_a(*alloc_type->m_type) ) { + lfortran_str_copy(dest, src, true, *module, *builder, context, string_descriptor); } else { + if( ASRUtils::is_array(alloc_type->m_type) ) { + llvm::Type *array_type = get_type_from_ttype_t_util(alloc_type->m_type, module); + src = CreateLoad2(array_type->getPointerTo(), src); + } LLVM::CreateStore(*builder, src, dest); } break; @@ -1947,11 +2154,6 @@ namespace LCompilers { dict_api->dict_deepcopy(src, dest, dict_type, module, name2memidx); break ; } - case ASR::ttypeType::Set: { - ASR::Set_t *set_type = ASR::down_cast(asr_type); - set_api->set_deepcopy(src, dest, set_type, module, name2memidx); - break; - } case ASR::ttypeType::StructType: { ASR::StructType_t* struct_t = ASR::down_cast(asr_type); ASR::Struct_t* struct_type_t = ASR::down_cast( @@ -1960,18 +2162,21 @@ namespace LCompilers { while( struct_type_t != nullptr ) { for( auto item: struct_type_t->m_symtab->get_scope() ) { if( ASR::is_a(*item.second) || - ASR::is_a(*item.second) || - ASR::is_a(*item.second) ) { + ASR::is_a(*item.second) ) { continue ; } std::string mem_name = item.first; int mem_idx = name2memidx[der_type_name][mem_name]; - llvm::Value* src_member = create_gep(src, mem_idx); - if( !LLVM::is_llvm_struct(ASRUtils::symbol_type(item.second)) && - !ASRUtils::is_array(ASRUtils::symbol_type(item.second)) ) { - src_member = LLVM::CreateLoad(*builder, src_member); + llvm::Value* src_member = create_gep2(name2dertype[der_type_name], src, mem_idx); + llvm::Type *mem_type = get_type_from_ttype_t_util( + ASRUtils::symbol_type(item.second), module); + ASR::ttype_t* member_type = ASRUtils::symbol_type(item.second); + if( !LLVM::is_llvm_struct(member_type) && + !ASRUtils::is_array(member_type) && + !ASRUtils::is_descriptorString(member_type)) { + src_member = LLVMUtils::CreateLoad2(mem_type, src_member); } - llvm::Value* dest_member = create_gep(dest, mem_idx); + llvm::Value* dest_member = create_gep2(name2dertype[der_type_name], dest, mem_idx); deepcopy(src_member, dest_member, ASRUtils::symbol_type(item.second), module, name2memidx); @@ -1988,55 +2193,23 @@ namespace LCompilers { } default: { throw LCompilersException("LLVMUtils::deepcopy isn't implemented for " + - ASRUtils::type_to_str(asr_type)); + ASRUtils::type_to_str_fortran(asr_type)); } } } + llvm::Value* LLVMUtils::convert_kind(llvm::Value* val, llvm::Type* target_type){ + LCOMPILERS_ASSERT( + (val->getType()->isIntegerTy() && target_type->isIntegerTy()) || + (val->getType()->isFloatingPointTy() && target_type->isFloatingPointTy())); - void LLVMUtils::free_data(llvm::Value* src, ASR::ttype_t* asr_type, llvm::Module* module) { - switch( ASRUtils::type_get_past_array(asr_type)->type ) { - // TODO: change this if explicit freeing is required for any of the below - case ASR::ttypeType::Integer: - case ASR::ttypeType::UnsignedInteger: - case ASR::ttypeType::Real: - case ASR::ttypeType::Logical: - case ASR::ttypeType::Complex: - case ASR::ttypeType::Character: - case ASR::ttypeType::FunctionType: - case ASR::ttypeType::CPtr: - case ASR::ttypeType::Allocatable: { - break ; - } - case ASR::ttypeType::Tuple: { - // TODO: implement tuple free - break ; - } - case ASR::ttypeType::List: { - ASR::List_t* list_type = ASR::down_cast(asr_type); - list_api->free_data(src, list_type->m_type, *module); - break ; - } - case ASR::ttypeType::Dict: { - ASR::Dict_t* dict_type = ASR::down_cast(asr_type); - set_dict_api(dict_type); - dict_api->dict_free(src, module, dict_type->m_key_type, - dict_type->m_value_type); - break ; - } - case ASR::ttypeType::Set: { - ASR::Set_t *set_type = ASR::down_cast(asr_type); - set_set_api(set_type); - set_api->set_free(src, module, set_type->m_type); - break ; - } - case ASR::ttypeType::StructType: { - // TODO: implement struct free and call destructor if required - break ; - } - default: { - break; - } - + if(val->getType()->getPrimitiveSizeInBits() == target_type->getPrimitiveSizeInBits()){ + return val; + } else if(val->getType()->getPrimitiveSizeInBits() > target_type->getPrimitiveSizeInBits()){ + return val->getType()->isIntegerTy() ? + builder->CreateTrunc(val, target_type) : builder->CreateFPTrunc(val, target_type); + } else { + return val->getType()->isIntegerTy() ? + builder->CreateSExt(val, target_type): builder->CreateFPExt(val, target_type); } } @@ -2109,7 +2282,7 @@ namespace LCompilers { value_type_code, value_type_size); std::vector dict_type_vec = {llvm::Type::getInt32Ty(context), key_list_type, value_list_type, - llvm::Type::getInt8PtrTy(context)}; + llvm::Type::getInt8Ty(context)->getPointerTo()}; llvm::Type* dict_desc = llvm::StructType::create(context, dict_type_vec, "dict"); typecode2dicttype[llvm_key] = std::make_tuple(dict_desc, std::make_pair(key_type_size, value_type_size), @@ -2130,11 +2303,6 @@ namespace LCompilers { return get_key_value_pair_type(key_type_code, value_type_code); } - llvm::Type* LLVMDict::get_key_value_pair_type( - ASR::ttype_t* /*key_asr_type*/, ASR::ttype_t* /*value_asr_type*/) { - return nullptr; - } - llvm::Type* LLVMDictSeparateChaining::get_dict_type( std::string key_type_code, std::string value_type_code, int32_t key_type_size, int32_t value_type_size, @@ -2146,13 +2314,13 @@ namespace LCompilers { } std::vector key_value_vec = {key_type, value_type, - llvm::Type::getInt8PtrTy(context)}; + llvm::Type::getInt8Ty(context)->getPointerTo()}; llvm::Type* key_value_pair = llvm::StructType::create(context, key_value_vec, "key_value"); std::vector dict_type_vec = {llvm::Type::getInt32Ty(context), llvm::Type::getInt32Ty(context), llvm::Type::getInt32Ty(context), key_value_pair->getPointerTo(), - llvm::Type::getInt8PtrTy(context), + llvm::Type::getInt8Ty(context)->getPointerTo(), llvm::Type::getInt1Ty(context)}; llvm::Type* dict_desc = llvm::StructType::create(context, dict_type_vec, "dict"); typecode2dicttype[llvm_key] = std::make_tuple(dict_desc, @@ -2180,15 +2348,17 @@ namespace LCompilers { throw LCompilersException("list for " + type_code + " not declared yet."); } int32_t type_size = std::get<1>(typecode2listtype[type_code]); - llvm::Value* llvm_type_size = llvm::ConstantInt::get(context, llvm::APInt(32, type_size)); - llvm::Value* current_capacity = llvm::ConstantInt::get(context, llvm::APInt(32, initial_capacity)); - llvm::Value* list_data = LLVM::lfortran_calloc(context, module, *builder, - current_capacity, llvm_type_size); + llvm::Value* arg_size = llvm::ConstantInt::get(context, + llvm::APInt(32, type_size * initial_capacity)); + + llvm::Value* list_data = LLVM::lfortran_malloc(context, module, *builder, + arg_size); llvm::Type* el_type = std::get<2>(typecode2listtype[type_code]); list_data = builder->CreateBitCast(list_data, el_type->getPointerTo()); llvm::Value* list_data_ptr = get_pointer_to_list_data(list); builder->CreateStore(list_data, list_data_ptr); llvm::Value* current_end_point = llvm::ConstantInt::get(context, llvm::APInt(32, n)); + llvm::Value* current_capacity = llvm::ConstantInt::get(context, llvm::APInt(32, initial_capacity)); builder->CreateStore(current_end_point, get_pointer_to_current_end_point(list)); builder->CreateStore(current_capacity, get_pointer_to_current_capacity(list)); } @@ -2201,8 +2371,8 @@ namespace LCompilers { } int32_t type_size = std::get<1>(typecode2listtype[type_code]); llvm::Value* llvm_type_size = llvm::ConstantInt::get(context, llvm::APInt(32, type_size)); - llvm::Value* list_data = LLVM::lfortran_calloc(context, module, *builder, - initial_capacity, llvm_type_size); + llvm::Value* arg_size = builder->CreateMul(llvm_type_size, initial_capacity); + llvm::Value* list_data = LLVM::lfortran_malloc(context, module, *builder, arg_size); llvm::Type* el_type = std::get<2>(typecode2listtype[type_code]); list_data = builder->CreateBitCast(list_data, el_type->getPointerTo()); @@ -2216,10 +2386,6 @@ namespace LCompilers { return llvm_utils->create_gep(dict, 1); } - llvm::Value* LLVMDict::get_pointer_to_key_value_pairs(llvm::Value* /*dict*/) { - return nullptr; - } - llvm::Value* LLVMDictSeparateChaining::get_pointer_to_key_value_pairs(llvm::Value* dict) { return llvm_utils->create_gep(dict, 3); } @@ -2295,7 +2461,7 @@ namespace LCompilers { std::string key_type_code, std::string value_type_code, llvm::Value* dict, llvm::Module* module, llvm::Value* llvm_capacity) { llvm::Value* rehash_flag_ptr = get_pointer_to_rehash_flag(dict); - llvm::Value* rehash_flag = LLVM::CreateLoad(*builder, rehash_flag_ptr); + llvm::Value* rehash_flag = llvm_utils->CreateLoad(rehash_flag_ptr); llvm::Value* llvm_zero = llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), llvm::APInt(32, 0)); llvm::Value* occupancy_ptr = get_pointer_to_occupancy(dict); LLVM::CreateStore(*builder, llvm_zero, occupancy_ptr); @@ -2310,7 +2476,7 @@ namespace LCompilers { llvm::Value* key_value_ptr = LLVM::lfortran_malloc(context, *module, *builder, malloc_size); rehash_flag = builder->CreateAnd(rehash_flag, builder->CreateICmpNE(key_value_ptr, - llvm::ConstantPointerNull::get(llvm::Type::getInt8PtrTy(context))) + llvm::ConstantPointerNull::get(llvm::Type::getInt8Ty(context)->getPointerTo())) ); key_value_ptr = builder->CreateBitCast(key_value_ptr, key_value_pair_type->getPointerTo()); LLVM::CreateStore(*builder, key_value_ptr, get_pointer_to_key_value_pairs(dict)); @@ -2322,7 +2488,7 @@ namespace LCompilers { llvm_mask_size); rehash_flag = builder->CreateAnd(rehash_flag, builder->CreateICmpNE(key_mask, - llvm::ConstantPointerNull::get(llvm::Type::getInt8PtrTy(context))) + llvm::ConstantPointerNull::get(llvm::Type::getInt8Ty(context)->getPointerTo())) ); LLVM::CreateStore(*builder, key_mask, get_pointer_to_keymask(dict)); @@ -2342,17 +2508,18 @@ namespace LCompilers { std::map>& name2memidx) { LCOMPILERS_ASSERT(src->getType() == dest->getType()); std::string src_type_code = ASRUtils::get_type_code(element_type); - llvm::Value* src_end_point = LLVM::CreateLoad(*builder, get_pointer_to_current_end_point(src)); - llvm::Value* src_capacity = LLVM::CreateLoad(*builder, get_pointer_to_current_capacity(src)); + llvm::Value* src_end_point = llvm_utils->CreateLoad(get_pointer_to_current_end_point(src)); + llvm::Value* src_capacity = llvm_utils->CreateLoad(get_pointer_to_current_capacity(src)); llvm::Value* dest_end_point_ptr = get_pointer_to_current_end_point(dest); llvm::Value* dest_capacity_ptr = get_pointer_to_current_capacity(dest); builder->CreateStore(src_end_point, dest_end_point_ptr); builder->CreateStore(src_capacity, dest_capacity_ptr); - llvm::Value* src_data = LLVM::CreateLoad(*builder, get_pointer_to_list_data(src)); + llvm::Value* src_data = llvm_utils->CreateLoad(get_pointer_to_list_data(src)); int32_t type_size = std::get<1>(typecode2listtype[src_type_code]); - llvm::Value* llvm_type_size = llvm::ConstantInt::get(context, llvm::APInt(32, type_size)); - llvm::Value* copy_data = LLVM::lfortran_calloc(context, *module, *builder, - src_capacity, llvm_type_size); + llvm::Value* arg_size = builder->CreateMul(llvm::ConstantInt::get(context, + llvm::APInt(32, type_size)), src_capacity); + llvm::Value* copy_data = LLVM::lfortran_malloc(context, *module, *builder, + arg_size); llvm::Type* el_type = std::get<2>(typecode2listtype[src_type_code]); copy_data = builder->CreateBitCast(copy_data, el_type->getPointerTo()); @@ -2370,9 +2537,7 @@ namespace LCompilers { // TODO: Should be created outside the user loop and not here. // LLVMList should treat them as data members and create them // only if they are NULL - get_builder0() - llvm::AllocaInst *pos_ptr = builder0.CreateAlloca(llvm::Type::getInt32Ty(context), - nullptr); + llvm::AllocaInst *pos_ptr = llvm_utils->CreateAlloca(llvm::Type::getInt32Ty(context)); LLVM::CreateStore(*builder, llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), llvm::APInt(32, 0)), pos_ptr); @@ -2385,14 +2550,14 @@ namespace LCompilers { { llvm::Value *cond = builder->CreateICmpSGT( src_end_point, - LLVM::CreateLoad(*builder, pos_ptr)); + llvm_utils->CreateLoad(pos_ptr)); builder->CreateCondBr(cond, loopbody, loopend); } // body llvm_utils->start_new_block(loopbody); { - llvm::Value* pos = LLVM::CreateLoad(*builder, pos_ptr); + llvm::Value* pos = llvm_utils->CreateLoad(pos_ptr); llvm::Value* srci = read_item(src, pos, false, *module, true); llvm::Value* desti = read_item(dest, pos, false, *module, true); llvm_utils->deepcopy(srci, desti, element_type, module, name2memidx); @@ -2407,8 +2572,6 @@ namespace LCompilers { // end llvm_utils->start_new_block(loopend); } else { - llvm::Value* arg_size = builder->CreateMul(llvm::ConstantInt::get(context, - llvm::APInt(32, type_size)), src_capacity); builder->CreateMemCpy(copy_data, llvm::MaybeAlign(), src_data, llvm::MaybeAlign(), arg_size); builder->CreateStore(copy_data, get_pointer_to_list_data(dest)); @@ -2419,7 +2582,7 @@ namespace LCompilers { ASR::Dict_t* dict_type, llvm::Module* module, std::map>& name2memidx) { LCOMPILERS_ASSERT(src->getType() == dest->getType()); - llvm::Value* src_occupancy = LLVM::CreateLoad(*builder, get_pointer_to_occupancy(src)); + llvm::Value* src_occupancy = llvm_utils->CreateLoad(get_pointer_to_occupancy(src)); llvm::Value* dest_occupancy_ptr = get_pointer_to_occupancy(dest); LLVM::CreateStore(*builder, src_occupancy, dest_occupancy_ptr); @@ -2434,13 +2597,13 @@ namespace LCompilers { llvm_utils->list_api->list_deepcopy(src_value_list, dest_value_list, dict_type->m_value_type, module, name2memidx); - llvm::Value* src_key_mask = LLVM::CreateLoad(*builder, get_pointer_to_keymask(src)); + llvm::Value* src_key_mask = llvm_utils->CreateLoad(get_pointer_to_keymask(src)); llvm::Value* dest_key_mask_ptr = get_pointer_to_keymask(dest); llvm::DataLayout data_layout(module); size_t mask_size = data_layout.getTypeAllocSize(llvm::Type::getInt8Ty(context)); llvm::Value* llvm_mask_size = llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), llvm::APInt(32, mask_size)); - llvm::Value* src_capacity = LLVM::CreateLoad(*builder, get_pointer_to_capacity(src)); + llvm::Value* src_capacity = llvm_utils->CreateLoad(get_pointer_to_capacity(src)); llvm::Value* dest_key_mask = LLVM::lfortran_calloc(context, *module, *builder, src_capacity, llvm_mask_size); builder->CreateMemCpy(dest_key_mask, llvm::MaybeAlign(), src_key_mask, @@ -2452,15 +2615,14 @@ namespace LCompilers { llvm::Value* srci, llvm::Value* desti, llvm::Value* dest_key_value_pairs, ASR::Dict_t* dict_type, llvm::Module* module, std::map>& name2memidx) { - get_builder0() - src_itr = builder0.CreateAlloca(llvm::Type::getInt8PtrTy(context), nullptr); - dest_itr = builder0.CreateAlloca(llvm::Type::getInt8PtrTy(context), nullptr); + src_itr = llvm_utils->CreateAlloca(llvm::Type::getInt8Ty(context)->getPointerTo()); + dest_itr = llvm_utils->CreateAlloca(llvm::Type::getInt8Ty(context)->getPointerTo()); llvm::Type* key_value_pair_type = get_key_value_pair_type(dict_type->m_key_type, dict_type->m_value_type)->getPointerTo(); LLVM::CreateStore(*builder, - builder->CreateBitCast(srci, llvm::Type::getInt8PtrTy(context)), + builder->CreateBitCast(srci, llvm::Type::getInt8Ty(context)->getPointerTo()), src_itr); LLVM::CreateStore(*builder, - builder->CreateBitCast(desti, llvm::Type::getInt8PtrTy(context)), + builder->CreateBitCast(desti, llvm::Type::getInt8Ty(context)->getPointerTo()), dest_itr); llvm::BasicBlock *loophead = llvm::BasicBlock::Create(context, "loop.head"); llvm::BasicBlock *loopbody = llvm::BasicBlock::Create(context, "loop.body"); @@ -2469,8 +2631,8 @@ namespace LCompilers { llvm_utils->start_new_block(loophead); { llvm::Value *cond = builder->CreateICmpNE( - LLVM::CreateLoad(*builder, src_itr), - llvm::ConstantPointerNull::get(llvm::Type::getInt8PtrTy(context)) + llvm_utils->CreateLoad(src_itr), + llvm::ConstantPointerNull::get(llvm::Type::getInt8Ty(context)->getPointerTo()) ); builder->CreateCondBr(cond, loopbody, loopend); } @@ -2478,25 +2640,25 @@ namespace LCompilers { // body llvm_utils->start_new_block(loopbody); { - llvm::Value* curr_src = builder->CreateBitCast(LLVM::CreateLoad(*builder, src_itr), + llvm::Value* curr_src = builder->CreateBitCast(llvm_utils->CreateLoad(src_itr), key_value_pair_type); - llvm::Value* curr_dest = builder->CreateBitCast(LLVM::CreateLoad(*builder, dest_itr), + llvm::Value* curr_dest = builder->CreateBitCast(llvm_utils->CreateLoad(dest_itr), key_value_pair_type); llvm::Value* src_key_ptr = llvm_utils->create_gep(curr_src, 0); llvm::Value* src_value_ptr = llvm_utils->create_gep(curr_src, 1); llvm::Value *src_key = src_key_ptr, *src_value = src_value_ptr; if( !LLVM::is_llvm_struct(dict_type->m_key_type) ) { - src_key = LLVM::CreateLoad(*builder, src_key_ptr); + src_key = llvm_utils->CreateLoad(src_key_ptr); } if( !LLVM::is_llvm_struct(dict_type->m_value_type) ) { - src_value = LLVM::CreateLoad(*builder, src_value_ptr); + src_value = llvm_utils->CreateLoad(src_value_ptr); } llvm::Value* dest_key_ptr = llvm_utils->create_gep(curr_dest, 0); llvm::Value* dest_value_ptr = llvm_utils->create_gep(curr_dest, 1); llvm_utils->deepcopy(src_key, dest_key_ptr, dict_type->m_key_type, module, name2memidx); llvm_utils->deepcopy(src_value, dest_value_ptr, dict_type->m_value_type, module, name2memidx); - llvm::Value* src_next_ptr = LLVM::CreateLoad(*builder, llvm_utils->create_gep(curr_src, 2)); + llvm::Value* src_next_ptr = llvm_utils->CreateLoad(llvm_utils->create_gep(curr_src, 2)); llvm::Value* curr_dest_next_ptr = llvm_utils->create_gep(curr_dest, 2); LLVM::CreateStore(*builder, src_next_ptr, src_itr); llvm::Function *fn = builder->GetInsertBlock()->getParent(); @@ -2504,13 +2666,13 @@ namespace LCompilers { llvm::BasicBlock *elseBB = llvm::BasicBlock::Create(context, "else"); llvm::BasicBlock *mergeBB = llvm::BasicBlock::Create(context, "ifcont"); llvm::Value* src_next_exists = builder->CreateICmpNE(src_next_ptr, - llvm::ConstantPointerNull::get(llvm::Type::getInt8PtrTy(context))); + llvm::ConstantPointerNull::get(llvm::Type::getInt8Ty(context)->getPointerTo())); builder->CreateCondBr(src_next_exists, thenBB, elseBB); builder->SetInsertPoint(thenBB); { - llvm::Value* next_idx = LLVM::CreateLoad(*builder, next_ptr); + llvm::Value* next_idx = llvm_utils->CreateLoad(next_ptr); llvm::Value* dest_next_ptr = llvm_utils->create_ptr_gep(dest_key_value_pairs, next_idx); - dest_next_ptr = builder->CreateBitCast(dest_next_ptr, llvm::Type::getInt8PtrTy(context)); + dest_next_ptr = builder->CreateBitCast(dest_next_ptr, llvm::Type::getInt8Ty(context)->getPointerTo()); LLVM::CreateStore(*builder, dest_next_ptr, curr_dest_next_ptr); LLVM::CreateStore(*builder, dest_next_ptr, dest_itr); next_idx = builder->CreateAdd(next_idx, llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), @@ -2521,7 +2683,7 @@ namespace LCompilers { llvm_utils->start_new_block(elseBB); { LLVM::CreateStore(*builder, - llvm::ConstantPointerNull::get(llvm::Type::getInt8PtrTy(context)), + llvm::ConstantPointerNull::get(llvm::Type::getInt8Ty(context)->getPointerTo()), curr_dest_next_ptr ); } @@ -2538,11 +2700,10 @@ namespace LCompilers { llvm::Value* kv_ll, llvm::Value* dict, llvm::Value* capacity, ASR::ttype_t* m_key_type, ASR::ttype_t* m_value_type, llvm::Module* module, std::map>& name2memidx) { - get_builder0() - src_itr = builder0.CreateAlloca(llvm::Type::getInt8PtrTy(context), nullptr); + src_itr = llvm_utils->CreateAlloca(llvm::Type::getInt8Ty(context)->getPointerTo()); llvm::Type* key_value_pair_type = get_key_value_pair_type(m_key_type, m_value_type)->getPointerTo(); LLVM::CreateStore(*builder, - builder->CreateBitCast(kv_ll, llvm::Type::getInt8PtrTy(context)), + builder->CreateBitCast(kv_ll, llvm::Type::getInt8Ty(context)->getPointerTo()), src_itr); llvm::BasicBlock *loophead = llvm::BasicBlock::Create(context, "loop.head"); llvm::BasicBlock *loopbody = llvm::BasicBlock::Create(context, "loop.body"); @@ -2551,8 +2712,8 @@ namespace LCompilers { llvm_utils->start_new_block(loophead); { llvm::Value *cond = builder->CreateICmpNE( - LLVM::CreateLoad(*builder, src_itr), - llvm::ConstantPointerNull::get(llvm::Type::getInt8PtrTy(context)) + llvm_utils->CreateLoad(src_itr), + llvm::ConstantPointerNull::get(llvm::Type::getInt8Ty(context)->getPointerTo()) ); builder->CreateCondBr(cond, loopbody, loopend); } @@ -2560,16 +2721,16 @@ namespace LCompilers { // body llvm_utils->start_new_block(loopbody); { - llvm::Value* curr_src = builder->CreateBitCast(LLVM::CreateLoad(*builder, src_itr), + llvm::Value* curr_src = builder->CreateBitCast(llvm_utils->CreateLoad(src_itr), key_value_pair_type); llvm::Value* src_key_ptr = llvm_utils->create_gep(curr_src, 0); llvm::Value* src_value_ptr = llvm_utils->create_gep(curr_src, 1); llvm::Value *src_key = src_key_ptr, *src_value = src_value_ptr; if( !LLVM::is_llvm_struct(m_key_type) ) { - src_key = LLVM::CreateLoad(*builder, src_key_ptr); + src_key = llvm_utils->CreateLoad(src_key_ptr); } if( !LLVM::is_llvm_struct(m_value_type) ) { - src_value = LLVM::CreateLoad(*builder, src_value_ptr); + src_value = llvm_utils->CreateLoad(src_value_ptr); } llvm::Value* key_hash = get_key_hash(capacity, src_key, m_key_type, *module); resolve_collision_for_write( @@ -2578,7 +2739,7 @@ namespace LCompilers { m_key_type, m_value_type, name2memidx); - llvm::Value* src_next_ptr = LLVM::CreateLoad(*builder, llvm_utils->create_gep(curr_src, 2)); + llvm::Value* src_next_ptr = llvm_utils->CreateLoad(llvm_utils->create_gep(curr_src, 2)); LLVM::CreateStore(*builder, src_next_ptr, src_itr); } @@ -2592,11 +2753,11 @@ namespace LCompilers { llvm::Value* src, llvm::Value* dest, ASR::Dict_t* dict_type, llvm::Module* module, std::map>& name2memidx) { - llvm::Value* src_occupancy = LLVM::CreateLoad(*builder, get_pointer_to_occupancy(src)); - llvm::Value* src_filled_buckets = LLVM::CreateLoad(*builder, get_pointer_to_number_of_filled_buckets(src)); - llvm::Value* src_capacity = LLVM::CreateLoad(*builder, get_pointer_to_capacity(src)); - llvm::Value* src_key_mask = LLVM::CreateLoad(*builder, get_pointer_to_keymask(src)); - llvm::Value* src_rehash_flag = LLVM::CreateLoad(*builder, get_pointer_to_rehash_flag(src)); + llvm::Value* src_occupancy = llvm_utils->CreateLoad(get_pointer_to_occupancy(src)); + llvm::Value* src_filled_buckets = llvm_utils->CreateLoad(get_pointer_to_number_of_filled_buckets(src)); + llvm::Value* src_capacity = llvm_utils->CreateLoad(get_pointer_to_capacity(src)); + llvm::Value* src_key_mask = llvm_utils->CreateLoad(get_pointer_to_keymask(src)); + llvm::Value* src_rehash_flag = llvm_utils->CreateLoad(get_pointer_to_rehash_flag(src)); LLVM::CreateStore(*builder, src_occupancy, get_pointer_to_occupancy(dest)); LLVM::CreateStore(*builder, src_filled_buckets, get_pointer_to_number_of_filled_buckets(dest)); LLVM::CreateStore(*builder, src_capacity, get_pointer_to_capacity(dest)); @@ -2619,14 +2780,13 @@ namespace LCompilers { dest_key_value_pairs = builder->CreateBitCast( dest_key_value_pairs, get_key_value_pair_type(dict_type->m_key_type, dict_type->m_value_type)->getPointerTo()); - get_builder0() - copy_itr = builder0.CreateAlloca(llvm::Type::getInt32Ty(context), nullptr); - next_ptr = builder0.CreateAlloca(llvm::Type::getInt32Ty(context), nullptr); + copy_itr = llvm_utils->CreateAlloca(llvm::Type::getInt32Ty(context)); + next_ptr = llvm_utils->CreateAlloca(llvm::Type::getInt32Ty(context)); llvm::Value* llvm_zero = llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), llvm::APInt(32, 0)); LLVM::CreateStore(*builder, llvm_zero, copy_itr); LLVM::CreateStore(*builder, src_capacity, next_ptr); - llvm::Value* src_key_value_pairs = LLVM::CreateLoad(*builder, get_pointer_to_key_value_pairs(src)); + llvm::Value* src_key_value_pairs = llvm_utils->CreateLoad(get_pointer_to_key_value_pairs(src)); llvm::BasicBlock *loophead = llvm::BasicBlock::Create(context, "loop.head"); llvm::BasicBlock *loopbody = llvm::BasicBlock::Create(context, "loop.body"); llvm::BasicBlock *loopend = llvm::BasicBlock::Create(context, "loop.end"); @@ -2636,15 +2796,15 @@ namespace LCompilers { { llvm::Value *cond = builder->CreateICmpSGT( src_capacity, - LLVM::CreateLoad(*builder, copy_itr)); + llvm_utils->CreateLoad(copy_itr)); builder->CreateCondBr(cond, loopbody, loopend); } // body llvm_utils->start_new_block(loopbody); { - llvm::Value* itr = LLVM::CreateLoad(*builder, copy_itr); - llvm::Value* key_mask_value = LLVM::CreateLoad(*builder, + llvm::Value* itr = llvm_utils->CreateLoad(copy_itr); + llvm::Value* key_mask_value = llvm_utils->CreateLoad( llvm_utils->create_ptr_gep(src_key_mask, itr)); LLVM::CreateStore(*builder, key_mask_value, llvm_utils->create_ptr_gep(dest_key_mask, itr)); @@ -2673,7 +2833,7 @@ namespace LCompilers { void LLVMList::check_index_within_bounds(llvm::Value* list, llvm::Value* pos, llvm::Module& module) { - llvm::Value* end_point = LLVM::CreateLoad(*builder, + llvm::Value* end_point = llvm_utils->CreateLoad( get_pointer_to_current_end_point(list)); llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), llvm::APInt(32, 0)); @@ -2707,7 +2867,7 @@ namespace LCompilers { if( enable_bounds_checking ) { check_index_within_bounds(list, pos, *module); } - llvm::Value* list_data = LLVM::CreateLoad(*builder, get_pointer_to_list_data(list)); + llvm::Value* list_data = llvm_utils->CreateLoad(get_pointer_to_list_data(list)); llvm::Value* element_ptr = llvm_utils->create_ptr_gep(list_data, pos); llvm_utils->deepcopy(item, element_ptr, asr_type, module, name2memidx); } @@ -2718,7 +2878,7 @@ namespace LCompilers { if( enable_bounds_checking ) { check_index_within_bounds(list, pos, module); } - llvm::Value* list_data = LLVM::CreateLoad(*builder, get_pointer_to_list_data(list)); + llvm::Value* list_data = llvm_utils->CreateLoad(get_pointer_to_list_data(list)); llvm::Value* element_ptr = llvm_utils->create_ptr_gep(list_data, pos); LLVM::CreateStore(*builder, item, element_ptr); } @@ -2736,9 +2896,8 @@ namespace LCompilers { llvm::Value* key, llvm::Value* key_list, llvm::Value* key_mask, llvm::Module& module, ASR::ttype_t* key_asr_type, bool for_read) { - get_builder0() - pos_ptr = builder0.CreateAlloca(llvm::Type::getInt32Ty(context), nullptr); - is_key_matching_var = builder0.CreateAlloca(llvm::Type::getInt1Ty(context), nullptr); + pos_ptr = llvm_utils->CreateAlloca(llvm::Type::getInt32Ty(context)); + is_key_matching_var = llvm_utils->CreateAlloca(llvm::Type::getInt1Ty(context)); LLVM::CreateStore(*builder, key_hash, pos_ptr); @@ -2750,8 +2909,8 @@ namespace LCompilers { // head llvm_utils->start_new_block(loophead); { - llvm::Value* pos = LLVM::CreateLoad(*builder, pos_ptr); - llvm::Value* key_mask_value = LLVM::CreateLoad(*builder, + llvm::Value* pos = llvm_utils->CreateLoad(pos_ptr); + llvm::Value* key_mask_value = llvm_utils->CreateLoad( llvm_utils->create_ptr_gep(key_mask, pos)); llvm::Value* is_key_skip = builder->CreateICmpEQ(key_mask_value, llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), llvm::APInt(8, 3))); @@ -2779,12 +2938,12 @@ namespace LCompilers { llvm::Value *cond = nullptr; if( for_read ) { cond = builder->CreateAnd(is_key_set, builder->CreateNot( - LLVM::CreateLoad(*builder, is_key_matching_var))); + llvm_utils->CreateLoad(is_key_matching_var))); cond = builder->CreateOr(is_key_skip, cond); } else { cond = builder->CreateAnd(is_key_set, builder->CreateNot(is_key_skip)); cond = builder->CreateAnd(cond, builder->CreateNot( - LLVM::CreateLoad(*builder, is_key_matching_var))); + llvm_utils->CreateLoad(is_key_matching_var))); } builder->CreateCondBr(cond, loopbody, loopend); } @@ -2793,7 +2952,7 @@ namespace LCompilers { // body llvm_utils->start_new_block(loopbody); { - llvm::Value* pos = LLVM::CreateLoad(*builder, pos_ptr); + llvm::Value* pos = llvm_utils->CreateLoad(pos_ptr); pos = builder->CreateAdd(pos, llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), llvm::APInt(32, 1))); pos = builder->CreateSRem(pos, capacity); @@ -2852,12 +3011,10 @@ namespace LCompilers { * } * */ - - get_builder0() if( !for_read ) { - pos_ptr = builder0.CreateAlloca(llvm::Type::getInt32Ty(context), nullptr); + pos_ptr = llvm_utils->CreateAlloca(llvm::Type::getInt32Ty(context)); } - is_key_matching_var = builder0.CreateAlloca(llvm::Type::getInt1Ty(context), nullptr); + is_key_matching_var = llvm_utils->CreateAlloca(llvm::Type::getInt1Ty(context)); LLVM::CreateStore(*builder, key_hash, pos_ptr); @@ -2868,8 +3025,8 @@ namespace LCompilers { // head llvm_utils->start_new_block(loophead); { - llvm::Value* pos = LLVM::CreateLoad(*builder, pos_ptr); - llvm::Value* key_mask_value = LLVM::CreateLoad(*builder, + llvm::Value* pos = llvm_utils->CreateLoad(pos_ptr); + llvm::Value* key_mask_value = llvm_utils->CreateLoad( llvm_utils->create_ptr_gep(key_mask, pos)); llvm::Value* is_key_skip = builder->CreateICmpEQ(key_mask_value, llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), llvm::APInt(8, 3))); @@ -2896,12 +3053,12 @@ namespace LCompilers { llvm::Value *cond = nullptr; if( for_read ) { cond = builder->CreateAnd(is_key_set, builder->CreateNot( - LLVM::CreateLoad(*builder, is_key_matching_var))); + llvm_utils->CreateLoad(is_key_matching_var))); cond = builder->CreateOr(is_key_skip, cond); } else { cond = builder->CreateAnd(is_key_set, builder->CreateNot(is_key_skip)); cond = builder->CreateAnd(cond, builder->CreateNot( - LLVM::CreateLoad(*builder, is_key_matching_var))); + llvm_utils->CreateLoad(is_key_matching_var))); } builder->CreateCondBr(cond, loopbody, loopend); } @@ -2909,7 +3066,7 @@ namespace LCompilers { // body llvm_utils->start_new_block(loopbody); { - llvm::Value* pos = LLVM::CreateLoad(*builder, pos_ptr); + llvm::Value* pos = llvm_utils->CreateLoad(pos_ptr); pos = builder->CreateAdd(pos, llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), llvm::APInt(32, 1))); pos = builder->CreateSRem(pos, capacity); @@ -2953,24 +3110,22 @@ namespace LCompilers { * // now, chain_itr either points to kv or is nullptr * */ - - get_builder0() - chain_itr = builder0.CreateAlloca(llvm::Type::getInt8PtrTy(context), nullptr); - chain_itr_prev = builder0.CreateAlloca(llvm::Type::getInt8PtrTy(context), nullptr); - is_key_matching_var = builder0.CreateAlloca(llvm::Type::getInt1Ty(context), nullptr); + chain_itr = llvm_utils->CreateAlloca(llvm::Type::getInt8Ty(context)->getPointerTo()); + chain_itr_prev = llvm_utils->CreateAlloca(llvm::Type::getInt8Ty(context)->getPointerTo()); + is_key_matching_var = llvm_utils->CreateAlloca(llvm::Type::getInt1Ty(context)); LLVM::CreateStore(*builder, - llvm::ConstantPointerNull::get(llvm::Type::getInt8PtrTy(context)), chain_itr_prev); - llvm::Value* key_mask_value = LLVM::CreateLoad(*builder, + llvm::ConstantPointerNull::get(llvm::Type::getInt8Ty(context)->getPointerTo()), chain_itr_prev); + llvm::Value* key_mask_value = llvm_utils->CreateLoad( llvm_utils->create_ptr_gep(key_mask, key_hash)); llvm_utils->create_if_else(builder->CreateICmpEQ(key_mask_value, llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), llvm::APInt(8, 1))), [&]() { llvm::Value* kv_ll_i8 = builder->CreateBitCast(key_value_pair_linked_list, - llvm::Type::getInt8PtrTy(context)); + llvm::Type::getInt8Ty(context)->getPointerTo()); LLVM::CreateStore(*builder, kv_ll_i8, chain_itr); }, [&]() { LLVM::CreateStore(*builder, - llvm::ConstantPointerNull::get(llvm::Type::getInt8PtrTy(context)), chain_itr); + llvm::ConstantPointerNull::get(llvm::Type::getInt8Ty(context)->getPointerTo()), chain_itr); }); LLVM::CreateStore(*builder, llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), llvm::APInt(1, 0)), @@ -2984,28 +3139,28 @@ namespace LCompilers { llvm_utils->start_new_block(loophead); { llvm::Value *cond = builder->CreateICmpNE( - LLVM::CreateLoad(*builder, chain_itr), - llvm::ConstantPointerNull::get(llvm::Type::getInt8PtrTy(context)) + llvm_utils->CreateLoad(chain_itr), + llvm::ConstantPointerNull::get(llvm::Type::getInt8Ty(context)->getPointerTo()) ); - cond = builder->CreateAnd(cond, builder->CreateNot(LLVM::CreateLoad( - *builder, is_key_matching_var))); + cond = builder->CreateAnd(cond, builder->CreateNot( + llvm_utils->CreateLoad(is_key_matching_var))); builder->CreateCondBr(cond, loopbody, loopend); } // body llvm_utils->start_new_block(loopbody); { - llvm::Value* kv_struct_i8 = LLVM::CreateLoad(*builder, chain_itr); + llvm::Value* kv_struct_i8 = llvm_utils->CreateLoad(chain_itr); llvm::Value* kv_struct = builder->CreateBitCast(kv_struct_i8, kv_pair_type->getPointerTo()); llvm::Value* kv_struct_key = llvm_utils->create_gep(kv_struct, 0); if( !LLVM::is_llvm_struct(key_asr_type) ) { - kv_struct_key = LLVM::CreateLoad(*builder, kv_struct_key); + kv_struct_key = llvm_utils->CreateLoad(kv_struct_key); } LLVM::CreateStore(*builder, llvm_utils->is_equal_by_value(key, kv_struct_key, module, key_asr_type), is_key_matching_var); - llvm_utils->create_if_else(builder->CreateNot(LLVM::CreateLoad(*builder, is_key_matching_var)), [&]() { + llvm_utils->create_if_else(builder->CreateNot(llvm_utils->CreateLoad(is_key_matching_var)), [&]() { LLVM::CreateStore(*builder, kv_struct_i8, chain_itr_prev); - llvm::Value* next_kv_struct = LLVM::CreateLoad(*builder, llvm_utils->create_gep(kv_struct, 2)); + llvm::Value* next_kv_struct = llvm_utils->CreateLoad(llvm_utils->create_gep(kv_struct, 2)); LLVM::CreateStore(*builder, next_kv_struct, chain_itr); }, []() {}); } @@ -3024,15 +3179,15 @@ namespace LCompilers { std::map>& name2memidx) { llvm::Value* key_list = get_key_list(dict); llvm::Value* value_list = get_value_list(dict); - llvm::Value* key_mask = LLVM::CreateLoad(*builder, get_pointer_to_keymask(dict)); - llvm::Value* capacity = LLVM::CreateLoad(*builder, get_pointer_to_capacity(dict)); + llvm::Value* key_mask = llvm_utils->CreateLoad(get_pointer_to_keymask(dict)); + llvm::Value* capacity = llvm_utils->CreateLoad(get_pointer_to_capacity(dict)); this->resolve_collision(capacity, key_hash, key, key_list, key_mask, *module, key_asr_type); - llvm::Value* pos = LLVM::CreateLoad(*builder, pos_ptr); + llvm::Value* pos = llvm_utils->CreateLoad(pos_ptr); llvm_utils->list_api->write_item(key_list, pos, key, key_asr_type, false, module, name2memidx); llvm_utils->list_api->write_item(value_list, pos, value, value_asr_type, false, module, name2memidx); - llvm::Value* key_mask_value = LLVM::CreateLoad(*builder, + llvm::Value* key_mask_value = llvm_utils->CreateLoad( llvm_utils->create_ptr_gep(key_mask, pos)); llvm::Value* is_slot_empty = builder->CreateICmpEQ(key_mask_value, llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), llvm::APInt(8, 0))); @@ -3040,7 +3195,7 @@ namespace LCompilers { llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), llvm::APInt(8, 3)))); llvm::Value* occupancy_ptr = get_pointer_to_occupancy(dict); is_slot_empty = builder->CreateZExt(is_slot_empty, llvm::Type::getInt32Ty(context)); - llvm::Value* occupancy = LLVM::CreateLoad(*builder, occupancy_ptr); + llvm::Value* occupancy = llvm_utils->CreateLoad(occupancy_ptr); LLVM::CreateStore(*builder, builder->CreateAdd(occupancy, is_slot_empty), occupancy_ptr); LLVM::CreateStore(*builder, @@ -3076,16 +3231,16 @@ namespace LCompilers { llvm::Value* key_list = get_key_list(dict); llvm::Value* value_list = get_value_list(dict); - llvm::Value* key_mask = LLVM::CreateLoad(*builder, get_pointer_to_keymask(dict)); - llvm::Value* capacity = LLVM::CreateLoad(*builder, get_pointer_to_capacity(dict)); + llvm::Value* key_mask = llvm_utils->CreateLoad(get_pointer_to_keymask(dict)); + llvm::Value* capacity = llvm_utils->CreateLoad(get_pointer_to_capacity(dict)); this->resolve_collision(capacity, key_hash, key, key_list, key_mask, *module, key_asr_type); - llvm::Value* pos = LLVM::CreateLoad(*builder, pos_ptr); + llvm::Value* pos = llvm_utils->CreateLoad(pos_ptr); llvm_utils->list_api->write_item(key_list, pos, key, key_asr_type, false, module, name2memidx); llvm_utils->list_api->write_item(value_list, pos, value, value_asr_type, false, module, name2memidx); - llvm::Value* key_mask_value = LLVM::CreateLoad(*builder, + llvm::Value* key_mask_value = llvm_utils->CreateLoad( llvm_utils->create_ptr_gep(key_mask, pos)); llvm::Value* is_slot_empty = builder->CreateICmpEQ(key_mask_value, llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), llvm::APInt(8, 0))); @@ -3093,14 +3248,14 @@ namespace LCompilers { llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), llvm::APInt(8, 3)))); llvm::Value* occupancy_ptr = get_pointer_to_occupancy(dict); is_slot_empty = builder->CreateZExt(is_slot_empty, llvm::Type::getInt32Ty(context)); - llvm::Value* occupancy = LLVM::CreateLoad(*builder, occupancy_ptr); + llvm::Value* occupancy = llvm_utils->CreateLoad(occupancy_ptr); LLVM::CreateStore(*builder, builder->CreateAdd(occupancy, is_slot_empty), occupancy_ptr); llvm::Value* linear_prob_happened = builder->CreateICmpNE(key_hash, pos); linear_prob_happened = builder->CreateOr(linear_prob_happened, builder->CreateICmpEQ( - LLVM::CreateLoad(*builder, llvm_utils->create_ptr_gep(key_mask, key_hash)), + llvm_utils->CreateLoad(llvm_utils->create_ptr_gep(key_mask, key_hash)), llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), llvm::APInt(8, 2) )) ); @@ -3151,28 +3306,28 @@ namespace LCompilers { * */ - llvm::Value* capacity = LLVM::CreateLoad(*builder, get_pointer_to_capacity(dict)); - llvm::Value* key_value_pairs = LLVM::CreateLoad(*builder, get_pointer_to_key_value_pairs(dict)); + llvm::Value* capacity = llvm_utils->CreateLoad(get_pointer_to_capacity(dict)); + llvm::Value* key_value_pairs = llvm_utils->CreateLoad(get_pointer_to_key_value_pairs(dict)); llvm::Value* key_value_pair_linked_list = llvm_utils->create_ptr_gep(key_value_pairs, key_hash); - llvm::Value* key_mask = LLVM::CreateLoad(*builder, get_pointer_to_keymask(dict)); + llvm::Value* key_mask = llvm_utils->CreateLoad(get_pointer_to_keymask(dict)); llvm::Type* kv_struct_type = get_key_value_pair_type(key_asr_type, value_asr_type); this->resolve_collision(capacity, key_hash, key, key_value_pair_linked_list, kv_struct_type, key_mask, *module, key_asr_type); - llvm::Value* kv_struct_i8 = LLVM::CreateLoad(*builder, chain_itr); + llvm::Value* kv_struct_i8 = llvm_utils->CreateLoad(chain_itr); llvm::Function *fn = builder->GetInsertBlock()->getParent(); llvm::BasicBlock *thenBB = llvm::BasicBlock::Create(context, "then", fn); llvm::BasicBlock *elseBB = llvm::BasicBlock::Create(context, "else"); llvm::BasicBlock *mergeBB = llvm::BasicBlock::Create(context, "ifcont"); llvm::Value* do_insert = builder->CreateICmpEQ(kv_struct_i8, - llvm::ConstantPointerNull::get(llvm::Type::getInt8PtrTy(context))); + llvm::ConstantPointerNull::get(llvm::Type::getInt8Ty(context)->getPointerTo())); builder->CreateCondBr(do_insert, thenBB, elseBB); builder->SetInsertPoint(thenBB); { llvm_utils->create_if_else(builder->CreateICmpNE( - LLVM::CreateLoad(*builder, chain_itr_prev), - llvm::ConstantPointerNull::get(llvm::Type::getInt8PtrTy(context))), [&]() { + llvm_utils->CreateLoad(chain_itr_prev), + llvm::ConstantPointerNull::get(llvm::Type::getInt8Ty(context)->getPointerTo())), [&]() { llvm::DataLayout data_layout(module); size_t kv_struct_size = data_layout.getTypeAllocSize(kv_struct_type); llvm::Value* malloc_size = llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), kv_struct_size); @@ -3181,21 +3336,21 @@ namespace LCompilers { llvm_utils->deepcopy(key, llvm_utils->create_gep(new_kv_struct, 0), key_asr_type, module, name2memidx); llvm_utils->deepcopy(value, llvm_utils->create_gep(new_kv_struct, 1), value_asr_type, module, name2memidx); LLVM::CreateStore(*builder, - llvm::ConstantPointerNull::get(llvm::Type::getInt8PtrTy(context)), + llvm::ConstantPointerNull::get(llvm::Type::getInt8Ty(context)->getPointerTo()), llvm_utils->create_gep(new_kv_struct, 2)); - llvm::Value* kv_struct_prev_i8 = LLVM::CreateLoad(*builder, chain_itr_prev); + llvm::Value* kv_struct_prev_i8 = llvm_utils->CreateLoad(chain_itr_prev); llvm::Value* kv_struct_prev = builder->CreateBitCast(kv_struct_prev_i8, kv_struct_type->getPointerTo()); LLVM::CreateStore(*builder, new_kv_struct_i8, llvm_utils->create_gep(kv_struct_prev, 2)); }, [&]() { llvm_utils->deepcopy(key, llvm_utils->create_gep(key_value_pair_linked_list, 0), key_asr_type, module, name2memidx); llvm_utils->deepcopy(value, llvm_utils->create_gep(key_value_pair_linked_list, 1), value_asr_type, module, name2memidx); LLVM::CreateStore(*builder, - llvm::ConstantPointerNull::get(llvm::Type::getInt8PtrTy(context)), + llvm::ConstantPointerNull::get(llvm::Type::getInt8Ty(context)->getPointerTo()), llvm_utils->create_gep(key_value_pair_linked_list, 2)); }); llvm::Value* occupancy_ptr = get_pointer_to_occupancy(dict); - llvm::Value* occupancy = LLVM::CreateLoad(*builder, occupancy_ptr); + llvm::Value* occupancy = llvm_utils->CreateLoad(occupancy_ptr); occupancy = builder->CreateAdd(occupancy, llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), 1)); LLVM::CreateStore(*builder, occupancy, occupancy_ptr); @@ -3210,10 +3365,10 @@ namespace LCompilers { llvm_utils->start_new_block(mergeBB); llvm::Value* buckets_filled_ptr = get_pointer_to_number_of_filled_buckets(dict); llvm::Value* key_mask_value_ptr = llvm_utils->create_ptr_gep(key_mask, key_hash); - llvm::Value* key_mask_value = LLVM::CreateLoad(*builder, key_mask_value_ptr); + llvm::Value* key_mask_value = llvm_utils->CreateLoad(key_mask_value_ptr); llvm::Value* buckets_filled_delta = builder->CreateICmpEQ(key_mask_value, llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), llvm::APInt(8, 0))); - llvm::Value* buckets_filled = LLVM::CreateLoad(*builder, buckets_filled_ptr); + llvm::Value* buckets_filled = llvm_utils->CreateLoad(buckets_filled_ptr); buckets_filled = builder->CreateAdd( buckets_filled, builder->CreateZExt(buckets_filled_delta, llvm::Type::getInt32Ty(context)) @@ -3230,10 +3385,10 @@ namespace LCompilers { ASR::ttype_t* key_asr_type, ASR::ttype_t* /*value_asr_type*/) { llvm::Value* key_list = get_key_list(dict); llvm::Value* value_list = get_value_list(dict); - llvm::Value* key_mask = LLVM::CreateLoad(*builder, get_pointer_to_keymask(dict)); - llvm::Value* capacity = LLVM::CreateLoad(*builder, get_pointer_to_capacity(dict)); + llvm::Value* key_mask = llvm_utils->CreateLoad(get_pointer_to_keymask(dict)); + llvm::Value* capacity = llvm_utils->CreateLoad(get_pointer_to_capacity(dict)); this->resolve_collision(capacity, key_hash, key, key_list, key_mask, module, key_asr_type, true); - llvm::Value* pos = LLVM::CreateLoad(*builder, pos_ptr); + llvm::Value* pos = llvm_utils->CreateLoad(pos_ptr); llvm::Value* item = llvm_utils->list_api->read_item(value_list, pos, false, module, true); return item; } @@ -3241,18 +3396,16 @@ namespace LCompilers { llvm::Value* LLVMDict::resolve_collision_for_read_with_bound_check( llvm::Value* dict, llvm::Value* key_hash, llvm::Value* key, llvm::Module& module, - ASR::ttype_t* key_asr_type, ASR::ttype_t* /*value_asr_type*/, bool check_if_exists) { + ASR::ttype_t* key_asr_type, ASR::ttype_t* /*value_asr_type*/) { llvm::Value* key_list = get_key_list(dict); llvm::Value* value_list = get_value_list(dict); - llvm::Value* key_mask = LLVM::CreateLoad(*builder, get_pointer_to_keymask(dict)); - llvm::Value* capacity = LLVM::CreateLoad(*builder, get_pointer_to_capacity(dict)); + llvm::Value* key_mask = llvm_utils->CreateLoad(get_pointer_to_keymask(dict)); + llvm::Value* capacity = llvm_utils->CreateLoad(get_pointer_to_capacity(dict)); this->resolve_collision(capacity, key_hash, key, key_list, key_mask, module, key_asr_type, true); - llvm::Value* pos = LLVM::CreateLoad(*builder, pos_ptr); + llvm::Value* pos = llvm_utils->CreateLoad(pos_ptr); llvm::Value* is_key_matching = llvm_utils->is_equal_by_value(key, llvm_utils->list_api->read_item(key_list, pos, false, module, LLVM::is_llvm_struct(key_asr_type)), module, key_asr_type); - if (check_if_exists) - return is_key_matching; llvm_utils->create_if_else(is_key_matching, [&]() { }, [&]() { @@ -3281,7 +3434,7 @@ namespace LCompilers { false, module, false); LLVM::CreateStore(*builder, item, result); }, [=]() { - LLVM::CreateStore(*builder, LLVM::CreateLoad(*builder, def_value), result); + LLVM::CreateStore(*builder, llvm_utils->CreateLoad(def_value), result); }); } @@ -3292,17 +3445,16 @@ namespace LCompilers { llvm::Value* def_value) { llvm::Value* key_list = get_key_list(dict); llvm::Value* value_list = get_value_list(dict); - llvm::Value* key_mask = LLVM::CreateLoad(*builder, get_pointer_to_keymask(dict)); - llvm::Value* capacity = LLVM::CreateLoad(*builder, get_pointer_to_capacity(dict)); + llvm::Value* key_mask = llvm_utils->CreateLoad(get_pointer_to_keymask(dict)); + llvm::Value* capacity = llvm_utils->CreateLoad(get_pointer_to_capacity(dict)); this->resolve_collision(capacity, key_hash, key, key_list, key_mask, module, key_asr_type, true); - llvm::Value* pos = LLVM::CreateLoad(*builder, pos_ptr); + llvm::Value* pos = llvm_utils->CreateLoad(pos_ptr); std::pair llvm_key = std::make_pair( ASRUtils::get_type_code(key_asr_type), ASRUtils::get_type_code(value_asr_type) ); - get_builder0() llvm::Type* value_type = std::get<2>(typecode2dicttype[llvm_key]).second; - llvm::Value* result = builder0.CreateAlloca(value_type, nullptr); + llvm::Value* result = llvm_utils->CreateAlloca(value_type); _check_key_present_or_default(module, key, key_list, key_asr_type, value_list, pos, def_value, result); return result; @@ -3311,7 +3463,7 @@ namespace LCompilers { llvm::Value* LLVMDictOptimizedLinearProbing::resolve_collision_for_read_with_bound_check( llvm::Value* dict, llvm::Value* key_hash, llvm::Value* key, llvm::Module& module, - ASR::ttype_t* key_asr_type, ASR::ttype_t* /*value_asr_type*/, bool check_if_exists) { + ASR::ttype_t* key_asr_type, ASR::ttype_t* /*value_asr_type*/) { /** * C++ equivalent: @@ -3341,21 +3493,17 @@ namespace LCompilers { llvm::Value* key_list = get_key_list(dict); llvm::Value* value_list = get_value_list(dict); - llvm::Value* key_mask = LLVM::CreateLoad(*builder, get_pointer_to_keymask(dict)); - llvm::Value* capacity = LLVM::CreateLoad(*builder, get_pointer_to_capacity(dict)); - get_builder0() - pos_ptr = builder0.CreateAlloca(llvm::Type::getInt32Ty(context), nullptr); + llvm::Value* key_mask = llvm_utils->CreateLoad(get_pointer_to_keymask(dict)); + llvm::Value* capacity = llvm_utils->CreateLoad(get_pointer_to_capacity(dict)); + pos_ptr = llvm_utils->CreateAlloca(llvm::Type::getInt32Ty(context)); llvm::Function *fn = builder->GetInsertBlock()->getParent(); llvm::BasicBlock *thenBB = llvm::BasicBlock::Create(context, "then", fn); llvm::BasicBlock *elseBB = llvm::BasicBlock::Create(context, "else"); llvm::BasicBlock *mergeBB = llvm::BasicBlock::Create(context, "ifcont"); - llvm::Value* key_mask_value = LLVM::CreateLoad(*builder, + llvm::Value* key_mask_value = llvm_utils->CreateLoad( llvm_utils->create_ptr_gep(key_mask, key_hash)); llvm::Value* is_prob_not_neeeded = builder->CreateICmpEQ(key_mask_value, llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), llvm::APInt(8, 1))); - llvm::AllocaInst *flag_ptr = builder0.CreateAlloca(llvm::Type::getInt1Ty(context), nullptr); - LLVM::CreateStore(*builder, llvm::ConstantInt::get(llvm::Type::getInt1Ty(context), 0), flag_ptr); - LLVM::CreateStore(*builder, llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), 0), pos_ptr); builder->CreateCondBr(is_prob_not_neeeded, thenBB, elseBB); builder->SetInsertPoint(thenBB); { @@ -3373,9 +3521,6 @@ namespace LCompilers { llvm_utils->create_if_else(is_key_matching, [=]() { LLVM::CreateStore(*builder, key_hash, pos_ptr); }, [&]() { - if (check_if_exists) { - LLVM::CreateStore(*builder, llvm::ConstantInt::get(llvm::Type::getInt1Ty(context), 1), flag_ptr); - } else { std::string message = "The dict does not contain the specified key"; llvm::Value *fmt_ptr = builder->CreateGlobalStringPtr("KeyError: %s\n"); llvm::Value *fmt_ptr2 = builder->CreateGlobalStringPtr(message); @@ -3384,7 +3529,7 @@ namespace LCompilers { llvm::Value *exit_code = llvm::ConstantInt::get(context, llvm::APInt(32, exit_code_int)); exit(context, module, *builder, exit_code); - }}); + }); } builder->CreateBr(mergeBB); llvm_utils->start_new_block(elseBB); @@ -3393,29 +3538,11 @@ namespace LCompilers { module, key_asr_type, true); } llvm_utils->start_new_block(mergeBB); - llvm::Value *pos = LLVM::CreateLoad(*builder, pos_ptr); - llvm::Value* pos_mask_value = LLVM::CreateLoad(*builder, - llvm_utils->create_ptr_gep(key_mask, pos)); - llvm::Value *flag = builder->CreateOr( - builder->CreateICmpEQ(pos_mask_value, - llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), llvm::APInt(8, 0))), - LLVM::CreateLoad(*builder, flag_ptr)); - llvm::AllocaInst *is_key_matching_ptr = builder0.CreateAlloca(llvm::Type::getInt1Ty(context), nullptr); - - llvm_utils->create_if_else(flag, [&](){ - LLVM::CreateStore(*builder, llvm::ConstantInt::get(llvm::Type::getInt1Ty(context), 0), is_key_matching_ptr); - }, [&](){ - // Check if the actual element is present or not - LLVM::CreateStore(*builder, llvm_utils->is_equal_by_value(key, + llvm::Value* pos = llvm_utils->CreateLoad(pos_ptr); + // Check if the actual key is present or not + llvm::Value* is_key_matching = llvm_utils->is_equal_by_value(key, llvm_utils->list_api->read_item(key_list, pos, false, module, - LLVM::is_llvm_struct(key_asr_type)), module, key_asr_type), is_key_matching_ptr); - }); - - llvm::Value *is_key_matching = LLVM::CreateLoad(*builder, is_key_matching_ptr); - - if (check_if_exists) { - return is_key_matching; - } + LLVM::is_llvm_struct(key_asr_type)), module, key_asr_type); llvm_utils->create_if_else(is_key_matching, [&]() { }, [&]() { @@ -3439,15 +3566,14 @@ namespace LCompilers { ASR::ttype_t* key_asr_type, ASR::ttype_t* /*value_asr_type*/) { llvm::Value* key_list = get_key_list(dict); llvm::Value* value_list = get_value_list(dict); - llvm::Value* key_mask = LLVM::CreateLoad(*builder, get_pointer_to_keymask(dict)); - llvm::Value* capacity = LLVM::CreateLoad(*builder, get_pointer_to_capacity(dict)); - get_builder0() - pos_ptr = builder0.CreateAlloca(llvm::Type::getInt32Ty(context), nullptr); + llvm::Value* key_mask = llvm_utils->CreateLoad(get_pointer_to_keymask(dict)); + llvm::Value* capacity = llvm_utils->CreateLoad(get_pointer_to_capacity(dict)); + pos_ptr = llvm_utils->CreateAlloca(llvm::Type::getInt32Ty(context)); llvm::Function *fn = builder->GetInsertBlock()->getParent(); llvm::BasicBlock *thenBB = llvm::BasicBlock::Create(context, "then", fn); llvm::BasicBlock *elseBB = llvm::BasicBlock::Create(context, "else"); llvm::BasicBlock *mergeBB = llvm::BasicBlock::Create(context, "ifcont"); - llvm::Value* key_mask_value = LLVM::CreateLoad(*builder, + llvm::Value* key_mask_value = llvm_utils->CreateLoad( llvm_utils->create_ptr_gep(key_mask, key_hash)); llvm::Value* is_prob_not_neeeded = builder->CreateICmpEQ(key_mask_value, llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), llvm::APInt(8, 1))); @@ -3477,7 +3603,7 @@ namespace LCompilers { module, key_asr_type, true); } llvm_utils->start_new_block(mergeBB); - llvm::Value* pos = LLVM::CreateLoad(*builder, pos_ptr); + llvm::Value* pos = llvm_utils->CreateLoad(pos_ptr); llvm::Value* item = llvm_utils->list_api->read_item(value_list, pos, false, module, true); return item; @@ -3490,21 +3616,20 @@ namespace LCompilers { llvm::Value *def_value) { llvm::Value* key_list = get_key_list(dict); llvm::Value* value_list = get_value_list(dict); - llvm::Value* key_mask = LLVM::CreateLoad(*builder, get_pointer_to_keymask(dict)); - llvm::Value* capacity = LLVM::CreateLoad(*builder, get_pointer_to_capacity(dict)); - get_builder0() - pos_ptr = builder0.CreateAlloca(llvm::Type::getInt32Ty(context), nullptr); + llvm::Value* key_mask = llvm_utils->CreateLoad(get_pointer_to_keymask(dict)); + llvm::Value* capacity = llvm_utils->CreateLoad(get_pointer_to_capacity(dict)); + pos_ptr = llvm_utils->CreateAlloca(llvm::Type::getInt32Ty(context)); std::pair llvm_key = std::make_pair( ASRUtils::get_type_code(key_asr_type), ASRUtils::get_type_code(value_asr_type) ); llvm::Type* value_type = std::get<2>(typecode2dicttype[llvm_key]).second; - llvm::Value* result = builder0.CreateAlloca(value_type, nullptr); + llvm::Value* result = llvm_utils->CreateAlloca(value_type); llvm::Function *fn = builder->GetInsertBlock()->getParent(); llvm::BasicBlock *thenBB = llvm::BasicBlock::Create(context, "then", fn); llvm::BasicBlock *elseBB = llvm::BasicBlock::Create(context, "else"); llvm::BasicBlock *mergeBB = llvm::BasicBlock::Create(context, "ifcont"); - llvm::Value* key_mask_value = LLVM::CreateLoad(*builder, + llvm::Value* key_mask_value = llvm_utils->CreateLoad( llvm_utils->create_ptr_gep(key_mask, key_hash)); llvm::Value* is_prob_not_neeeded = builder->CreateICmpEQ(key_mask_value, llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), llvm::APInt(8, 1))); @@ -3517,7 +3642,7 @@ namespace LCompilers { llvm_utils->create_if_else(is_key_matching, [=]() { LLVM::CreateStore(*builder, key_hash, pos_ptr); }, [=]() { - LLVM::CreateStore(*builder, LLVM::CreateLoad(*builder, def_value), result); + LLVM::CreateStore(*builder, llvm_utils->CreateLoad(def_value), result); }); } builder->CreateBr(mergeBB); @@ -3527,7 +3652,7 @@ namespace LCompilers { module, key_asr_type, true); } llvm_utils->start_new_block(mergeBB); - llvm::Value* pos = LLVM::CreateLoad(*builder, pos_ptr); + llvm::Value* pos = llvm_utils->CreateLoad(pos_ptr); _check_key_present_or_default(module, key, key_list, key_asr_type, value_list, pos, def_value, result); return result; @@ -3537,10 +3662,10 @@ namespace LCompilers { llvm::Value* dict, llvm::Value* key_hash, llvm::Value* key, llvm::Module& module, ASR::ttype_t* key_asr_type, ASR::ttype_t* value_asr_type) { - llvm::Value* capacity = LLVM::CreateLoad(*builder, get_pointer_to_capacity(dict)); - llvm::Value* key_value_pairs = LLVM::CreateLoad(*builder, get_pointer_to_key_value_pairs(dict)); + llvm::Value* capacity = llvm_utils->CreateLoad(get_pointer_to_capacity(dict)); + llvm::Value* key_value_pairs = llvm_utils->CreateLoad(get_pointer_to_key_value_pairs(dict)); llvm::Value* key_value_pair_linked_list = llvm_utils->create_ptr_gep(key_value_pairs, key_hash); - llvm::Value* key_mask = LLVM::CreateLoad(*builder, get_pointer_to_keymask(dict)); + llvm::Value* key_mask = llvm_utils->CreateLoad(get_pointer_to_keymask(dict)); llvm::Type* kv_struct_type = get_key_value_pair_type(key_asr_type, value_asr_type); this->resolve_collision(capacity, key_hash, key, key_value_pair_linked_list, kv_struct_type, key_mask, module, key_asr_type); @@ -3549,11 +3674,10 @@ namespace LCompilers { ASRUtils::get_type_code(value_asr_type) ); llvm::Type* value_type = std::get<2>(typecode2dicttype[llvm_key]).second; - get_builder0() - tmp_value_ptr = builder0.CreateAlloca(value_type, nullptr); - llvm::Value* kv_struct_i8 = LLVM::CreateLoad(*builder, chain_itr); + tmp_value_ptr = llvm_utils->CreateAlloca(value_type); + llvm::Value* kv_struct_i8 = llvm_utils->CreateLoad(chain_itr); llvm::Value* kv_struct = builder->CreateBitCast(kv_struct_i8, kv_struct_type->getPointerTo()); - llvm::Value* value = LLVM::CreateLoad(*builder, llvm_utils->create_gep(kv_struct, 1)); + llvm::Value* value = llvm_utils->CreateLoad(llvm_utils->create_gep(kv_struct, 1)); LLVM::CreateStore(*builder, value, tmp_value_ptr); return tmp_value_ptr; } @@ -3561,7 +3685,7 @@ namespace LCompilers { llvm::Value* LLVMDictSeparateChaining::resolve_collision_for_read_with_bound_check( llvm::Value* dict, llvm::Value* key_hash, llvm::Value* key, llvm::Module& module, - ASR::ttype_t* key_asr_type, ASR::ttype_t* value_asr_type, bool check_if_exists) { + ASR::ttype_t* key_asr_type, ASR::ttype_t* value_asr_type) { /** * C++ equivalent: * @@ -3573,10 +3697,10 @@ namespace LCompilers { * */ - llvm::Value* capacity = LLVM::CreateLoad(*builder, get_pointer_to_capacity(dict)); - llvm::Value* key_value_pairs = LLVM::CreateLoad(*builder, get_pointer_to_key_value_pairs(dict)); + llvm::Value* capacity = llvm_utils->CreateLoad(get_pointer_to_capacity(dict)); + llvm::Value* key_value_pairs = llvm_utils->CreateLoad(get_pointer_to_key_value_pairs(dict)); llvm::Value* key_value_pair_linked_list = llvm_utils->create_ptr_gep(key_value_pairs, key_hash); - llvm::Value* key_mask = LLVM::CreateLoad(*builder, get_pointer_to_keymask(dict)); + llvm::Value* key_mask = llvm_utils->CreateLoad(get_pointer_to_keymask(dict)); llvm::Type* kv_struct_type = get_key_value_pair_type(key_asr_type, value_asr_type); this->resolve_collision(capacity, key_hash, key, key_value_pair_linked_list, kv_struct_type, key_mask, module, key_asr_type); @@ -3585,25 +3709,20 @@ namespace LCompilers { ASRUtils::get_type_code(value_asr_type) ); llvm::Type* value_type = std::get<2>(typecode2dicttype[llvm_key]).second; - get_builder0() - tmp_value_ptr = builder0.CreateAlloca(value_type, nullptr); - llvm::Value* key_mask_value = LLVM::CreateLoad(*builder, + tmp_value_ptr = llvm_utils->CreateAlloca(value_type); + llvm::Value* key_mask_value = llvm_utils->CreateLoad( llvm_utils->create_ptr_gep(key_mask, key_hash)); llvm::Value* does_kv_exists = builder->CreateICmpEQ(key_mask_value, llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), llvm::APInt(8, 1))); does_kv_exists = builder->CreateAnd(does_kv_exists, - builder->CreateICmpNE(LLVM::CreateLoad(*builder, chain_itr), - llvm::ConstantPointerNull::get(llvm::Type::getInt8PtrTy(context))) + builder->CreateICmpNE(llvm_utils->CreateLoad(chain_itr), + llvm::ConstantPointerNull::get(llvm::Type::getInt8Ty(context)->getPointerTo())) ); - if (check_if_exists) { - return does_kv_exists; - } - llvm_utils->create_if_else(does_kv_exists, [&]() { - llvm::Value* kv_struct_i8 = LLVM::CreateLoad(*builder, chain_itr); + llvm::Value* kv_struct_i8 = llvm_utils->CreateLoad(chain_itr); llvm::Value* kv_struct = builder->CreateBitCast(kv_struct_i8, kv_struct_type->getPointerTo()); - llvm::Value* value = LLVM::CreateLoad(*builder, llvm_utils->create_gep(kv_struct, 1)); + llvm::Value* value = llvm_utils->CreateLoad(llvm_utils->create_gep(kv_struct, 1)); LLVM::CreateStore(*builder, value, tmp_value_ptr); }, [&]() { std::string message = "The dict does not contain the specified key"; @@ -3622,10 +3741,10 @@ namespace LCompilers { llvm::Value* dict, llvm::Value* key_hash, llvm::Value* key, llvm::Module& module, ASR::ttype_t* key_asr_type, ASR::ttype_t* value_asr_type, llvm::Value *def_value) { - llvm::Value* capacity = LLVM::CreateLoad(*builder, get_pointer_to_capacity(dict)); - llvm::Value* key_value_pairs = LLVM::CreateLoad(*builder, get_pointer_to_key_value_pairs(dict)); + llvm::Value* capacity = llvm_utils->CreateLoad(get_pointer_to_capacity(dict)); + llvm::Value* key_value_pairs = llvm_utils->CreateLoad(get_pointer_to_key_value_pairs(dict)); llvm::Value* key_value_pair_linked_list = llvm_utils->create_ptr_gep(key_value_pairs, key_hash); - llvm::Value* key_mask = LLVM::CreateLoad(*builder, get_pointer_to_keymask(dict)); + llvm::Value* key_mask = llvm_utils->CreateLoad(get_pointer_to_keymask(dict)); llvm::Type* kv_struct_type = get_key_value_pair_type(key_asr_type, value_asr_type); this->resolve_collision(capacity, key_hash, key, key_value_pair_linked_list, kv_struct_type, key_mask, module, key_asr_type); @@ -3634,24 +3753,23 @@ namespace LCompilers { ASRUtils::get_type_code(value_asr_type) ); llvm::Type* value_type = std::get<2>(typecode2dicttype[llvm_key]).second; - get_builder0() - tmp_value_ptr = builder0.CreateAlloca(value_type, nullptr); - llvm::Value* key_mask_value = LLVM::CreateLoad(*builder, + tmp_value_ptr = llvm_utils->CreateAlloca(value_type); + llvm::Value* key_mask_value = llvm_utils->CreateLoad( llvm_utils->create_ptr_gep(key_mask, key_hash)); llvm::Value* does_kv_exists = builder->CreateICmpEQ(key_mask_value, llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), llvm::APInt(8, 1))); does_kv_exists = builder->CreateAnd(does_kv_exists, - builder->CreateICmpNE(LLVM::CreateLoad(*builder, chain_itr), - llvm::ConstantPointerNull::get(llvm::Type::getInt8PtrTy(context))) + builder->CreateICmpNE(llvm_utils->CreateLoad(chain_itr), + llvm::ConstantPointerNull::get(llvm::Type::getInt8Ty(context)->getPointerTo())) ); llvm_utils->create_if_else(does_kv_exists, [&]() { - llvm::Value* kv_struct_i8 = LLVM::CreateLoad(*builder, chain_itr); + llvm::Value* kv_struct_i8 = llvm_utils->CreateLoad(chain_itr); llvm::Value* kv_struct = builder->CreateBitCast(kv_struct_i8, kv_struct_type->getPointerTo()); - llvm::Value* value = LLVM::CreateLoad(*builder, llvm_utils->create_gep(kv_struct, 1)); + llvm::Value* value = llvm_utils->CreateLoad(llvm_utils->create_gep(kv_struct, 1)); LLVM::CreateStore(*builder, value, tmp_value_ptr); }, [&]() { - LLVM::CreateStore(*builder, LLVM::CreateLoad(*builder, def_value), tmp_value_ptr); + LLVM::CreateStore(*builder, llvm_utils->CreateLoad(def_value), tmp_value_ptr); }); return tmp_value_ptr; } @@ -3674,16 +3792,15 @@ namespace LCompilers { ); return int_hash; } - case ASR::ttypeType::Character: { + case ASR::ttypeType::String: { // Polynomial rolling hash function for strings llvm::Value* null_char = llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), llvm::APInt(8, '\0')); llvm::Value* p = llvm::ConstantInt::get(llvm::Type::getInt64Ty(context), llvm::APInt(64, 31)); llvm::Value* m = llvm::ConstantInt::get(llvm::Type::getInt64Ty(context), llvm::APInt(64, 100000009)); - get_builder0() - hash_value = builder0.CreateAlloca(llvm::Type::getInt64Ty(context), nullptr, "hash_value"); - hash_iter = builder0.CreateAlloca(llvm::Type::getInt64Ty(context), nullptr, "hash_iter"); - polynomial_powers = builder0.CreateAlloca(llvm::Type::getInt64Ty(context), nullptr, "p_pow"); + hash_value = llvm_utils->CreateAlloca(llvm::Type::getInt64Ty(context), nullptr, "hash_value"); + hash_iter = llvm_utils->CreateAlloca(llvm::Type::getInt64Ty(context), nullptr, "hash_iter"); + polynomial_powers = llvm_utils->CreateAlloca(llvm::Type::getInt64Ty(context), nullptr, "p_pow"); LLVM::CreateStore(*builder, llvm::ConstantInt::get(llvm::Type::getInt64Ty(context), llvm::APInt(64, 0)), hash_value); @@ -3700,8 +3817,8 @@ namespace LCompilers { // head llvm_utils->start_new_block(loophead); { - llvm::Value* i = LLVM::CreateLoad(*builder, hash_iter); - llvm::Value* c = LLVM::CreateLoad(*builder, llvm_utils->create_ptr_gep(key, i)); + llvm::Value* i = llvm_utils->CreateLoad(hash_iter); + llvm::Value* c = llvm_utils->CreateLoad(llvm_utils->create_ptr_gep(key, i)); llvm::Value *cond = builder->CreateICmpNE(c, null_char); builder->CreateCondBr(cond, loopbody, loopend); } @@ -3712,10 +3829,10 @@ namespace LCompilers { // for c in key: // hash_value = (hash_value + (ord(c) + 1) * p_pow) % m // p_pow = (p_pow * p) % m - llvm::Value* i = LLVM::CreateLoad(*builder, hash_iter); - llvm::Value* c = LLVM::CreateLoad(*builder, llvm_utils->create_ptr_gep(key, i)); - llvm::Value* p_pow = LLVM::CreateLoad(*builder, polynomial_powers); - llvm::Value* hash = LLVM::CreateLoad(*builder, hash_value); + llvm::Value* i = llvm_utils->CreateLoad(hash_iter); + llvm::Value* c = llvm_utils->CreateLoad(llvm_utils->create_ptr_gep(key, i)); + llvm::Value* p_pow = llvm_utils->CreateLoad(polynomial_powers); + llvm::Value* hash = llvm_utils->CreateLoad(hash_value); c = builder->CreateZExt(c, llvm::Type::getInt64Ty(context)); c = builder->CreateAdd(c, llvm::ConstantInt::get(llvm::Type::getInt64Ty(context), llvm::APInt(64, 1))); c = builder->CreateMul(c, p_pow); @@ -3734,7 +3851,7 @@ namespace LCompilers { // end llvm_utils->start_new_block(loopend); - llvm::Value* hash = LLVM::CreateLoad(*builder, hash_value); + llvm::Value* hash = llvm_utils->CreateLoad(hash_value); hash = builder->CreateTrunc(hash, llvm::Type::getInt32Ty(context)); return builder->CreateSRem(hash, capacity); } @@ -3772,10 +3889,8 @@ namespace LCompilers { ASR::ttype_t* key_asr_type, ASR::ttype_t* value_asr_type, std::map>& name2memidx) { - get_builder0() - llvm::Value* capacity_ptr = get_pointer_to_capacity(dict); - llvm::Value* old_capacity = LLVM::CreateLoad(*builder, capacity_ptr); + llvm::Value* old_capacity = llvm_utils->CreateLoad(capacity_ptr); llvm::Value* capacity = builder->CreateMul(old_capacity, llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), llvm::APInt(32, 2))); capacity = builder->CreateAdd(capacity, llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), @@ -3791,16 +3906,16 @@ namespace LCompilers { int32_t value_type_size = std::get<1>(typecode2dicttype[dict_type_key]).second; llvm::Value* key_list = get_key_list(dict); - llvm::Value* new_key_list = builder0.CreateAlloca(llvm_utils->list_api->get_list_type(key_llvm_type, - key_type_code, key_type_size), nullptr); + llvm::Value* new_key_list = llvm_utils->CreateAlloca(llvm_utils->list_api->get_list_type(key_llvm_type, + key_type_code, key_type_size)); llvm_utils->list_api->list_init(key_type_code, new_key_list, *module, capacity, capacity); llvm::Value* value_list = get_value_list(dict); - llvm::Value* new_value_list = builder0.CreateAlloca(llvm_utils->list_api->get_list_type(value_llvm_type, - value_type_code, value_type_size), nullptr); + llvm::Value* new_value_list = llvm_utils->CreateAlloca(llvm_utils->list_api->get_list_type(value_llvm_type, + value_type_code, value_type_size)); llvm_utils->list_api->list_init(value_type_code, new_value_list, *module, capacity, capacity); - llvm::Value* key_mask = LLVM::CreateLoad(*builder, get_pointer_to_keymask(dict)); + llvm::Value* key_mask = llvm_utils->CreateLoad(get_pointer_to_keymask(dict)); llvm::DataLayout data_layout(module); size_t mask_size = data_layout.getTypeAllocSize(llvm::Type::getInt8Ty(context)); llvm::Value* llvm_mask_size = llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), @@ -3808,8 +3923,8 @@ namespace LCompilers { llvm::Value* new_key_mask = LLVM::lfortran_calloc(context, *module, *builder, capacity, llvm_mask_size); - llvm::Value* current_capacity = LLVM::CreateLoad(*builder, get_pointer_to_capacity(dict)); - idx_ptr = builder0.CreateAlloca(llvm::Type::getInt32Ty(context), nullptr); + llvm::Value* current_capacity = llvm_utils->CreateLoad(get_pointer_to_capacity(dict)); + idx_ptr = llvm_utils->CreateAlloca(llvm::Type::getInt32Ty(context)); LLVM::CreateStore(*builder, llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), llvm::APInt(32, 0)), idx_ptr); @@ -3820,19 +3935,19 @@ namespace LCompilers { // head llvm_utils->start_new_block(loophead); { - llvm::Value *cond = builder->CreateICmpSGT(old_capacity, LLVM::CreateLoad(*builder, idx_ptr)); + llvm::Value *cond = builder->CreateICmpSGT(old_capacity, llvm_utils->CreateLoad(idx_ptr)); builder->CreateCondBr(cond, loopbody, loopend); } // body llvm_utils->start_new_block(loopbody); { - llvm::Value* idx = LLVM::CreateLoad(*builder, idx_ptr); + llvm::Value* idx = llvm_utils->CreateLoad(idx_ptr); llvm::Function *fn = builder->GetInsertBlock()->getParent(); llvm::BasicBlock *thenBB = llvm::BasicBlock::Create(context, "then", fn); llvm::BasicBlock *elseBB = llvm::BasicBlock::Create(context, "else"); llvm::BasicBlock *mergeBB = llvm::BasicBlock::Create(context, "ifcont"); - llvm::Value* is_key_set = LLVM::CreateLoad(*builder, llvm_utils->create_ptr_gep(key_mask, idx)); + llvm::Value* is_key_set = llvm_utils->CreateLoad(llvm_utils->create_ptr_gep(key_mask, idx)); is_key_set = builder->CreateICmpNE(is_key_set, llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), llvm::APInt(8, 0))); builder->CreateCondBr(is_key_set, thenBB, elseBB); @@ -3845,7 +3960,7 @@ namespace LCompilers { llvm::Value* key_hash = get_key_hash(current_capacity, key, key_asr_type, *module); this->resolve_collision(current_capacity, key_hash, key, new_key_list, new_key_mask, *module, key_asr_type); - llvm::Value* pos = LLVM::CreateLoad(*builder, pos_ptr); + llvm::Value* pos = llvm_utils->CreateLoad(pos_ptr); llvm::Value* key_dest = llvm_utils->list_api->read_item( new_key_list, pos, false, *module, true); llvm_utils->deepcopy(key, key_dest, key_asr_type, module, name2memidx); @@ -3875,9 +3990,11 @@ namespace LCompilers { llvm_utils->start_new_block(loopend); // TODO: Free key_list, value_list and key_mask - dict_free(dict, module, key_asr_type, value_asr_type); - LLVM::CreateStore(*builder, LLVM::CreateLoad(*builder, new_key_list), key_list); - LLVM::CreateStore(*builder, LLVM::CreateLoad(*builder, new_value_list), value_list); + llvm_utils->list_api->free_data(key_list, *module); + llvm_utils->list_api->free_data(value_list, *module); + LLVM::lfortran_free(context, *module, *builder, key_mask); + LLVM::CreateStore(*builder, llvm_utils->CreateLoad(new_key_list), key_list); + LLVM::CreateStore(*builder, llvm_utils->CreateLoad(new_value_list), value_list); LLVM::CreateStore(*builder, new_key_mask, get_pointer_to_keymask(dict)); } @@ -3886,29 +4003,28 @@ namespace LCompilers { ASR::ttype_t* key_asr_type, ASR::ttype_t* value_asr_type, std::map>& name2memidx) { - get_builder0() - old_capacity = builder0.CreateAlloca(llvm::Type::getInt32Ty(context), nullptr); - old_occupancy = builder0.CreateAlloca(llvm::Type::getInt32Ty(context), nullptr); - old_number_of_buckets_filled = builder0.CreateAlloca(llvm::Type::getInt32Ty(context), nullptr); - idx_ptr = builder0.CreateAlloca(llvm::Type::getInt32Ty(context), nullptr); - old_key_value_pairs = builder0.CreateAlloca(llvm::Type::getInt8PtrTy(context), nullptr); - old_key_mask = builder0.CreateAlloca(llvm::Type::getInt8PtrTy(context), nullptr); + old_capacity = llvm_utils->CreateAlloca(llvm::Type::getInt32Ty(context)); + old_occupancy = llvm_utils->CreateAlloca(llvm::Type::getInt32Ty(context)); + old_number_of_buckets_filled = llvm_utils->CreateAlloca(llvm::Type::getInt32Ty(context)); + idx_ptr = llvm_utils->CreateAlloca(llvm::Type::getInt32Ty(context)); + old_key_value_pairs = llvm_utils->CreateAlloca(llvm::Type::getInt8Ty(context)->getPointerTo()); + old_key_mask = llvm_utils->CreateAlloca(llvm::Type::getInt8Ty(context)->getPointerTo()); llvm::Value* capacity_ptr = get_pointer_to_capacity(dict); llvm::Value* occupancy_ptr = get_pointer_to_occupancy(dict); llvm::Value* number_of_buckets_filled_ptr = get_pointer_to_number_of_filled_buckets(dict); - llvm::Value* old_capacity_value = LLVM::CreateLoad(*builder, capacity_ptr); + llvm::Value* old_capacity_value = llvm_utils->CreateLoad(capacity_ptr); LLVM::CreateStore(*builder, old_capacity_value, old_capacity); LLVM::CreateStore(*builder, - LLVM::CreateLoad(*builder, occupancy_ptr), + llvm_utils->CreateLoad(occupancy_ptr), old_occupancy ); LLVM::CreateStore(*builder, - LLVM::CreateLoad(*builder, number_of_buckets_filled_ptr), + llvm_utils->CreateLoad(number_of_buckets_filled_ptr), old_number_of_buckets_filled ); - llvm::Value* old_key_mask_value = LLVM::CreateLoad(*builder, get_pointer_to_keymask(dict)); - llvm::Value* old_key_value_pairs_value = LLVM::CreateLoad(*builder, get_pointer_to_key_value_pairs(dict)); - old_key_value_pairs_value = builder->CreateBitCast(old_key_value_pairs_value, llvm::Type::getInt8PtrTy(context)); + llvm::Value* old_key_mask_value = llvm_utils->CreateLoad(get_pointer_to_keymask(dict)); + llvm::Value* old_key_value_pairs_value = llvm_utils->CreateLoad(get_pointer_to_key_value_pairs(dict)); + old_key_value_pairs_value = builder->CreateBitCast(old_key_value_pairs_value, llvm::Type::getInt8Ty(context)->getPointerTo()); LLVM::CreateStore(*builder, old_key_mask_value, old_key_mask); LLVM::CreateStore(*builder, old_key_value_pairs_value, old_key_value_pairs); @@ -3923,15 +4039,15 @@ namespace LCompilers { llvm::BasicBlock *thenBB_rehash = llvm::BasicBlock::Create(context, "then", fn); llvm::BasicBlock *elseBB_rehash = llvm::BasicBlock::Create(context, "else"); llvm::BasicBlock *mergeBB_rehash = llvm::BasicBlock::Create(context, "ifcont"); - llvm::Value* rehash_flag = LLVM::CreateLoad(*builder, get_pointer_to_rehash_flag(dict)); + llvm::Value* rehash_flag = llvm_utils->CreateLoad(get_pointer_to_rehash_flag(dict)); builder->CreateCondBr(rehash_flag, thenBB_rehash, elseBB_rehash); builder->SetInsertPoint(thenBB_rehash); - old_key_value_pairs_value = LLVM::CreateLoad(*builder, old_key_value_pairs); + old_key_value_pairs_value = llvm_utils->CreateLoad(old_key_value_pairs); old_key_value_pairs_value = builder->CreateBitCast(old_key_value_pairs_value, get_key_value_pair_type(key_asr_type, value_asr_type)->getPointerTo()); - old_key_mask_value = LLVM::CreateLoad(*builder, old_key_mask); - old_capacity_value = LLVM::CreateLoad(*builder, old_capacity); - capacity = LLVM::CreateLoad(*builder, get_pointer_to_capacity(dict)); + old_key_mask_value = llvm_utils->CreateLoad(old_key_mask); + old_capacity_value = llvm_utils->CreateLoad(old_capacity); + capacity = llvm_utils->CreateLoad(get_pointer_to_capacity(dict)); LLVM::CreateStore(*builder, llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), llvm::APInt(32, 0)), idx_ptr); llvm::BasicBlock *loophead = llvm::BasicBlock::Create(context, "loop.head"); llvm::BasicBlock *loopbody = llvm::BasicBlock::Create(context, "loop.body"); @@ -3942,15 +4058,15 @@ namespace LCompilers { { llvm::Value *cond = builder->CreateICmpSGT( old_capacity_value, - LLVM::CreateLoad(*builder, idx_ptr)); + llvm_utils->CreateLoad(idx_ptr)); builder->CreateCondBr(cond, loopbody, loopend); } // body llvm_utils->start_new_block(loopbody); { - llvm::Value* itr = LLVM::CreateLoad(*builder, idx_ptr); - llvm::Value* key_mask_value = LLVM::CreateLoad(*builder, + llvm::Value* itr = llvm_utils->CreateLoad(idx_ptr); + llvm::Value* key_mask_value = llvm_utils->CreateLoad( llvm_utils->create_ptr_gep(old_key_mask_value, itr)); llvm::Value* is_key_set = builder->CreateICmpEQ(key_mask_value, llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), llvm::APInt(8, 1))); @@ -3970,33 +4086,30 @@ namespace LCompilers { // end llvm_utils->start_new_block(loopend); - - free_data(module, key_asr_type, value_asr_type, old_capacity_value, old_key_mask_value, old_key_value_pairs_value); - builder->CreateBr(mergeBB_rehash); llvm_utils->start_new_block(elseBB_rehash); { LLVM::CreateStore(*builder, - LLVM::CreateLoad(*builder, old_capacity), + llvm_utils->CreateLoad(old_capacity), get_pointer_to_capacity(dict) ); LLVM::CreateStore(*builder, - LLVM::CreateLoad(*builder, old_occupancy), + llvm_utils->CreateLoad(old_occupancy), get_pointer_to_occupancy(dict) ); LLVM::CreateStore(*builder, - LLVM::CreateLoad(*builder, old_number_of_buckets_filled), + llvm_utils->CreateLoad(old_number_of_buckets_filled), get_pointer_to_number_of_filled_buckets(dict) ); LLVM::CreateStore(*builder, builder->CreateBitCast( - LLVM::CreateLoad(*builder, old_key_value_pairs), + llvm_utils->CreateLoad(old_key_value_pairs), get_key_value_pair_type(key_asr_type, value_asr_type)->getPointerTo() ), get_pointer_to_key_value_pairs(dict) ); LLVM::CreateStore(*builder, - LLVM::CreateLoad(*builder, old_key_mask), + llvm_utils->CreateLoad(old_key_mask), get_pointer_to_keymask(dict) ); } @@ -4017,8 +4130,8 @@ namespace LCompilers { * */ - llvm::Value* occupancy = LLVM::CreateLoad(*builder, get_pointer_to_occupancy(dict)); - llvm::Value* capacity = LLVM::CreateLoad(*builder, get_pointer_to_capacity(dict)); + llvm::Value* occupancy = llvm_utils->CreateLoad(get_pointer_to_occupancy(dict)); + llvm::Value* capacity = llvm_utils->CreateLoad(get_pointer_to_capacity(dict)); // Threshold hash is chosen from https://en.wikipedia.org/wiki/Hash_table#Load_factor // occupancy / capacity >= 0.6 is same as 5 * occupancy >= 3 * capacity llvm::Value* occupancy_times_5 = builder->CreateMul(occupancy, llvm::ConstantInt::get( @@ -4047,9 +4160,9 @@ namespace LCompilers { * */ - llvm::Value* occupancy = LLVM::CreateLoad(*builder, get_pointer_to_occupancy(dict)); - llvm::Value* buckets_filled = LLVM::CreateLoad(*builder, get_pointer_to_number_of_filled_buckets(dict)); - llvm::Value* rehash_condition = LLVM::CreateLoad(*builder, get_pointer_to_rehash_flag(dict)); + llvm::Value* occupancy = llvm_utils->CreateLoad(get_pointer_to_occupancy(dict)); + llvm::Value* buckets_filled = llvm_utils->CreateLoad(get_pointer_to_number_of_filled_buckets(dict)); + llvm::Value* rehash_condition = llvm_utils->CreateLoad(get_pointer_to_rehash_flag(dict)); llvm::Value* buckets_filled_times_2 = builder->CreateMul(buckets_filled, llvm::ConstantInt::get( llvm::Type::getInt32Ty(context), llvm::APInt(32, 2))); rehash_condition = builder->CreateAnd(rehash_condition, @@ -4065,7 +4178,7 @@ namespace LCompilers { ASR::ttype_t* key_asr_type, ASR::ttype_t* value_asr_type, std::map>& name2memidx) { rehash_all_at_once_if_needed(dict, module, key_asr_type, value_asr_type, name2memidx); - llvm::Value* current_capacity = LLVM::CreateLoad(*builder, get_pointer_to_capacity(dict)); + llvm::Value* current_capacity = llvm_utils->CreateLoad(get_pointer_to_capacity(dict)); llvm::Value* key_hash = get_key_hash(current_capacity, key, key_asr_type, *module); this->resolve_collision_for_write(dict, key_hash, key, value, module, key_asr_type, value_asr_type, name2memidx); @@ -4078,7 +4191,7 @@ namespace LCompilers { llvm::Value* LLVMDict::read_item(llvm::Value* dict, llvm::Value* key, llvm::Module& module, ASR::Dict_t* dict_type, bool enable_bounds_checking, bool get_pointer) { - llvm::Value* current_capacity = LLVM::CreateLoad(*builder, get_pointer_to_capacity(dict)); + llvm::Value* current_capacity = llvm_utils->CreateLoad(get_pointer_to_capacity(dict)); llvm::Value* key_hash = get_key_hash(current_capacity, key, dict_type->m_key_type, module); llvm::Value* value_ptr; if (enable_bounds_checking) { @@ -4091,13 +4204,13 @@ namespace LCompilers { if( get_pointer ) { return value_ptr; } - return LLVM::CreateLoad(*builder, value_ptr); + return llvm_utils->CreateLoad(value_ptr); } llvm::Value* LLVMDict::get_item(llvm::Value* dict, llvm::Value* key, llvm::Module& module, ASR::Dict_t* dict_type, llvm::Value* def_value, bool get_pointer) { - llvm::Value* current_capacity = LLVM::CreateLoad(*builder, get_pointer_to_capacity(dict)); + llvm::Value* current_capacity = llvm_utils->CreateLoad(get_pointer_to_capacity(dict)); llvm::Value* key_hash = get_key_hash(current_capacity, key, dict_type->m_key_type, module); llvm::Value* value_ptr = this->resolve_collision_for_read_with_default(dict, key_hash, key, module, dict_type->m_key_type, dict_type->m_value_type, @@ -4105,12 +4218,12 @@ namespace LCompilers { if( get_pointer ) { return value_ptr; } - return LLVM::CreateLoad(*builder, value_ptr); + return llvm_utils->CreateLoad(value_ptr); } llvm::Value* LLVMDictSeparateChaining::read_item(llvm::Value* dict, llvm::Value* key, llvm::Module& module, ASR::Dict_t* dict_type, bool enable_bounds_checking, bool get_pointer) { - llvm::Value* current_capacity = LLVM::CreateLoad(*builder, get_pointer_to_capacity(dict)); + llvm::Value* current_capacity = llvm_utils->CreateLoad(get_pointer_to_capacity(dict)); llvm::Value* key_hash = get_key_hash(current_capacity, key, dict_type->m_key_type, module); llvm::Value* value_ptr; if (enable_bounds_checking) { @@ -4129,12 +4242,12 @@ namespace LCompilers { if( get_pointer ) { return value_ptr; } - return LLVM::CreateLoad(*builder, value_ptr); + return llvm_utils->CreateLoad(value_ptr); } llvm::Value* LLVMDictSeparateChaining::get_item(llvm::Value* dict, llvm::Value* key, llvm::Module& module, ASR::Dict_t* dict_type, llvm::Value* def_value, bool get_pointer) { - llvm::Value* current_capacity = LLVM::CreateLoad(*builder, get_pointer_to_capacity(dict)); + llvm::Value* current_capacity = llvm_utils->CreateLoad(get_pointer_to_capacity(dict)); llvm::Value* key_hash = get_key_hash(current_capacity, key, dict_type->m_key_type, module); llvm::Value* value_ptr = this->resolve_collision_for_read_with_default(dict, key_hash, key, module, dict_type->m_key_type, dict_type->m_value_type, @@ -4148,7 +4261,7 @@ namespace LCompilers { if( get_pointer ) { return value_ptr; } - return LLVM::CreateLoad(*builder, value_ptr); + return llvm_utils->CreateLoad(value_ptr); } llvm::Value* LLVMDict::pop_item(llvm::Value* dict, llvm::Value* key, @@ -4162,18 +4275,18 @@ namespace LCompilers { * occupancy -= 1; */ - llvm::Value* current_capacity = LLVM::CreateLoad(*builder, get_pointer_to_capacity(dict)); + llvm::Value* current_capacity = llvm_utils->CreateLoad(get_pointer_to_capacity(dict)); llvm::Value* key_hash = get_key_hash(current_capacity, key, dict_type->m_key_type, module); llvm::Value* value_ptr = this->resolve_collision_for_read_with_bound_check(dict, key_hash, key, module, dict_type->m_key_type, dict_type->m_value_type); - llvm::Value* pos = LLVM::CreateLoad(*builder, pos_ptr); - llvm::Value* key_mask = LLVM::CreateLoad(*builder, get_pointer_to_keymask(dict)); + llvm::Value* pos = llvm_utils->CreateLoad(pos_ptr); + llvm::Value* key_mask = llvm_utils->CreateLoad(get_pointer_to_keymask(dict)); llvm::Value* key_mask_i = llvm_utils->create_ptr_gep(key_mask, pos); llvm::Value* tombstone_marker = llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), llvm::APInt(8, 3)); LLVM::CreateStore(*builder, tombstone_marker, key_mask_i); llvm::Value* occupancy_ptr = get_pointer_to_occupancy(dict); - llvm::Value* occupancy = LLVM::CreateLoad(*builder, occupancy_ptr); + llvm::Value* occupancy = llvm_utils->CreateLoad(occupancy_ptr); occupancy = builder->CreateSub(occupancy, llvm::ConstantInt::get( llvm::Type::getInt32Ty(context), llvm::APInt(32, 1))); LLVM::CreateStore(*builder, occupancy, occupancy_ptr); @@ -4183,13 +4296,12 @@ namespace LCompilers { std::string value_type_code = ASRUtils::get_type_code(dict_type->m_value_type); llvm::Type* llvm_value_type = std::get<2>(typecode2dicttype[std::make_pair( key_type_code, value_type_code)]).second; - get_builder0() - llvm::Value* return_ptr = builder0.CreateAlloca(llvm_value_type, nullptr); - LLVM::CreateStore(*builder, LLVM::CreateLoad(*builder, value_ptr), return_ptr); + llvm::Value* return_ptr = llvm_utils->CreateAlloca(llvm_value_type); + LLVM::CreateStore(*builder, llvm_utils->CreateLoad(value_ptr), return_ptr); return return_ptr; } - return LLVM::CreateLoad(*builder, value_ptr); + return llvm_utils->CreateLoad(value_ptr); } llvm::Value* LLVMDictSeparateChaining::pop_item( @@ -4222,7 +4334,7 @@ namespace LCompilers { * */ - llvm::Value* current_capacity = LLVM::CreateLoad(*builder, get_pointer_to_capacity(dict)); + llvm::Value* current_capacity = llvm_utils->CreateLoad(get_pointer_to_capacity(dict)); llvm::Value* key_hash = get_key_hash(current_capacity, key, dict_type->m_key_type, module); llvm::Value* value_ptr = this->resolve_collision_for_read_with_bound_check(dict, key_hash, key, module, dict_type->m_key_type, dict_type->m_value_type); @@ -4232,40 +4344,40 @@ namespace LCompilers { ); llvm::Type* value_type = std::get<2>(typecode2dicttype[llvm_key]).second; value_ptr = builder->CreateBitCast(value_ptr, value_type->getPointerTo()); - llvm::Value* prev = LLVM::CreateLoad(*builder, chain_itr_prev); - llvm::Value* found = LLVM::CreateLoad(*builder, chain_itr); + llvm::Value* prev = llvm_utils->CreateLoad(chain_itr_prev); + llvm::Value* found = llvm_utils->CreateLoad(chain_itr); llvm::Type* kv_struct_type = get_key_value_pair_type(dict_type->m_key_type, dict_type->m_value_type); found = builder->CreateBitCast(found, kv_struct_type->getPointerTo()); - llvm::Value* found_next = LLVM::CreateLoad(*builder, llvm_utils->create_gep(found, 2)); + llvm::Value* found_next = llvm_utils->CreateLoad(llvm_utils->create_gep(found, 2)); llvm_utils->create_if_else(builder->CreateICmpNE(prev, - llvm::ConstantPointerNull::get(llvm::Type::getInt8PtrTy(context))), [&]() { + llvm::ConstantPointerNull::get(llvm::Type::getInt8Ty(context)->getPointerTo())), [&]() { prev = builder->CreateBitCast(prev, kv_struct_type->getPointerTo()); LLVM::CreateStore(*builder, found_next, llvm_utils->create_gep(prev, 2)); }, [&]() { llvm_utils->create_if_else(builder->CreateICmpEQ(found_next, - llvm::ConstantPointerNull::get(llvm::Type::getInt8PtrTy(context))), [&]() { - llvm::Value* key_mask = LLVM::CreateLoad(*builder, get_pointer_to_keymask(dict)); + llvm::ConstantPointerNull::get(llvm::Type::getInt8Ty(context)->getPointerTo())), [&]() { + llvm::Value* key_mask = llvm_utils->CreateLoad(get_pointer_to_keymask(dict)); LLVM::CreateStore( *builder, llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), llvm::APInt(8, 0)), llvm_utils->create_ptr_gep(key_mask, key_hash) ); llvm::Value* num_buckets_filled_ptr = get_pointer_to_number_of_filled_buckets(dict); - llvm::Value* num_buckets_filled = LLVM::CreateLoad(*builder, num_buckets_filled_ptr); + llvm::Value* num_buckets_filled = llvm_utils->CreateLoad(num_buckets_filled_ptr); num_buckets_filled = builder->CreateSub(num_buckets_filled, llvm::ConstantInt::get( llvm::Type::getInt32Ty(context), llvm::APInt(32, 1))); LLVM::CreateStore(*builder, num_buckets_filled, num_buckets_filled_ptr); }, [&]() { found_next = builder->CreateBitCast(found_next, kv_struct_type->getPointerTo()); - llvm::Value* key_value_pairs = LLVM::CreateLoad(*builder, get_pointer_to_key_value_pairs(dict)); - LLVM::CreateStore(*builder, LLVM::CreateLoad(*builder, found_next), + llvm::Value* key_value_pairs = llvm_utils->CreateLoad(get_pointer_to_key_value_pairs(dict)); + LLVM::CreateStore(*builder, llvm_utils->CreateLoad(found_next), llvm_utils->create_ptr_gep(key_value_pairs, key_hash)); }); }); llvm::Value* occupancy_ptr = get_pointer_to_occupancy(dict); - llvm::Value* occupancy = LLVM::CreateLoad(*builder, occupancy_ptr); + llvm::Value* occupancy = llvm_utils->CreateLoad(occupancy_ptr); occupancy = builder->CreateSub(occupancy, llvm::ConstantInt::get( llvm::Type::getInt32Ty(context), llvm::APInt(32, 1))); LLVM::CreateStore(*builder, occupancy, occupancy_ptr); @@ -4275,13 +4387,12 @@ namespace LCompilers { std::string value_type_code = ASRUtils::get_type_code(dict_type->m_value_type); llvm::Type* llvm_value_type = std::get<2>(typecode2dicttype[std::make_pair( key_type_code, value_type_code)]).second; - get_builder0() - llvm::Value* return_ptr = builder0.CreateAlloca(llvm_value_type, nullptr); - LLVM::CreateStore(*builder, LLVM::CreateLoad(*builder, value_ptr), return_ptr); + llvm::Value* return_ptr = llvm_utils->CreateAlloca(llvm_value_type); + LLVM::CreateStore(*builder, llvm_utils->CreateLoad(value_ptr), return_ptr); return return_ptr; } - return LLVM::CreateLoad(*builder, value_ptr); + return llvm_utils->CreateLoad(value_ptr); } void LLVMDict::get_elements_list(llvm::Value* dict, @@ -4313,12 +4424,11 @@ namespace LCompilers { * */ - llvm::Value* capacity = LLVM::CreateLoad(*builder, get_pointer_to_capacity(dict)); - llvm::Value* key_mask = LLVM::CreateLoad(*builder, get_pointer_to_keymask(dict)); + llvm::Value* capacity = llvm_utils->CreateLoad(get_pointer_to_capacity(dict)); + llvm::Value* key_mask = llvm_utils->CreateLoad(get_pointer_to_keymask(dict)); llvm::Value* el_list = key_or_value == 0 ? get_key_list(dict) : get_value_list(dict); ASR::ttype_t* el_asr_type = key_or_value == 0 ? key_asr_type : value_asr_type; - get_builder0(); - idx_ptr = builder0.CreateAlloca(llvm::Type::getInt32Ty(context), nullptr); + idx_ptr = llvm_utils->CreateAlloca(llvm::Type::getInt32Ty(context)); LLVM::CreateStore(*builder, llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), llvm::APInt(32, 0)), idx_ptr); @@ -4329,15 +4439,15 @@ namespace LCompilers { // head llvm_utils->start_new_block(loophead); { - llvm::Value *cond = builder->CreateICmpSGT(capacity, LLVM::CreateLoad(*builder, idx_ptr)); + llvm::Value *cond = builder->CreateICmpSGT(capacity, llvm_utils->CreateLoad(idx_ptr)); builder->CreateCondBr(cond, loopbody, loopend); } // body llvm_utils->start_new_block(loopbody); { - llvm::Value* idx = LLVM::CreateLoad(*builder, idx_ptr); - llvm::Value* key_mask_value = LLVM::CreateLoad(*builder, + llvm::Value* idx = llvm_utils->CreateLoad(idx_ptr); + llvm::Value* key_mask_value = llvm_utils->CreateLoad( llvm_utils->create_ptr_gep(key_mask, idx)); llvm::Value* is_key_skip = builder->CreateICmpEQ(key_mask_value, llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), llvm::APInt(8, 3))); @@ -4370,15 +4480,14 @@ namespace LCompilers { ASR::ttype_t* value_asr_type, llvm::Module& module, std::map>& name2memidx, bool key_or_value) { - get_builder0() - idx_ptr = builder0.CreateAlloca(llvm::Type::getInt32Ty(context), nullptr); - chain_itr = builder0.CreateAlloca(llvm::Type::getInt8PtrTy(context), nullptr); + idx_ptr = llvm_utils->CreateAlloca(llvm::Type::getInt32Ty(context)); + chain_itr = llvm_utils->CreateAlloca(llvm::Type::getInt8Ty(context)->getPointerTo()); LLVM::CreateStore(*builder, llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), llvm::APInt(32, 0)), idx_ptr); - llvm::Value* capacity = LLVM::CreateLoad(*builder, get_pointer_to_capacity(dict)); - llvm::Value* key_mask = LLVM::CreateLoad(*builder, get_pointer_to_keymask(dict)); - llvm::Value* key_value_pairs = LLVM::CreateLoad(*builder, get_pointer_to_key_value_pairs(dict)); + llvm::Value* capacity = llvm_utils->CreateLoad(get_pointer_to_capacity(dict)); + llvm::Value* key_mask = llvm_utils->CreateLoad(get_pointer_to_keymask(dict)); + llvm::Value* key_value_pairs = llvm_utils->CreateLoad(get_pointer_to_key_value_pairs(dict)); llvm::Type* kv_pair_type = get_key_value_pair_type(key_asr_type, value_asr_type); ASR::ttype_t* el_asr_type = key_or_value == 0 ? key_asr_type : value_asr_type; llvm::BasicBlock *loophead = llvm::BasicBlock::Create(context, "loop.head"); @@ -4390,22 +4499,22 @@ namespace LCompilers { { llvm::Value *cond = builder->CreateICmpSGT( capacity, - LLVM::CreateLoad(*builder, idx_ptr)); + llvm_utils->CreateLoad(idx_ptr)); builder->CreateCondBr(cond, loopbody, loopend); } // body llvm_utils->start_new_block(loopbody); { - llvm::Value* idx = LLVM::CreateLoad(*builder, idx_ptr); - llvm::Value* key_mask_value = LLVM::CreateLoad(*builder, + llvm::Value* idx = llvm_utils->CreateLoad(idx_ptr); + llvm::Value* key_mask_value = llvm_utils->CreateLoad( llvm_utils->create_ptr_gep(key_mask, idx)); llvm::Value* is_key_set = builder->CreateICmpEQ(key_mask_value, llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), llvm::APInt(8, 1))); llvm_utils->create_if_else(is_key_set, [&]() { llvm::Value* dict_i = llvm_utils->create_ptr_gep(key_value_pairs, idx); - llvm::Value* kv_ll_i8 = builder->CreateBitCast(dict_i, llvm::Type::getInt8PtrTy(context)); + llvm::Value* kv_ll_i8 = builder->CreateBitCast(dict_i, llvm::Type::getInt8Ty(context)->getPointerTo()); LLVM::CreateStore(*builder, kv_ll_i8, chain_itr); llvm::BasicBlock *loop2head = llvm::BasicBlock::Create(context, "loop2.head"); @@ -4416,8 +4525,8 @@ namespace LCompilers { llvm_utils->start_new_block(loop2head); { llvm::Value *cond = builder->CreateICmpNE( - LLVM::CreateLoad(*builder, chain_itr), - llvm::ConstantPointerNull::get(llvm::Type::getInt8PtrTy(context)) + llvm_utils->CreateLoad(chain_itr), + llvm::ConstantPointerNull::get(llvm::Type::getInt8Ty(context)->getPointerTo()) ); builder->CreateCondBr(cond, loop2body, loop2end); } @@ -4425,15 +4534,15 @@ namespace LCompilers { // body llvm_utils->start_new_block(loop2body); { - llvm::Value* kv_struct_i8 = LLVM::CreateLoad(*builder, chain_itr); + llvm::Value* kv_struct_i8 = llvm_utils->CreateLoad(chain_itr); llvm::Value* kv_struct = builder->CreateBitCast(kv_struct_i8, kv_pair_type->getPointerTo()); llvm::Value* kv_el = llvm_utils->create_gep(kv_struct, key_or_value); if( !LLVM::is_llvm_struct(el_asr_type) ) { - kv_el = LLVM::CreateLoad(*builder, kv_el); + kv_el = llvm_utils->CreateLoad(kv_el); } llvm_utils->list_api->append(elements_list, kv_el, el_asr_type, &module, name2memidx); - llvm::Value* next_kv_struct = LLVM::CreateLoad(*builder, llvm_utils->create_gep(kv_struct, 2)); + llvm::Value* next_kv_struct = llvm_utils->CreateLoad(llvm_utils->create_gep(kv_struct, 2)); LLVM::CreateStore(*builder, next_kv_struct, chain_itr); } @@ -4454,190 +4563,30 @@ namespace LCompilers { llvm_utils->start_new_block(loopend); } - void LLVMDictSeparateChaining::free_data(llvm::Module *module, ASR::ttype_t* key_asr_type, - ASR::ttype_t* value_asr_type, llvm::Value *capacity, - llvm::Value *key_mask, llvm::Value *key_value_pairs) { - /* C++ equivalent: - * idx = 0; - * while (capacity > idx) { - * key_mask_value = key_mask[idx]; - * is_key_set = key_mask_value == 1; - * if (is_key_set) { - * dict_i = key_value_pairs[idx]; - * chain_itr = (i8*)dict_i; - * - * chain_itr = chain_itr[2]; - * while (chain_itr != nullptr) { - * kv_struct = (kv_pair_type*)chain_itr; - * free_data(kv_struct[0]); - * free_data(kv_struct[1]); - * next_kv_struct = kv_struct[2]; - * chain_itr = next_kv_struct; - * free(kv_struct); - * } - * } - * idx++; - * } - */ - llvm::Type* kv_pair_type = - get_key_value_pair_type(key_asr_type, value_asr_type); - get_builder0() - llvm::AllocaInst *chain_itr = builder0.CreateAlloca( - llvm::Type::getInt8PtrTy(context), nullptr); - llvm::AllocaInst *idx_ptr = builder0.CreateAlloca( - llvm::Type::getInt32Ty(context), nullptr); - LLVM::CreateStore(*builder, llvm::ConstantInt::get( - llvm::Type::getInt32Ty(context), llvm::APInt(32, 0)), idx_ptr); - llvm::BasicBlock *loophead = llvm::BasicBlock::Create(context, "loop.head"); - llvm::BasicBlock *loopbody = llvm::BasicBlock::Create(context, "loop.body"); - llvm::BasicBlock *loopend = llvm::BasicBlock::Create(context, "loop.end"); - - // head - llvm_utils->start_new_block(loophead); - { - llvm::Value *cond = builder->CreateICmpSGT( - capacity, - LLVM::CreateLoad(*builder, idx_ptr)); - builder->CreateCondBr(cond, loopbody, loopend); - } - - // body - llvm_utils->start_new_block(loopbody); - { - llvm::Value* idx = LLVM::CreateLoad(*builder, idx_ptr); - llvm::Value* key_mask_value = LLVM::CreateLoad(*builder, - llvm_utils->create_ptr_gep(key_mask, idx)); - - llvm::Value* is_key_set = builder->CreateICmpEQ(key_mask_value, - llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), llvm::APInt(8, 1))); - - llvm_utils->create_if_else(is_key_set, [&]() { - llvm::Value* dict_i = llvm_utils->create_ptr_gep(key_value_pairs, idx); - llvm::Value* kv_ll_i8 = builder->CreateBitCast(dict_i, llvm::Type::getInt8PtrTy(context)); - LLVM::CreateStore(*builder, kv_ll_i8, chain_itr); - - // In the linked list, we should not free the head node, - // since that will be freed through the final list free - // Hence we proceed to the next node and start freeing from there - llvm::Value* kv_struct_i8 = LLVM::CreateLoad(*builder, chain_itr); - llvm::Value* kv_struct = builder->CreateBitCast(kv_struct_i8, kv_pair_type->getPointerTo()); - llvm::Value* next_kv_struct = LLVM::CreateLoad(*builder, llvm_utils->create_gep(kv_struct, 2)); - LLVM::CreateStore(*builder, next_kv_struct, chain_itr); - - llvm::BasicBlock *loop2head = llvm::BasicBlock::Create(context, "loop2.head"); - llvm::BasicBlock *loop2body = llvm::BasicBlock::Create(context, "loop2.body"); - llvm::BasicBlock *loop2end = llvm::BasicBlock::Create(context, "loop2.end"); - - // head - llvm_utils->start_new_block(loop2head); - { - llvm::Value *cond = builder->CreateICmpNE( - LLVM::CreateLoad(*builder, chain_itr), - llvm::ConstantPointerNull::get(llvm::Type::getInt8PtrTy(context)) - ); - builder->CreateCondBr(cond, loop2body, loop2end); - } - - // body - llvm_utils->start_new_block(loop2body); - { - llvm::Value* kv_struct_i8 = LLVM::CreateLoad(*builder, chain_itr); - llvm::Value* kv_struct = builder->CreateBitCast(kv_struct_i8, kv_pair_type->getPointerTo()); - llvm::Value* key_ptr = llvm_utils->create_gep(kv_struct, 0); - llvm::Value* value_ptr = llvm_utils->create_gep(kv_struct, 1); - if( LLVM::is_llvm_struct(key_asr_type) ) { - llvm_utils->free_data(key_ptr, key_asr_type, module); - } - if( LLVM::is_llvm_struct(value_asr_type) ) { - llvm_utils->free_data(value_ptr, value_asr_type, module); - } - llvm::Value* next_kv_struct = LLVM::CreateLoad(*builder, llvm_utils->create_gep(kv_struct, 2)); - LLVM::CreateStore(*builder, next_kv_struct, chain_itr); - LLVM::lfortran_free(context, *module, *builder, kv_struct_i8); - } - - builder->CreateBr(loop2head); - - // end - llvm_utils->start_new_block(loop2end); - }, [=]() { - }); - llvm::Value* tmp = builder->CreateAdd(idx, - llvm::ConstantInt::get(context, llvm::APInt(32, 1))); - LLVM::CreateStore(*builder, tmp, idx_ptr); - } - builder->CreateBr(loophead); - - // end - llvm_utils->start_new_block(loopend); - - LLVM::lfortran_free(context, *module, *builder, key_mask); - LLVM::lfortran_free(context, *module, *builder, key_value_pairs); - } - - void LLVMDict::dict_clear(llvm::Value *dict, llvm::Module *module, - ASR::ttype_t *key_asr_type, ASR::ttype_t* value_asr_type) { - dict_free(dict, module, key_asr_type, value_asr_type); - - std::string key_type_code = ASRUtils::get_type_code(key_asr_type); - std::string value_type_code = ASRUtils::get_type_code(value_asr_type); - dict_init(key_type_code, value_type_code, dict, module, 0); - } - - void LLVMDictSeparateChaining::dict_clear(llvm::Value *dict, llvm::Module *module, - ASR::ttype_t *key_asr_type, ASR::ttype_t* value_asr_type) { - dict_free(dict, module, key_asr_type, value_asr_type); - dict_init(ASRUtils::get_type_code(key_asr_type), - ASRUtils::get_type_code(value_asr_type), dict, module, 0); - } - - void LLVMDict::dict_free(llvm::Value *dict, llvm::Module *module, - ASR::ttype_t *key_asr_type, ASR::ttype_t* value_asr_type) { - llvm::Value* key_list = get_key_list(dict); - llvm::Value* value_list = get_value_list(dict); - llvm::Value* key_mask = LLVM::CreateLoad(*builder, get_pointer_to_keymask(dict)); - llvm_utils->list_api->free_data(key_list, key_asr_type, *module); - llvm_utils->list_api->free_data(value_list, value_asr_type, *module); - LLVM::lfortran_free(context, *module, *builder, key_mask); - } - - void LLVMDictSeparateChaining::dict_free(llvm::Value *dict, llvm::Module *module, - ASR::ttype_t *key_asr_type, ASR::ttype_t* value_asr_type) { - llvm::Value *key_value_pairs = LLVM::CreateLoad(*builder, - get_pointer_to_key_value_pairs(dict)); - llvm::Value *capacity = LLVM::CreateLoad(*builder, - get_pointer_to_capacity(dict)); - llvm::Value *key_mask = LLVM::CreateLoad(*builder, - get_pointer_to_keymask(dict)); - free_data(module, key_asr_type, value_asr_type, capacity, key_mask, key_value_pairs); - } - - - llvm::Value* LLVMList::read_item(llvm::Value* list, llvm::Value* pos, bool enable_bounds_checking, llvm::Module& module, bool get_pointer) { if( enable_bounds_checking ) { check_index_within_bounds(list, pos, module); } - llvm::Value* list_data = LLVM::CreateLoad(*builder, get_pointer_to_list_data(list)); + llvm::Value* list_data = llvm_utils->CreateLoad(get_pointer_to_list_data(list)); llvm::Value* element_ptr = llvm_utils->create_ptr_gep(list_data, pos); if( get_pointer ) { return element_ptr; } - return LLVM::CreateLoad(*builder, element_ptr); + return llvm_utils->CreateLoad(element_ptr); } llvm::Value* LLVMList::len(llvm::Value* list) { - return LLVM::CreateLoad(*builder, get_pointer_to_current_end_point(list)); + return llvm_utils->CreateLoad(get_pointer_to_current_end_point(list)); } llvm::Value* LLVMDict::len(llvm::Value* dict) { - return LLVM::CreateLoad(*builder, get_pointer_to_occupancy(dict)); + return llvm_utils->CreateLoad(get_pointer_to_occupancy(dict)); } llvm::Value* LLVMDictSeparateChaining::len(llvm::Value* dict) { - return LLVM::CreateLoad(*builder, get_pointer_to_occupancy(dict)) ; + return llvm_utils->CreateLoad(get_pointer_to_occupancy(dict)) ; } bool LLVMDictInterface::is_dict_present() { @@ -4678,7 +4627,7 @@ namespace LCompilers { llvm::APInt(32, type_size)), new_capacity); llvm::Value* copy_data_ptr = get_pointer_to_list_data(list); - llvm::Value* copy_data = LLVM::CreateLoad(*builder, copy_data_ptr); + llvm::Value* copy_data = llvm_utils->CreateLoad(copy_data_ptr); copy_data = LLVM::lfortran_realloc(context, *module, *builder, copy_data, arg_size); copy_data = builder->CreateBitCast(copy_data, el_type->getPointerTo()); @@ -4691,7 +4640,7 @@ namespace LCompilers { void LLVMList::shift_end_point_by_one(llvm::Value* list) { llvm::Value* end_point_ptr = get_pointer_to_current_end_point(list); - llvm::Value* end_point = LLVM::CreateLoad(*builder, end_point_ptr); + llvm::Value* end_point = llvm_utils->CreateLoad(end_point_ptr); end_point = builder->CreateAdd(end_point, llvm::ConstantInt::get(context, llvm::APInt(32, 1))); builder->CreateStore(end_point, end_point_ptr); } @@ -4699,8 +4648,8 @@ namespace LCompilers { void LLVMList::append(llvm::Value* list, llvm::Value* item, ASR::ttype_t* asr_type, llvm::Module* module, std::map>& name2memidx) { - llvm::Value* current_end_point = LLVM::CreateLoad(*builder, get_pointer_to_current_end_point(list)); - llvm::Value* current_capacity = LLVM::CreateLoad(*builder, get_pointer_to_current_capacity(list)); + llvm::Value* current_end_point = llvm_utils->CreateLoad(get_pointer_to_current_end_point(list)); + llvm::Value* current_capacity = llvm_utils->CreateLoad(get_pointer_to_current_capacity(list)); std::string type_code = ASRUtils::get_type_code(asr_type); int type_size = std::get<1>(typecode2listtype[type_code]); llvm::Type* el_type = std::get<2>(typecode2listtype[type_code]); @@ -4715,9 +4664,9 @@ namespace LCompilers { llvm::Module* module, std::map>& name2memidx) { std::string type_code = ASRUtils::get_type_code(asr_type); - llvm::Value* current_end_point = LLVM::CreateLoad(*builder, + llvm::Value* current_end_point = llvm_utils->CreateLoad( get_pointer_to_current_end_point(list)); - llvm::Value* current_capacity = LLVM::CreateLoad(*builder, + llvm::Value* current_capacity = llvm_utils->CreateLoad( get_pointer_to_current_capacity(list)); int type_size = std::get<1>(typecode2listtype[type_code]); llvm::Type* el_type = std::get<2>(typecode2listtype[type_code]); @@ -4744,16 +4693,15 @@ namespace LCompilers { // TODO: Should be created outside the user loop and not here. // LLVMList should treat them as data members and create them // only if they are NULL - get_builder0() - llvm::AllocaInst *tmp_ptr = builder0.CreateAlloca(el_type, nullptr); + llvm::AllocaInst *tmp_ptr = llvm_utils->CreateAlloca(el_type); LLVM::CreateStore(*builder, read_item(list, pos, false, *module, false), tmp_ptr); llvm::Value* tmp = nullptr; // TODO: Should be created outside the user loop and not here. // LLVMList should treat them as data members and create them // only if they are NULL - llvm::AllocaInst *pos_ptr = builder0.CreateAlloca( - llvm::Type::getInt32Ty(context), nullptr); + llvm::AllocaInst *pos_ptr = llvm_utils->CreateAlloca( + llvm::Type::getInt32Ty(context)); LLVM::CreateStore(*builder, pos, pos_ptr); llvm::BasicBlock *loophead = llvm::BasicBlock::Create(context, "loop.head"); @@ -4765,7 +4713,7 @@ namespace LCompilers { { llvm::Value *cond = builder->CreateICmpSGT( current_end_point, - LLVM::CreateLoad(*builder, pos_ptr)); + llvm_utils->CreateLoad(pos_ptr)); builder->CreateCondBr(cond, loopbody, loopend); } @@ -4773,14 +4721,14 @@ namespace LCompilers { llvm_utils->start_new_block(loopbody); { llvm::Value* next_index = builder->CreateAdd( - LLVM::CreateLoad(*builder, pos_ptr), + llvm_utils->CreateLoad(pos_ptr), llvm::ConstantInt::get(context, llvm::APInt(32, 1))); tmp = read_item(list, next_index, false, *module, false); - write_item(list, next_index, LLVM::CreateLoad(*builder, tmp_ptr), false, *module); + write_item(list, next_index, llvm_utils->CreateLoad(tmp_ptr), false, *module); LLVM::CreateStore(*builder, tmp, tmp_ptr); tmp = builder->CreateAdd( - LLVM::CreateLoad(*builder, pos_ptr), + llvm_utils->CreateLoad(pos_ptr), llvm::ConstantInt::get(context, llvm::APInt(32, 1))); LLVM::CreateStore(*builder, tmp, pos_ptr); } @@ -4803,7 +4751,7 @@ namespace LCompilers { * } * */ - llvm::Value* capacity = LLVM::CreateLoad(*builder, get_pointer_to_current_capacity(list)); + llvm::Value* capacity = llvm_utils->CreateLoad(get_pointer_to_current_capacity(list)); std::string type_code = ASRUtils::get_type_code(asr_type); int type_size = std::get<1>(typecode2listtype[type_code]); llvm::Type* el_type = std::get<2>(typecode2listtype[type_code]); @@ -4811,7 +4759,7 @@ namespace LCompilers { llvm::Value* arg_size = builder->CreateMul(llvm::ConstantInt::get(context, llvm::APInt(32, type_size)), n); llvm::Value* copy_data_ptr = get_pointer_to_list_data(list); - llvm::Value* copy_data = LLVM::CreateLoad(*builder, copy_data_ptr); + llvm::Value* copy_data = llvm_utils->CreateLoad(copy_data_ptr); copy_data = LLVM::lfortran_realloc(context, *module, *builder, copy_data, arg_size); copy_data = builder->CreateBitCast(copy_data, el_type->getPointerTo()); @@ -4838,15 +4786,14 @@ namespace LCompilers { * } */ - llvm::Value* end_point = LLVM::CreateLoad(*builder, + llvm::Value* end_point = llvm_utils->CreateLoad( get_pointer_to_current_end_point(list)); llvm::Type* pos_type = llvm::Type::getInt32Ty(context); - get_builder0() - llvm::AllocaInst *i = builder0.CreateAlloca(pos_type, nullptr); + llvm::AllocaInst *i = llvm_utils->CreateAlloca(pos_type); LLVM::CreateStore(*builder, llvm::ConstantInt::get( context, llvm::APInt(32, 0)), i); // i = 0 - llvm::AllocaInst *j = builder0.CreateAlloca(pos_type, nullptr); + llvm::AllocaInst *j = llvm_utils->CreateAlloca(pos_type); llvm::Value* tmp = nullptr; tmp = builder->CreateSub(end_point, llvm::ConstantInt::get(context, llvm::APInt(32, 1))); LLVM::CreateStore(*builder, tmp, j); // j = end_point - 1 @@ -4858,28 +4805,28 @@ namespace LCompilers { // head llvm_utils->start_new_block(loophead); { - llvm::Value *cond = builder->CreateICmpSGT(LLVM::CreateLoad(*builder, j), LLVM::CreateLoad(*builder, i)); + llvm::Value *cond = builder->CreateICmpSGT(llvm_utils->CreateLoad(j), llvm_utils->CreateLoad(i)); builder->CreateCondBr(cond, loopbody, loopend); } // body llvm_utils->start_new_block(loopbody); { - tmp = read_item(list, LLVM::CreateLoad(*builder, i), + tmp = read_item(list, llvm_utils->CreateLoad(i), false, module, false); // tmp = list[i] - write_item(list, LLVM::CreateLoad(*builder, i), - read_item(list, LLVM::CreateLoad(*builder, j), + write_item(list, llvm_utils->CreateLoad(i), + read_item(list, llvm_utils->CreateLoad(j), false, module, false), false, module); // list[i] = list[j] - write_item(list, LLVM::CreateLoad(*builder, j), + write_item(list, llvm_utils->CreateLoad(j), tmp, false, module); // list[j] = tmp tmp = builder->CreateAdd( - LLVM::CreateLoad(*builder, i), + llvm_utils->CreateLoad(i), llvm::ConstantInt::get(context, llvm::APInt(32, 1))); LLVM::CreateStore(*builder, tmp, i); tmp = builder->CreateSub( - LLVM::CreateLoad(*builder, j), + llvm_utils->CreateLoad(j), llvm::ConstantInt::get(context, llvm::APInt(32, 1))); LLVM::CreateStore(*builder, tmp, j); } @@ -4897,8 +4844,7 @@ namespace LCompilers { // TODO: Should be created outside the user loop and not here. // LLVMList should treat them as data members and create them // only if they are NULL - get_builder0() - llvm::AllocaInst *i = builder0.CreateAlloca(pos_type, nullptr); + llvm::AllocaInst *i = llvm_utils->CreateAlloca(pos_type); if(start) { LLVM::CreateStore(*builder, start, i); } @@ -4911,17 +4857,14 @@ namespace LCompilers { end_point = end; } else { - end_point = LLVM::CreateLoad(*builder, + end_point = llvm_utils->CreateLoad( get_pointer_to_current_end_point(list)); } llvm::Value* tmp = nullptr; /* Equivalent in C++: * int i = start; - * while(end_point > i) { - * if (list[i] == item) { - * break; - * } + * while(list[i] != item && end_point > i) { * i++; * } * @@ -4937,54 +4880,41 @@ namespace LCompilers { // head llvm_utils->start_new_block(loophead); { - llvm::Value *cond = builder->CreateICmpSGT(end_point, - LLVM::CreateLoad(*builder, i)); + llvm::Value* left_arg = read_item(list, llvm_utils->CreateLoad(i), + false, module, LLVM::is_llvm_struct(item_type)); + llvm::Value* is_item_not_equal = builder->CreateNot( + llvm_utils->is_equal_by_value( + left_arg, item, + module, item_type) + ); + llvm::Value *cond = builder->CreateAnd(is_item_not_equal, + builder->CreateICmpSGT(end_point, + llvm_utils->CreateLoad(i))); builder->CreateCondBr(cond, loopbody, loopend); } // body llvm_utils->start_new_block(loopbody); { - llvm::Value* left_arg = read_item(list, LLVM::CreateLoad(*builder, i), - false, module, LLVM::is_llvm_struct(item_type)); - - llvm::Value* is_item_equal = llvm_utils->is_equal_by_value( - left_arg, item, - module, item_type); - - llvm::BasicBlock *ifblock = llvm::BasicBlock::Create(context, "if"); - llvm::BasicBlock *elseblock = llvm::BasicBlock::Create(context, "else"); - - llvm_utils->start_new_block(ifblock); - { - builder->CreateCondBr(is_item_equal, loopend, elseblock); - } - - llvm_utils->start_new_block(elseblock); - { - tmp = builder->CreateAdd( - LLVM::CreateLoad(*builder, i), - llvm::ConstantInt::get(context, llvm::APInt(32, 1))); - LLVM::CreateStore(*builder, tmp, i); - builder->CreateBr(loophead); - } + tmp = builder->CreateAdd( + llvm_utils->CreateLoad(i), + llvm::ConstantInt::get(context, llvm::APInt(32, 1))); + LLVM::CreateStore(*builder, tmp, i); } + builder->CreateBr(loophead); // end llvm_utils->start_new_block(loopend); llvm::Value* cond = builder->CreateICmpEQ( - LLVM::CreateLoad(*builder, i), end_point); + llvm_utils->CreateLoad(i), end_point); llvm::Value* start_greater_than_end = builder->CreateICmpSGE( - LLVM::CreateLoad(*builder, i), end_point); + llvm_utils->CreateLoad(i), end_point); llvm::Value* condition = builder->CreateOr(cond, start_greater_than_end); llvm_utils->create_if_else(condition, [&]() { std::string message = "The list does not contain the element: "; llvm::Value *fmt_ptr = builder->CreateGlobalStringPtr("ValueError: %s%d\n"); llvm::Value *fmt_ptr2 = builder->CreateGlobalStringPtr(message); - if (ASR::is_a(*item_type)) { - fmt_ptr = builder->CreateGlobalStringPtr("ValueError: %s%s\n"); - } print_error(context, module, *builder, {fmt_ptr, fmt_ptr2, item}); int exit_code_int = 1; llvm::Value *exit_code = llvm::ConstantInt::get(context, @@ -4992,7 +4922,7 @@ namespace LCompilers { exit(context, module, *builder, exit_code); }, [=]() { }); - return LLVM::CreateLoad(*builder, i); + return llvm_utils->CreateLoad(i); } llvm::Value* LLVMList::index(llvm::Value* list, llvm::Value* item, @@ -5004,13 +4934,12 @@ namespace LCompilers { llvm::Value* LLVMList::count(llvm::Value* list, llvm::Value* item, ASR::ttype_t* item_type, llvm::Module& module) { llvm::Type* pos_type = llvm::Type::getInt32Ty(context); - llvm::Value* current_end_point = LLVM::CreateLoad(*builder, + llvm::Value* current_end_point = llvm_utils->CreateLoad( get_pointer_to_current_end_point(list)); - get_builder0() - llvm::AllocaInst *i = builder0.CreateAlloca(pos_type, nullptr); + llvm::AllocaInst *i = llvm_utils->CreateAlloca(pos_type); LLVM::CreateStore(*builder, llvm::ConstantInt::get( context, llvm::APInt(32, 0)), i); - llvm::AllocaInst *cnt = builder0.CreateAlloca(pos_type, nullptr); + llvm::AllocaInst *cnt = llvm_utils->CreateAlloca(pos_type); LLVM::CreateStore(*builder, llvm::ConstantInt::get( context, llvm::APInt(32, 0)), cnt); llvm::Value* tmp = nullptr; @@ -5036,7 +4965,7 @@ namespace LCompilers { llvm_utils->start_new_block(loophead); { llvm::Value *cond = builder->CreateICmpSGT(current_end_point, - LLVM::CreateLoad(*builder, i)); + llvm_utils->CreateLoad(i)); builder->CreateCondBr(cond, loopbody, loopend); } @@ -5044,19 +4973,19 @@ namespace LCompilers { llvm_utils->start_new_block(loopbody); { // if occurrence found, increment cnt - llvm::Value* left_arg = read_item(list, LLVM::CreateLoad(*builder, i), + llvm::Value* left_arg = read_item(list, llvm_utils->CreateLoad(i), false, module, LLVM::is_llvm_struct(item_type)); llvm::Value* cond = llvm_utils->is_equal_by_value(left_arg, item, module, item_type); llvm_utils->create_if_else(cond, [&]() { tmp = builder->CreateAdd( - LLVM::CreateLoad(*builder, cnt), + llvm_utils->CreateLoad(cnt), llvm::ConstantInt::get(context, llvm::APInt(32, 1))); LLVM::CreateStore(*builder, tmp, cnt); }, [=]() { }); // increment i tmp = builder->CreateAdd( - LLVM::CreateLoad(*builder, i), + llvm_utils->CreateLoad(i), llvm::ConstantInt::get(context, llvm::APInt(32, 1))); LLVM::CreateStore(*builder, tmp, i); } @@ -5065,20 +4994,18 @@ namespace LCompilers { // end llvm_utils->start_new_block(loopend); - return LLVM::CreateLoad(*builder, cnt); + return llvm_utils->CreateLoad(cnt); } void LLVMList::remove(llvm::Value* list, llvm::Value* item, ASR::ttype_t* item_type, llvm::Module& module) { - get_builder0() - llvm::Type* pos_type = llvm::Type::getInt32Ty(context); - llvm::Value* current_end_point = LLVM::CreateLoad(*builder, + llvm::Value* current_end_point = llvm_utils->CreateLoad( get_pointer_to_current_end_point(list)); // TODO: Should be created outside the user loop and not here. // LLVMList should treat them as data members and create them // only if they are NULL - llvm::AllocaInst *item_pos = builder0.CreateAlloca(pos_type, nullptr); + llvm::AllocaInst *item_pos = llvm_utils->CreateAlloca(pos_type); llvm::Value* tmp = LLVMList::find_item_position(list, item, item_type, module); LLVM::CreateStore(*builder, tmp, item_pos); @@ -5099,7 +5026,7 @@ namespace LCompilers { llvm_utils->start_new_block(loophead); { llvm::Value *cond = builder->CreateICmpSGT(current_end_point, - LLVM::CreateLoad(*builder, item_pos)); + llvm_utils->CreateLoad(item_pos)); builder->CreateCondBr(cond, loopbody, loopend); } @@ -5107,9 +5034,9 @@ namespace LCompilers { llvm_utils->start_new_block(loopbody); { tmp = builder->CreateAdd( - LLVM::CreateLoad(*builder, item_pos), + llvm_utils->CreateLoad(item_pos), llvm::ConstantInt::get(context, llvm::APInt(32, 1))); - write_item(list, LLVM::CreateLoad(*builder, item_pos), + write_item(list, llvm_utils->CreateLoad(item_pos), read_item(list, tmp, false, module, false), false, module); LLVM::CreateStore(*builder, tmp, item_pos); } @@ -5120,7 +5047,7 @@ namespace LCompilers { // Decrement end point by one llvm::Value* end_point_ptr = get_pointer_to_current_end_point(list); - llvm::Value* end_point = LLVM::CreateLoad(*builder, end_point_ptr); + llvm::Value* end_point = llvm_utils->CreateLoad(end_point_ptr); end_point = builder->CreateSub(end_point, llvm::ConstantInt::get( context, llvm::APInt(32, 1))); builder->CreateStore(end_point, end_point_ptr); @@ -5130,7 +5057,7 @@ namespace LCompilers { // If list is empty, output error llvm::Value* end_point_ptr = get_pointer_to_current_end_point(list); - llvm::Value* end_point = LLVM::CreateLoad(*builder, end_point_ptr); + llvm::Value* end_point = llvm_utils->CreateLoad(end_point_ptr); llvm::Value* cond = builder->CreateICmpEQ(llvm::ConstantInt::get( context, llvm::APInt(32, 0)), end_point); @@ -5161,7 +5088,6 @@ namespace LCompilers { llvm::Value* LLVMList::pop_position(llvm::Value* list, llvm::Value* pos, ASR::ttype_t* list_element_type, llvm::Module* module, std::map>& name2memidx) { - get_builder0() /* Equivalent in C++: * while(end_point > pos + 1) { * tmp = pos + 1; @@ -5171,20 +5097,20 @@ namespace LCompilers { */ llvm::Value* end_point_ptr = get_pointer_to_current_end_point(list); - llvm::Value* end_point = LLVM::CreateLoad(*builder, end_point_ptr); + llvm::Value* end_point = llvm_utils->CreateLoad(end_point_ptr); - llvm::AllocaInst *pos_ptr = builder0.CreateAlloca( - llvm::Type::getInt32Ty(context), nullptr); + llvm::AllocaInst *pos_ptr = llvm_utils->CreateAlloca( + llvm::Type::getInt32Ty(context)); LLVM::CreateStore(*builder, pos, pos_ptr); llvm::Value* tmp = nullptr; // Get element to return - llvm::Value* item = read_item(list, LLVM::CreateLoad(*builder, pos_ptr), + llvm::Value* item = read_item(list, llvm_utils->CreateLoad(pos_ptr), true, *module, LLVM::is_llvm_struct(list_element_type)); if( LLVM::is_llvm_struct(list_element_type) ) { std::string list_element_type_code = ASRUtils::get_type_code(list_element_type); LCOMPILERS_ASSERT(typecode2listtype.find(list_element_type_code) != typecode2listtype.end()); - llvm::AllocaInst *target = builder0.CreateAlloca( + llvm::AllocaInst *target = llvm_utils->CreateAlloca( std::get<2>(typecode2listtype[list_element_type_code]), nullptr, "pop_position_item"); llvm_utils->deepcopy(item, target, list_element_type, module, name2memidx); @@ -5199,7 +5125,7 @@ namespace LCompilers { llvm_utils->start_new_block(loophead); { llvm::Value *cond = builder->CreateICmpSGT(end_point, builder->CreateAdd( - LLVM::CreateLoad(*builder, pos_ptr), + llvm_utils->CreateLoad(pos_ptr), llvm::ConstantInt::get(context, llvm::APInt(32, 1)))); builder->CreateCondBr(cond, loopbody, loopend); } @@ -5208,9 +5134,9 @@ namespace LCompilers { llvm_utils->start_new_block(loopbody); { tmp = builder->CreateAdd( - LLVM::CreateLoad(*builder, pos_ptr), + llvm_utils->CreateLoad(pos_ptr), llvm::ConstantInt::get(context, llvm::APInt(32, 1))); - write_item(list, LLVM::CreateLoad(*builder, pos_ptr), + write_item(list, llvm_utils->CreateLoad(pos_ptr), read_item(list, tmp, false, *module, false), false, *module); LLVM::CreateStore(*builder, tmp, pos_ptr); } @@ -5227,56 +5153,15 @@ namespace LCompilers { return item; } - void LLVMList::list_clear(llvm::Value* list, ASR::ttype_t *item_type, - llvm::Module* module) { - free_data(list, item_type, *module); - std::string type_code = ASRUtils::get_type_code(item_type) ; - list_init(type_code, list, *module, 0, 0); + void LLVMList::list_clear(llvm::Value* list) { + llvm::Value* end_point_ptr = get_pointer_to_current_end_point(list); + llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), + llvm::APInt(32, 0)); + LLVM::CreateStore(*builder, zero, end_point_ptr); } - void LLVMList::free_data(llvm::Value* list, ASR::ttype_t* item_type, llvm::Module& module) { - // If it is an llvm struct, then it would require nested freeing, - // or else a simple free of the allocated data for the list is enough. - get_builder0() - if (LLVM::is_llvm_struct(item_type)) { - llvm::AllocaInst *pos_ptr = builder0.CreateAlloca(llvm::Type::getInt32Ty(context), - nullptr); - LLVM::CreateStore(*builder, llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), - llvm::APInt(32, 0)), pos_ptr); - - llvm::BasicBlock *loophead = llvm::BasicBlock::Create(context, "loop.head"); - llvm::BasicBlock *loopbody = llvm::BasicBlock::Create(context, "loop.body"); - llvm::BasicBlock *loopend = llvm::BasicBlock::Create(context, "loop.end"); - - // head - llvm_utils->start_new_block(loophead); - { - llvm::Value *cond = builder->CreateICmpSGT( - LLVM::CreateLoad(*builder, - get_pointer_to_current_end_point(list)), - LLVM::CreateLoad(*builder, pos_ptr)); - builder->CreateCondBr(cond, loopbody, loopend); - } - - // body - llvm_utils->start_new_block(loopbody); - { - llvm::Value* pos = LLVM::CreateLoad(*builder, pos_ptr); - llvm::Value* item = read_item(list, pos, false, module, true); - - llvm_utils->free_data(item, item_type, &module); - llvm::Value* tmp = builder->CreateAdd( - pos, - llvm::ConstantInt::get(context, llvm::APInt(32, 1))); - LLVM::CreateStore(*builder, tmp, pos_ptr); - } - builder->CreateBr(loophead); - - // end - llvm_utils->start_new_block(loopend); - } - - llvm::Value* data = LLVM::CreateLoad(*builder, get_pointer_to_list_data(list)); + void LLVMList::free_data(llvm::Value* list, llvm::Module& module) { + llvm::Value* data = llvm_utils->CreateLoad(get_pointer_to_list_data(list)); LLVM::lfortran_free(context, module, *builder, data); } @@ -5285,8 +5170,7 @@ namespace LCompilers { llvm::LLVMContext& context, llvm::IRBuilder<>* builder, llvm::Module& module) { - get_builder0() - llvm::AllocaInst *is_equal = builder0.CreateAlloca(llvm::Type::getInt1Ty(context), nullptr); + llvm::AllocaInst *is_equal = llvm_utils->CreateAlloca(llvm::Type::getInt1Ty(context)); LLVM::CreateStore(*builder, llvm::ConstantInt::get(context, llvm::APInt(1, 1)), is_equal); llvm::Value *a_len = llvm_utils->list_api->len(l1); llvm::Value *b_len = llvm_utils->list_api->len(l2); @@ -5297,8 +5181,7 @@ namespace LCompilers { llvm::BasicBlock *mergeBB = llvm::BasicBlock::Create(context, "ifcont"); builder->CreateCondBr(cond, thenBB, elseBB); builder->SetInsertPoint(thenBB); - builder0.SetInsertPoint(&entry_block, entry_block.getFirstInsertionPt()); - llvm::AllocaInst *idx = builder0.CreateAlloca(llvm::Type::getInt32Ty(context), nullptr); + llvm::AllocaInst *idx = llvm_utils->CreateAlloca(llvm::Type::getInt32Ty(context)); LLVM::CreateStore(*builder, llvm::ConstantInt::get( context, llvm::APInt(32, 0)), idx); llvm::BasicBlock *loophead = llvm::BasicBlock::Create(context, "loop.head"); @@ -5308,7 +5191,7 @@ namespace LCompilers { // head llvm_utils->start_new_block(loophead); { - llvm::Value* i = LLVM::CreateLoad(*builder, idx); + llvm::Value* i = llvm_utils->CreateLoad(idx); llvm::Value* cnd = builder->CreateICmpSLT(i, a_len); builder->CreateCondBr(cnd, loopbody, loopend); } @@ -5316,14 +5199,14 @@ namespace LCompilers { // body llvm_utils->start_new_block(loopbody); { - llvm::Value* i = LLVM::CreateLoad(*builder, idx); + llvm::Value* i = llvm_utils->CreateLoad(idx); llvm::Value* left_arg = llvm_utils->list_api->read_item(l1, i, false, module, LLVM::is_llvm_struct(item_type)); llvm::Value* right_arg = llvm_utils->list_api->read_item(l2, i, false, module, LLVM::is_llvm_struct(item_type)); llvm::Value* res = llvm_utils->is_equal_by_value(left_arg, right_arg, module, item_type); - res = builder->CreateAnd(LLVM::CreateLoad(*builder, is_equal), res); + res = builder->CreateAnd(llvm_utils->CreateLoad(is_equal), res); LLVM::CreateStore(*builder, res, is_equal); i = builder->CreateAdd(i, llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), llvm::APInt(32, 1))); @@ -5339,7 +5222,7 @@ namespace LCompilers { llvm_utils->start_new_block(elseBB); LLVM::CreateStore(*builder, llvm::ConstantInt::get(context, llvm::APInt(1, 0)), is_equal); llvm_utils->start_new_block(mergeBB); - return LLVM::CreateLoad(*builder, is_equal); + return llvm_utils->CreateLoad(is_equal); } llvm::Value* LLVMList::check_list_inequality(llvm::Value* l1, llvm::Value* l2, @@ -5367,20 +5250,18 @@ namespace LCompilers { * */ - get_builder0() - llvm::AllocaInst *equality_holds = builder0.CreateAlloca( - llvm::Type::getInt1Ty(context), nullptr); + llvm::AllocaInst *equality_holds = llvm_utils->CreateAlloca( + llvm::Type::getInt1Ty(context)); LLVM::CreateStore(*builder, llvm::ConstantInt::get(context, llvm::APInt(1, 1)), equality_holds); - llvm::AllocaInst *inequality_holds = builder0.CreateAlloca( - llvm::Type::getInt1Ty(context), nullptr); + llvm::AllocaInst *inequality_holds = llvm_utils->CreateAlloca( + llvm::Type::getInt1Ty(context)); LLVM::CreateStore(*builder, llvm::ConstantInt::get(context, llvm::APInt(1, 0)), inequality_holds); llvm::Value *a_len = llvm_utils->list_api->len(l1); llvm::Value *b_len = llvm_utils->list_api->len(l2); - builder0.SetInsertPoint(&entry_block, entry_block.getFirstInsertionPt()); - llvm::AllocaInst *idx = builder0.CreateAlloca(llvm::Type::getInt32Ty(context), nullptr); + llvm::AllocaInst *idx = llvm_utils->CreateAlloca(llvm::Type::getInt32Ty(context)); LLVM::CreateStore(*builder, llvm::ConstantInt::get( context, llvm::APInt(32, 0)), idx); llvm::BasicBlock *loophead = llvm::BasicBlock::Create(context, "loop.head"); @@ -5390,28 +5271,28 @@ namespace LCompilers { // head llvm_utils->start_new_block(loophead); { - llvm::Value* i = LLVM::CreateLoad(*builder, idx); + llvm::Value* i = llvm_utils->CreateLoad(idx); llvm::Value* cnd = builder->CreateICmpSLT(i, a_len); cnd = builder->CreateAnd(cnd, builder->CreateICmpSLT(i, b_len)); - cnd = builder->CreateAnd(cnd, LLVM::CreateLoad(*builder, equality_holds)); + cnd = builder->CreateAnd(cnd, llvm_utils->CreateLoad(equality_holds)); builder->CreateCondBr(cnd, loopbody, loopend); } // body llvm_utils->start_new_block(loopbody); { - llvm::Value* i = LLVM::CreateLoad(*builder, idx); + llvm::Value* i = llvm_utils->CreateLoad(idx); llvm::Value* left_arg = llvm_utils->list_api->read_item(l1, i, false, module, LLVM::is_llvm_struct(item_type)); llvm::Value* right_arg = llvm_utils->list_api->read_item(l2, i, false, module, LLVM::is_llvm_struct(item_type)); llvm::Value* res = llvm_utils->is_ineq_by_value(left_arg, right_arg, module, item_type, overload_id); - res = builder->CreateOr(LLVM::CreateLoad(*builder, inequality_holds), res); + res = builder->CreateOr(llvm_utils->CreateLoad(inequality_holds), res); LLVM::CreateStore(*builder, res, inequality_holds); res = llvm_utils->is_equal_by_value(left_arg, right_arg, module, item_type); - res = builder->CreateAnd(LLVM::CreateLoad(*builder, equality_holds), res); + res = builder->CreateAnd(llvm_utils->CreateLoad(equality_holds), res); LLVM::CreateStore(*builder, res, equality_holds); i = builder->CreateAdd(i, llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), llvm::APInt(32, 1))); @@ -5423,11 +5304,11 @@ namespace LCompilers { // end llvm_utils->start_new_block(loopend); - llvm::Value* cond = builder->CreateICmpEQ(LLVM::CreateLoad(*builder, idx), + llvm::Value* cond = builder->CreateICmpEQ(llvm_utils->CreateLoad(idx), a_len); cond = builder->CreateOr(cond, builder->CreateICmpEQ( - LLVM::CreateLoad(*builder, idx), b_len)); - cond = builder->CreateAnd(cond, LLVM::CreateLoad(*builder, equality_holds)); + llvm_utils->CreateLoad(idx), b_len)); + cond = builder->CreateAnd(cond, llvm_utils->CreateLoad(equality_holds)); llvm_utils->create_if_else(cond, [&]() { LLVM::CreateStore(*builder, llvm_utils->is_ineq_by_value(a_len, b_len, module, int32_type, overload_id), inequality_holds); @@ -5436,18 +5317,17 @@ namespace LCompilers { // context, llvm::APInt(1, 0)), inequality_holds); }); - return LLVM::CreateLoad(*builder, inequality_holds); + return llvm_utils->CreateLoad(inequality_holds); } void LLVMList::list_repeat_copy(llvm::Value* repeat_list, llvm::Value* init_list, llvm::Value* num_times, llvm::Value* init_list_len, llvm::Module* module) { - get_builder0() llvm::Type* pos_type = llvm::Type::getInt32Ty(context); - llvm::AllocaInst *i = builder0.CreateAlloca(pos_type, nullptr); + llvm::AllocaInst *i = llvm_utils->CreateAlloca(pos_type); LLVM::CreateStore(*builder, llvm::ConstantInt::get( context, llvm::APInt(32, 0)), i); // i = 0 - llvm::AllocaInst *j = builder0.CreateAlloca(pos_type, nullptr); + llvm::AllocaInst *j = llvm_utils->CreateAlloca(pos_type); llvm::Value* tmp = nullptr; llvm::BasicBlock *loophead = llvm::BasicBlock::Create(context, "loop.head"); @@ -5458,7 +5338,7 @@ namespace LCompilers { llvm_utils->start_new_block(loophead); { llvm::Value *cond = builder->CreateICmpSGT(num_times, - LLVM::CreateLoad(*builder, i)); + llvm_utils->CreateLoad(i)); builder->CreateCondBr(cond, loopbody, loopend); } @@ -5476,21 +5356,21 @@ namespace LCompilers { llvm_utils->start_new_block(loop2head); { llvm::Value *cond2 = builder->CreateICmpSGT(init_list_len, - LLVM::CreateLoad(*builder, j)); + llvm_utils->CreateLoad(j)); builder->CreateCondBr(cond2, loop2body, loop2end); } // body llvm_utils->start_new_block(loop2body); { - tmp = builder->CreateMul(init_list_len, LLVM::CreateLoad(*builder, i)); - tmp = builder->CreateAdd(tmp, LLVM::CreateLoad(*builder, j)); + tmp = builder->CreateMul(init_list_len, llvm_utils->CreateLoad(i)); + tmp = builder->CreateAdd(tmp, llvm_utils->CreateLoad(j)); write_item(repeat_list, tmp, - read_item(init_list, LLVM::CreateLoad(*builder, j), + read_item(init_list, llvm_utils->CreateLoad(j), false, *module, false), false, *module); tmp = builder->CreateAdd( - LLVM::CreateLoad(*builder, j), + llvm_utils->CreateLoad(j), llvm::ConstantInt::get(context, llvm::APInt(32, 1))); LLVM::CreateStore(*builder, tmp, j); } @@ -5500,7 +5380,7 @@ namespace LCompilers { llvm_utils->start_new_block(loop2end); tmp = builder->CreateAdd( - LLVM::CreateLoad(*builder, i), + llvm_utils->CreateLoad(i), llvm::ConstantInt::get(context, llvm::APInt(32, 1))); LLVM::CreateStore(*builder, tmp, i); } @@ -5512,8 +5392,8 @@ namespace LCompilers { LLVMTuple::LLVMTuple(llvm::LLVMContext& context_, LLVMUtils* llvm_utils_, - llvm::IRBuilder<>* builder_) : - context(context_), llvm_utils(llvm_utils_), builder(builder_) {} + llvm::IRBuilder<>* /*builder_*/) : + context(context_), llvm_utils(llvm_utils_) {} llvm::Type* LLVMTuple::get_tuple_type(std::string& type_code, std::vector& el_types) { @@ -5532,7 +5412,7 @@ namespace LCompilers { if( get_pointer ) { return item; } - return LLVM::CreateLoad(*builder, item); + return llvm_utils->CreateLoad(item); } llvm::Value* LLVMTuple::read_item(llvm::Value* llvm_tuple, size_t pos, @@ -5608,33 +5488,32 @@ namespace LCompilers { * */ - get_builder0() - llvm::AllocaInst *equality_holds = builder0.CreateAlloca( - llvm::Type::getInt1Ty(context), nullptr); + llvm::AllocaInst *equality_holds = llvm_utils->CreateAlloca( + llvm::Type::getInt1Ty(context)); LLVM::CreateStore(*builder, llvm::ConstantInt::get(context, llvm::APInt(1, 1)), equality_holds); - llvm::AllocaInst *inequality_holds = builder0.CreateAlloca( - llvm::Type::getInt1Ty(context), nullptr); + llvm::AllocaInst *inequality_holds = llvm_utils->CreateAlloca( + llvm::Type::getInt1Ty(context)); LLVM::CreateStore(*builder, llvm::ConstantInt::get(context, llvm::APInt(1, 0)), inequality_holds); for( size_t i = 0; i < tuple_type->n_type; i++ ) { - llvm_utils->create_if_else(LLVM::CreateLoad(*builder, equality_holds), [&]() { + llvm_utils->create_if_else(llvm_utils->CreateLoad(equality_holds), [&]() { llvm::Value* t1i = llvm_utils->tuple_api->read_item(t1, i, LLVM::is_llvm_struct( tuple_type->m_type[i])); llvm::Value* t2i = llvm_utils->tuple_api->read_item(t2, i, LLVM::is_llvm_struct( tuple_type->m_type[i])); llvm::Value* res = llvm_utils->is_ineq_by_value(t1i, t2i, module, tuple_type->m_type[i], overload_id); - res = builder->CreateOr(LLVM::CreateLoad(*builder, inequality_holds), res); + res = builder->CreateOr(llvm_utils->CreateLoad(inequality_holds), res); LLVM::CreateStore(*builder, res, inequality_holds); res = llvm_utils->is_equal_by_value(t1i, t2i, module, tuple_type->m_type[i]); - res = builder->CreateAnd(LLVM::CreateLoad(*builder, equality_holds), res); + res = builder->CreateAnd(llvm_utils->CreateLoad(equality_holds), res); LLVM::CreateStore(*builder, res, equality_holds); }, [](){}); } - return LLVM::CreateLoad(*builder, inequality_holds); + return llvm_utils->CreateLoad(inequality_holds); } void LLVMTuple::concat(llvm::Value* t1, llvm::Value* t2, ASR::Tuple_t* tuple_type_1, @@ -5755,7 +5634,7 @@ namespace LCompilers { type_code, type_size); std::vector set_type_vec = {llvm::Type::getInt32Ty(context), el_list_type, - llvm::Type::getInt8PtrTy(context)}; + llvm::Type::getInt8Ty(context)->getPointerTo()}; llvm::Type* set_desc = llvm::StructType::create(context, set_type_vec, "set"); typecode2settype[type_code] = std::make_tuple(set_desc, type_size, el_type); return set_desc; @@ -5768,13 +5647,13 @@ namespace LCompilers { return std::get<0>(typecode2settype[el_type_code]); } - std::vector el_vec = {el_type, llvm::Type::getInt8PtrTy(context)}; + std::vector el_vec = {el_type, llvm::Type::getInt8Ty(context)->getPointerTo()}; llvm::Type* elstruct = llvm::StructType::create(context, el_vec, "el"); std::vector set_type_vec = {llvm::Type::getInt32Ty(context), llvm::Type::getInt32Ty(context), llvm::Type::getInt32Ty(context), elstruct->getPointerTo(), - llvm::Type::getInt8PtrTy(context), + llvm::Type::getInt8Ty(context)->getPointerTo(), llvm::Type::getInt1Ty(context)}; llvm::Type* set_desc = llvm::StructType::create(context, set_type_vec, "set"); typecode2settype[el_type_code] = std::make_tuple(set_desc, el_type_size, el_type); @@ -5816,7 +5695,7 @@ namespace LCompilers { std::string el_type_code, llvm::Value* set, llvm::Module* module, llvm::Value* llvm_capacity) { llvm::Value* rehash_flag_ptr = get_pointer_to_rehash_flag(set); - llvm::Value* rehash_flag = LLVM::CreateLoad(*builder, rehash_flag_ptr); + llvm::Value* rehash_flag = llvm_utils->CreateLoad(rehash_flag_ptr); llvm::Value* llvm_zero = llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), llvm::APInt(32, 0)); llvm::Value* occupancy_ptr = get_pointer_to_occupancy(set); LLVM::CreateStore(*builder, llvm_zero, occupancy_ptr); @@ -5831,7 +5710,7 @@ namespace LCompilers { llvm::Value* el_ptr = LLVM::lfortran_malloc(context, *module, *builder, malloc_size); rehash_flag = builder->CreateAnd(rehash_flag, builder->CreateICmpNE(el_ptr, - llvm::ConstantPointerNull::get(llvm::Type::getInt8PtrTy(context))) + llvm::ConstantPointerNull::get(llvm::Type::getInt8Ty(context)->getPointerTo())) ); el_ptr = builder->CreateBitCast(el_ptr, el_type->getPointerTo()); LLVM::CreateStore(*builder, el_ptr, get_pointer_to_elems(set)); @@ -5843,7 +5722,7 @@ namespace LCompilers { llvm_mask_size); rehash_flag = builder->CreateAnd(rehash_flag, builder->CreateICmpNE(el_mask, - llvm::ConstantPointerNull::get(llvm::Type::getInt8PtrTy(context))) + llvm::ConstantPointerNull::get(llvm::Type::getInt8Ty(context)->getPointerTo())) ); LLVM::CreateStore(*builder, el_mask, get_pointer_to_mask(set)); @@ -5871,16 +5750,15 @@ namespace LCompilers { ); return int_hash; } - case ASR::ttypeType::Character: { + case ASR::ttypeType::String: { // Polynomial rolling hash function for strings llvm::Value* null_char = llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), llvm::APInt(8, '\0')); llvm::Value* p = llvm::ConstantInt::get(llvm::Type::getInt64Ty(context), llvm::APInt(64, 31)); llvm::Value* m = llvm::ConstantInt::get(llvm::Type::getInt64Ty(context), llvm::APInt(64, 100000009)); - get_builder0() - hash_value = builder0.CreateAlloca(llvm::Type::getInt64Ty(context), nullptr, "hash_value"); - hash_iter = builder0.CreateAlloca(llvm::Type::getInt64Ty(context), nullptr, "hash_iter"); - polynomial_powers = builder0.CreateAlloca(llvm::Type::getInt64Ty(context), nullptr, "p_pow"); + hash_value = llvm_utils->CreateAlloca(llvm::Type::getInt64Ty(context), nullptr, "hash_value"); + hash_iter = llvm_utils->CreateAlloca(llvm::Type::getInt64Ty(context), nullptr, "hash_iter"); + polynomial_powers = llvm_utils->CreateAlloca(llvm::Type::getInt64Ty(context), nullptr, "p_pow"); LLVM::CreateStore(*builder, llvm::ConstantInt::get(llvm::Type::getInt64Ty(context), llvm::APInt(64, 0)), hash_value); @@ -5897,8 +5775,8 @@ namespace LCompilers { // head llvm_utils->start_new_block(loophead); { - llvm::Value* i = LLVM::CreateLoad(*builder, hash_iter); - llvm::Value* c = LLVM::CreateLoad(*builder, llvm_utils->create_ptr_gep(el, i)); + llvm::Value* i = llvm_utils->CreateLoad(hash_iter); + llvm::Value* c = llvm_utils->CreateLoad(llvm_utils->create_ptr_gep(el, i)); llvm::Value *cond = builder->CreateICmpNE(c, null_char); builder->CreateCondBr(cond, loopbody, loopend); } @@ -5909,10 +5787,10 @@ namespace LCompilers { // for c in el: // hash_value = (hash_value + (ord(c) + 1) * p_pow) % m // p_pow = (p_pow * p) % m - llvm::Value* i = LLVM::CreateLoad(*builder, hash_iter); - llvm::Value* c = LLVM::CreateLoad(*builder, llvm_utils->create_ptr_gep(el, i)); - llvm::Value* p_pow = LLVM::CreateLoad(*builder, polynomial_powers); - llvm::Value* hash = LLVM::CreateLoad(*builder, hash_value); + llvm::Value* i = llvm_utils->CreateLoad(hash_iter); + llvm::Value* c = llvm_utils->CreateLoad(llvm_utils->create_ptr_gep(el, i)); + llvm::Value* p_pow = llvm_utils->CreateLoad(polynomial_powers); + llvm::Value* hash = llvm_utils->CreateLoad(hash_value); c = builder->CreateZExt(c, llvm::Type::getInt64Ty(context)); c = builder->CreateAdd(c, llvm::ConstantInt::get(llvm::Type::getInt64Ty(context), llvm::APInt(64, 1))); c = builder->CreateMul(c, p_pow); @@ -5931,7 +5809,7 @@ namespace LCompilers { // end llvm_utils->start_new_block(loopend); - llvm::Value* hash = LLVM::CreateLoad(*builder, hash_value); + llvm::Value* hash = llvm_utils->CreateLoad(hash_value); hash = builder->CreateTrunc(hash, llvm::Type::getInt32Ty(context)); return builder->CreateSRem(hash, capacity); } @@ -6002,11 +5880,10 @@ namespace LCompilers { * */ - get_builder0() if( !for_read ) { - pos_ptr = builder0.CreateAlloca(llvm::Type::getInt32Ty(context), nullptr); + pos_ptr = llvm_utils->CreateAlloca(llvm::Type::getInt32Ty(context)); } - is_el_matching_var = builder0.CreateAlloca(llvm::Type::getInt1Ty(context), nullptr); + is_el_matching_var = llvm_utils->CreateAlloca(llvm::Type::getInt1Ty(context)); LLVM::CreateStore(*builder, el_hash, pos_ptr); @@ -6017,8 +5894,8 @@ namespace LCompilers { // head llvm_utils->start_new_block(loophead); { - llvm::Value* pos = LLVM::CreateLoad(*builder, pos_ptr); - llvm::Value* el_mask_value = LLVM::CreateLoad(*builder, + llvm::Value* pos = llvm_utils->CreateLoad(pos_ptr); + llvm::Value* el_mask_value = llvm_utils->CreateLoad( llvm_utils->create_ptr_gep(el_mask, pos)); llvm::Value* is_el_skip = builder->CreateICmpEQ(el_mask_value, llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), llvm::APInt(8, 3))); @@ -6045,12 +5922,12 @@ namespace LCompilers { llvm::Value *cond = nullptr; if( for_read ) { cond = builder->CreateAnd(is_el_set, builder->CreateNot( - LLVM::CreateLoad(*builder, is_el_matching_var))); + llvm_utils->CreateLoad(is_el_matching_var))); cond = builder->CreateOr(is_el_skip, cond); } else { cond = builder->CreateAnd(is_el_set, builder->CreateNot(is_el_skip)); cond = builder->CreateAnd(cond, builder->CreateNot( - LLVM::CreateLoad(*builder, is_el_matching_var))); + llvm_utils->CreateLoad(is_el_matching_var))); } builder->CreateCondBr(cond, loopbody, loopend); } @@ -6058,7 +5935,7 @@ namespace LCompilers { // body llvm_utils->start_new_block(loopbody); { - llvm::Value* pos = LLVM::CreateLoad(*builder, pos_ptr); + llvm::Value* pos = llvm_utils->CreateLoad(pos_ptr); pos = builder->CreateAdd(pos, llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), llvm::APInt(32, 1))); pos = builder->CreateSRem(pos, capacity); @@ -6099,22 +5976,21 @@ namespace LCompilers { * */ - get_builder0() - chain_itr = builder0.CreateAlloca(llvm::Type::getInt8PtrTy(context), nullptr); - chain_itr_prev = builder0.CreateAlloca(llvm::Type::getInt8PtrTy(context), nullptr); - is_el_matching_var = builder0.CreateAlloca(llvm::Type::getInt1Ty(context), nullptr); + chain_itr = llvm_utils->CreateAlloca(llvm::Type::getInt8Ty(context)->getPointerTo()); + chain_itr_prev = llvm_utils->CreateAlloca(llvm::Type::getInt8Ty(context)->getPointerTo()); + is_el_matching_var = llvm_utils->CreateAlloca(llvm::Type::getInt1Ty(context)); LLVM::CreateStore(*builder, - llvm::ConstantPointerNull::get(llvm::Type::getInt8PtrTy(context)), chain_itr_prev); - llvm::Value* el_mask_value = LLVM::CreateLoad(*builder, + llvm::ConstantPointerNull::get(llvm::Type::getInt8Ty(context)->getPointerTo()), chain_itr_prev); + llvm::Value* el_mask_value = llvm_utils->CreateLoad( llvm_utils->create_ptr_gep(el_mask, el_hash)); llvm_utils->create_if_else(builder->CreateICmpEQ(el_mask_value, llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), llvm::APInt(8, 1))), [&]() { - llvm::Value* el_ll_i8 = builder->CreateBitCast(el_linked_list, llvm::Type::getInt8PtrTy(context)); + llvm::Value* el_ll_i8 = builder->CreateBitCast(el_linked_list, llvm::Type::getInt8Ty(context)->getPointerTo()); LLVM::CreateStore(*builder, el_ll_i8, chain_itr); }, [&]() { LLVM::CreateStore(*builder, - llvm::ConstantPointerNull::get(llvm::Type::getInt8PtrTy(context)), chain_itr); + llvm::ConstantPointerNull::get(llvm::Type::getInt8Ty(context)->getPointerTo()), chain_itr); }); LLVM::CreateStore(*builder, llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), llvm::APInt(1, 0)), @@ -6128,28 +6004,28 @@ namespace LCompilers { llvm_utils->start_new_block(loophead); { llvm::Value *cond = builder->CreateICmpNE( - LLVM::CreateLoad(*builder, chain_itr), - llvm::ConstantPointerNull::get(llvm::Type::getInt8PtrTy(context)) + llvm_utils->CreateLoad(chain_itr), + llvm::ConstantPointerNull::get(llvm::Type::getInt8Ty(context)->getPointerTo()) ); - cond = builder->CreateAnd(cond, builder->CreateNot(LLVM::CreateLoad( - *builder, is_el_matching_var))); + cond = builder->CreateAnd(cond, builder->CreateNot( + llvm_utils->CreateLoad(is_el_matching_var))); builder->CreateCondBr(cond, loopbody, loopend); } // body llvm_utils->start_new_block(loopbody); { - llvm::Value* el_struct_i8 = LLVM::CreateLoad(*builder, chain_itr); + llvm::Value* el_struct_i8 = llvm_utils->CreateLoad(chain_itr); LLVM::CreateStore(*builder, el_struct_i8, chain_itr_prev); llvm::Value* el_struct = builder->CreateBitCast(el_struct_i8, el_struct_type->getPointerTo()); llvm::Value* el_struct_el = llvm_utils->create_gep(el_struct, 0); if( !LLVM::is_llvm_struct(el_asr_type) ) { - el_struct_el = LLVM::CreateLoad(*builder, el_struct_el); + el_struct_el = llvm_utils->CreateLoad(el_struct_el); } LLVM::CreateStore(*builder, llvm_utils->is_equal_by_value(el, el_struct_el, module, el_asr_type), is_el_matching_var); - llvm_utils->create_if_else(builder->CreateNot(LLVM::CreateLoad(*builder, is_el_matching_var)), [&]() { - llvm::Value* next_el_struct = LLVM::CreateLoad(*builder, llvm_utils->create_gep(el_struct, 1)); + llvm_utils->create_if_else(builder->CreateNot(llvm_utils->CreateLoad(is_el_matching_var)), [&]() { + llvm::Value* next_el_struct = llvm_utils->CreateLoad(llvm_utils->create_gep(el_struct, 1)); LLVM::CreateStore(*builder, next_el_struct, chain_itr); }, []() {}); } @@ -6182,14 +6058,14 @@ namespace LCompilers { */ llvm::Value* el_list = get_el_list(set); - llvm::Value* el_mask = LLVM::CreateLoad(*builder, get_pointer_to_mask(set)); - llvm::Value* capacity = LLVM::CreateLoad(*builder, get_pointer_to_capacity(set)); + llvm::Value* el_mask = llvm_utils->CreateLoad(get_pointer_to_mask(set)); + llvm::Value* capacity = llvm_utils->CreateLoad(get_pointer_to_capacity(set)); this->resolve_collision(capacity, el_hash, el, el_list, el_mask, *module, el_asr_type); - llvm::Value* pos = LLVM::CreateLoad(*builder, pos_ptr); + llvm::Value* pos = llvm_utils->CreateLoad(pos_ptr); llvm_utils->list_api->write_item(el_list, pos, el, el_asr_type, false, module, name2memidx); - llvm::Value* el_mask_value = LLVM::CreateLoad(*builder, + llvm::Value* el_mask_value = llvm_utils->CreateLoad( llvm_utils->create_ptr_gep(el_mask, pos)); llvm::Value* is_slot_empty = builder->CreateICmpEQ(el_mask_value, llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), llvm::APInt(8, 0))); @@ -6197,14 +6073,14 @@ namespace LCompilers { llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), llvm::APInt(8, 3)))); llvm::Value* occupancy_ptr = get_pointer_to_occupancy(set); is_slot_empty = builder->CreateZExt(is_slot_empty, llvm::Type::getInt32Ty(context)); - llvm::Value* occupancy = LLVM::CreateLoad(*builder, occupancy_ptr); + llvm::Value* occupancy = llvm_utils->CreateLoad(occupancy_ptr); LLVM::CreateStore(*builder, builder->CreateAdd(occupancy, is_slot_empty), occupancy_ptr); llvm::Value* linear_prob_happened = builder->CreateICmpNE(el_hash, pos); linear_prob_happened = builder->CreateOr(linear_prob_happened, builder->CreateICmpEQ( - LLVM::CreateLoad(*builder, llvm_utils->create_ptr_gep(el_mask, el_hash)), + llvm_utils->CreateLoad(llvm_utils->create_ptr_gep(el_mask, el_hash)), llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), llvm::APInt(8, 2) )) ); @@ -6249,27 +6125,27 @@ namespace LCompilers { * */ - llvm::Value* elems = LLVM::CreateLoad(*builder, get_pointer_to_elems(set)); + llvm::Value* elems = llvm_utils->CreateLoad(get_pointer_to_elems(set)); llvm::Value* el_linked_list = llvm_utils->create_ptr_gep(elems, el_hash); - llvm::Value* el_mask = LLVM::CreateLoad(*builder, get_pointer_to_mask(set)); + llvm::Value* el_mask = llvm_utils->CreateLoad(get_pointer_to_mask(set)); llvm::Type* el_struct_type = typecode2elstruct[ASRUtils::get_type_code(el_asr_type)]; this->resolve_collision(el_hash, el, el_linked_list, el_struct_type, el_mask, *module, el_asr_type); - llvm::Value* el_struct_i8 = LLVM::CreateLoad(*builder, chain_itr); + llvm::Value* el_struct_i8 = llvm_utils->CreateLoad(chain_itr); llvm::Function *fn = builder->GetInsertBlock()->getParent(); llvm::BasicBlock *thenBB = llvm::BasicBlock::Create(context, "then", fn); llvm::BasicBlock *elseBB = llvm::BasicBlock::Create(context, "else"); llvm::BasicBlock *mergeBB = llvm::BasicBlock::Create(context, "ifcont"); llvm::Value* do_insert = builder->CreateICmpEQ(el_struct_i8, - llvm::ConstantPointerNull::get(llvm::Type::getInt8PtrTy(context))); + llvm::ConstantPointerNull::get(llvm::Type::getInt8Ty(context)->getPointerTo())); builder->CreateCondBr(do_insert, thenBB, elseBB); builder->SetInsertPoint(thenBB); { llvm_utils->create_if_else(builder->CreateICmpNE( - LLVM::CreateLoad(*builder, chain_itr_prev), - llvm::ConstantPointerNull::get(llvm::Type::getInt8PtrTy(context))), [&]() { + llvm_utils->CreateLoad(chain_itr_prev), + llvm::ConstantPointerNull::get(llvm::Type::getInt8Ty(context)->getPointerTo())), [&]() { llvm::DataLayout data_layout(module); size_t el_struct_size = data_layout.getTypeAllocSize(el_struct_type); llvm::Value* malloc_size = llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), el_struct_size); @@ -6277,20 +6153,20 @@ namespace LCompilers { llvm::Value* new_el_struct = builder->CreateBitCast(new_el_struct_i8, el_struct_type->getPointerTo()); llvm_utils->deepcopy(el, llvm_utils->create_gep(new_el_struct, 0), el_asr_type, module, name2memidx); LLVM::CreateStore(*builder, - llvm::ConstantPointerNull::get(llvm::Type::getInt8PtrTy(context)), + llvm::ConstantPointerNull::get(llvm::Type::getInt8Ty(context)->getPointerTo()), llvm_utils->create_gep(new_el_struct, 1)); - llvm::Value* el_struct_prev_i8 = LLVM::CreateLoad(*builder, chain_itr_prev); + llvm::Value* el_struct_prev_i8 = llvm_utils->CreateLoad(chain_itr_prev); llvm::Value* el_struct_prev = builder->CreateBitCast(el_struct_prev_i8, el_struct_type->getPointerTo()); LLVM::CreateStore(*builder, new_el_struct_i8, llvm_utils->create_gep(el_struct_prev, 1)); }, [&]() { llvm_utils->deepcopy(el, llvm_utils->create_gep(el_linked_list, 0), el_asr_type, module, name2memidx); LLVM::CreateStore(*builder, - llvm::ConstantPointerNull::get(llvm::Type::getInt8PtrTy(context)), + llvm::ConstantPointerNull::get(llvm::Type::getInt8Ty(context)->getPointerTo()), llvm_utils->create_gep(el_linked_list, 1)); }); llvm::Value* occupancy_ptr = get_pointer_to_occupancy(set); - llvm::Value* occupancy = LLVM::CreateLoad(*builder, occupancy_ptr); + llvm::Value* occupancy = llvm_utils->CreateLoad(occupancy_ptr); occupancy = builder->CreateAdd(occupancy, llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), 1)); LLVM::CreateStore(*builder, occupancy, occupancy_ptr); @@ -6304,10 +6180,10 @@ namespace LCompilers { llvm_utils->start_new_block(mergeBB); llvm::Value* buckets_filled_ptr = get_pointer_to_number_of_filled_buckets(set); llvm::Value* el_mask_value_ptr = llvm_utils->create_ptr_gep(el_mask, el_hash); - llvm::Value* el_mask_value = LLVM::CreateLoad(*builder, el_mask_value_ptr); + llvm::Value* el_mask_value = llvm_utils->CreateLoad(el_mask_value_ptr); llvm::Value* buckets_filled_delta = builder->CreateICmpEQ(el_mask_value, llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), llvm::APInt(8, 0))); - llvm::Value* buckets_filled = LLVM::CreateLoad(*builder, buckets_filled_ptr); + llvm::Value* buckets_filled = llvm_utils->CreateLoad(buckets_filled_ptr); buckets_filled = builder->CreateAdd( buckets_filled, builder->CreateZExt(buckets_filled_delta, llvm::Type::getInt32Ty(context)) @@ -6350,10 +6226,8 @@ namespace LCompilers { * el_mask = new_el_mask; * */ - - get_builder0() llvm::Value* capacity_ptr = get_pointer_to_capacity(set); - llvm::Value* old_capacity = LLVM::CreateLoad(*builder, capacity_ptr); + llvm::Value* old_capacity = llvm_utils->CreateLoad(capacity_ptr); llvm::Value* capacity = builder->CreateMul(old_capacity, llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), llvm::APInt(32, 2))); capacity = builder->CreateAdd(capacity, llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), @@ -6365,11 +6239,11 @@ namespace LCompilers { int32_t el_type_size = std::get<1>(typecode2settype[el_type_code]); llvm::Value* el_list = get_el_list(set); - llvm::Value* new_el_list = builder0.CreateAlloca(llvm_utils->list_api->get_list_type(el_llvm_type, - el_type_code, el_type_size), nullptr); + llvm::Value* new_el_list = llvm_utils->CreateAlloca(llvm_utils->list_api->get_list_type(el_llvm_type, + el_type_code, el_type_size)); llvm_utils->list_api->list_init(el_type_code, new_el_list, *module, capacity, capacity); - llvm::Value* el_mask = LLVM::CreateLoad(*builder, get_pointer_to_mask(set)); + llvm::Value* el_mask = llvm_utils->CreateLoad(get_pointer_to_mask(set)); llvm::DataLayout data_layout(module); size_t mask_size = data_layout.getTypeAllocSize(llvm::Type::getInt8Ty(context)); llvm::Value* llvm_mask_size = llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), @@ -6377,8 +6251,8 @@ namespace LCompilers { llvm::Value* new_el_mask = LLVM::lfortran_calloc(context, *module, *builder, capacity, llvm_mask_size); - llvm::Value* current_capacity = LLVM::CreateLoad(*builder, get_pointer_to_capacity(set)); - idx_ptr = builder0.CreateAlloca(llvm::Type::getInt32Ty(context), nullptr); + llvm::Value* current_capacity = llvm_utils->CreateLoad(get_pointer_to_capacity(set)); + idx_ptr = llvm_utils->CreateAlloca(llvm::Type::getInt32Ty(context)); LLVM::CreateStore(*builder, llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), llvm::APInt(32, 0)), idx_ptr); @@ -6389,19 +6263,19 @@ namespace LCompilers { // head llvm_utils->start_new_block(loophead); { - llvm::Value *cond = builder->CreateICmpSGT(old_capacity, LLVM::CreateLoad(*builder, idx_ptr)); + llvm::Value *cond = builder->CreateICmpSGT(old_capacity, llvm_utils->CreateLoad(idx_ptr)); builder->CreateCondBr(cond, loopbody, loopend); } // body llvm_utils->start_new_block(loopbody); { - llvm::Value* idx = LLVM::CreateLoad(*builder, idx_ptr); + llvm::Value* idx = llvm_utils->CreateLoad(idx_ptr); llvm::Function *fn = builder->GetInsertBlock()->getParent(); llvm::BasicBlock *thenBB = llvm::BasicBlock::Create(context, "then", fn); llvm::BasicBlock *elseBB = llvm::BasicBlock::Create(context, "else"); llvm::BasicBlock *mergeBB = llvm::BasicBlock::Create(context, "ifcont"); - llvm::Value* is_el_set = LLVM::CreateLoad(*builder, llvm_utils->create_ptr_gep(el_mask, idx)); + llvm::Value* is_el_set = llvm_utils->CreateLoad(llvm_utils->create_ptr_gep(el_mask, idx)); is_el_set = builder->CreateICmpNE(is_el_set, llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), llvm::APInt(8, 0))); builder->CreateCondBr(is_el_set, thenBB, elseBB); @@ -6412,7 +6286,7 @@ namespace LCompilers { llvm::Value* el_hash = get_el_hash(current_capacity, el, el_asr_type, *module); this->resolve_collision(current_capacity, el_hash, el, new_el_list, new_el_mask, *module, el_asr_type); - llvm::Value* pos = LLVM::CreateLoad(*builder, pos_ptr); + llvm::Value* pos = llvm_utils->CreateLoad(pos_ptr); llvm::Value* el_dest = llvm_utils->list_api->read_item( new_el_list, pos, false, *module, true); llvm_utils->deepcopy(el, el_dest, el_asr_type, module, name2memidx); @@ -6438,8 +6312,9 @@ namespace LCompilers { // end llvm_utils->start_new_block(loopend); - set_free(set, module, el_asr_type); - LLVM::CreateStore(*builder, LLVM::CreateLoad(*builder, new_el_list), el_list); + llvm_utils->list_api->free_data(el_list, *module); + LLVM::lfortran_free(context, *module, *builder, el_mask); + LLVM::CreateStore(*builder, llvm_utils->CreateLoad(new_el_list), el_list); LLVM::CreateStore(*builder, new_el_mask, get_pointer_to_mask(set)); } @@ -6464,31 +6339,29 @@ namespace LCompilers { * } * */ - - get_builder0() - old_capacity = builder0.CreateAlloca(llvm::Type::getInt32Ty(context), nullptr); - old_occupancy = builder0.CreateAlloca(llvm::Type::getInt32Ty(context), nullptr); - old_number_of_buckets_filled = builder0.CreateAlloca(llvm::Type::getInt32Ty(context), nullptr); - idx_ptr = builder0.CreateAlloca(llvm::Type::getInt32Ty(context), nullptr); - old_elems = builder0.CreateAlloca(llvm::Type::getInt8PtrTy(context), nullptr); - old_el_mask = builder0.CreateAlloca(llvm::Type::getInt8PtrTy(context), nullptr); + old_capacity = llvm_utils->CreateAlloca(llvm::Type::getInt32Ty(context)); + old_occupancy = llvm_utils->CreateAlloca(llvm::Type::getInt32Ty(context)); + old_number_of_buckets_filled = llvm_utils->CreateAlloca(llvm::Type::getInt32Ty(context)); + idx_ptr = llvm_utils->CreateAlloca(llvm::Type::getInt32Ty(context)); + old_elems = llvm_utils->CreateAlloca(llvm::Type::getInt8Ty(context)->getPointerTo()); + old_el_mask = llvm_utils->CreateAlloca(llvm::Type::getInt8Ty(context)->getPointerTo()); llvm::Value* capacity_ptr = get_pointer_to_capacity(set); llvm::Value* occupancy_ptr = get_pointer_to_occupancy(set); llvm::Value* number_of_buckets_filled_ptr = get_pointer_to_number_of_filled_buckets(set); - llvm::Value* old_capacity_value = LLVM::CreateLoad(*builder, capacity_ptr); + llvm::Value* old_capacity_value = llvm_utils->CreateLoad(capacity_ptr); LLVM::CreateStore(*builder, old_capacity_value, old_capacity); LLVM::CreateStore(*builder, - LLVM::CreateLoad(*builder, occupancy_ptr), + llvm_utils->CreateLoad(occupancy_ptr), old_occupancy ); LLVM::CreateStore(*builder, - LLVM::CreateLoad(*builder, number_of_buckets_filled_ptr), + llvm_utils->CreateLoad(number_of_buckets_filled_ptr), old_number_of_buckets_filled ); - llvm::Value* old_el_mask_value = LLVM::CreateLoad(*builder, get_pointer_to_mask(set)); - llvm::Value* old_elems_value = LLVM::CreateLoad(*builder, get_pointer_to_elems(set)); - old_elems_value = builder->CreateBitCast(old_elems_value, llvm::Type::getInt8PtrTy(context)); + llvm::Value* old_el_mask_value = llvm_utils->CreateLoad(get_pointer_to_mask(set)); + llvm::Value* old_elems_value = llvm_utils->CreateLoad(get_pointer_to_elems(set)); + old_elems_value = builder->CreateBitCast(old_elems_value, llvm::Type::getInt8Ty(context)->getPointerTo()); LLVM::CreateStore(*builder, old_el_mask_value, old_el_mask); LLVM::CreateStore(*builder, old_elems_value, old_elems); @@ -6503,16 +6376,16 @@ namespace LCompilers { llvm::BasicBlock *thenBB_rehash = llvm::BasicBlock::Create(context, "then", fn); llvm::BasicBlock *elseBB_rehash = llvm::BasicBlock::Create(context, "else"); llvm::BasicBlock *mergeBB_rehash = llvm::BasicBlock::Create(context, "ifcont"); - llvm::Value* rehash_flag = LLVM::CreateLoad(*builder, get_pointer_to_rehash_flag(set)); + llvm::Value* rehash_flag = llvm_utils->CreateLoad(get_pointer_to_rehash_flag(set)); builder->CreateCondBr(rehash_flag, thenBB_rehash, elseBB_rehash); builder->SetInsertPoint(thenBB_rehash); - old_elems_value = LLVM::CreateLoad(*builder, old_elems); + old_elems_value = llvm_utils->CreateLoad(old_elems); old_elems_value = builder->CreateBitCast(old_elems_value, typecode2elstruct[ASRUtils::get_type_code(el_asr_type)]->getPointerTo()); - old_el_mask_value = LLVM::CreateLoad(*builder, old_el_mask); - old_capacity_value = LLVM::CreateLoad(*builder, old_capacity); - capacity = LLVM::CreateLoad(*builder, get_pointer_to_capacity(set)); + old_el_mask_value = llvm_utils->CreateLoad(old_el_mask); + old_capacity_value = llvm_utils->CreateLoad(old_capacity); + capacity = llvm_utils->CreateLoad(get_pointer_to_capacity(set)); LLVM::CreateStore(*builder, llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), llvm::APInt(32, 0)), idx_ptr); llvm::BasicBlock *loophead = llvm::BasicBlock::Create(context, "loop.head"); llvm::BasicBlock *loopbody = llvm::BasicBlock::Create(context, "loop.body"); @@ -6523,15 +6396,15 @@ namespace LCompilers { { llvm::Value *cond = builder->CreateICmpSGT( old_capacity_value, - LLVM::CreateLoad(*builder, idx_ptr)); + llvm_utils->CreateLoad(idx_ptr)); builder->CreateCondBr(cond, loopbody, loopend); } // body llvm_utils->start_new_block(loopbody); { - llvm::Value* itr = LLVM::CreateLoad(*builder, idx_ptr); - llvm::Value* el_mask_value = LLVM::CreateLoad(*builder, + llvm::Value* itr = llvm_utils->CreateLoad(idx_ptr); + llvm::Value* el_mask_value = llvm_utils->CreateLoad( llvm_utils->create_ptr_gep(old_el_mask_value, itr)); llvm::Value* is_el_set = builder->CreateICmpEQ(el_mask_value, llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), llvm::APInt(8, 1))); @@ -6551,33 +6424,30 @@ namespace LCompilers { // end llvm_utils->start_new_block(loopend); - - free_data(module, el_asr_type, old_capacity_value, old_elems_value, old_el_mask_value); - builder->CreateBr(mergeBB_rehash); llvm_utils->start_new_block(elseBB_rehash); { LLVM::CreateStore(*builder, - LLVM::CreateLoad(*builder, old_capacity), + llvm_utils->CreateLoad(old_capacity), get_pointer_to_capacity(set) ); LLVM::CreateStore(*builder, - LLVM::CreateLoad(*builder, old_occupancy), + llvm_utils->CreateLoad(old_occupancy), get_pointer_to_occupancy(set) ); LLVM::CreateStore(*builder, - LLVM::CreateLoad(*builder, old_number_of_buckets_filled), + llvm_utils->CreateLoad(old_number_of_buckets_filled), get_pointer_to_number_of_filled_buckets(set) ); LLVM::CreateStore(*builder, builder->CreateBitCast( - LLVM::CreateLoad(*builder, old_elems), + llvm_utils->CreateLoad(old_elems), typecode2elstruct[ASRUtils::get_type_code(el_asr_type)]->getPointerTo() ), get_pointer_to_elems(set) ); LLVM::CreateStore(*builder, - LLVM::CreateLoad(*builder, old_el_mask), + llvm_utils->CreateLoad(old_el_mask), get_pointer_to_mask(set) ); } @@ -6598,12 +6468,11 @@ namespace LCompilers { * */ - get_builder0() - src_itr = builder0.CreateAlloca(llvm::Type::getInt8PtrTy(context), nullptr); + src_itr = llvm_utils->CreateAlloca(llvm::Type::getInt8Ty(context)->getPointerTo()); llvm::Type* el_struct_type = typecode2elstruct[ASRUtils::get_type_code(m_el_type)]->getPointerTo(); LLVM::CreateStore(*builder, - builder->CreateBitCast(el_ll, llvm::Type::getInt8PtrTy(context)), + builder->CreateBitCast(el_ll, llvm::Type::getInt8Ty(context)->getPointerTo()), src_itr); llvm::BasicBlock *loophead = llvm::BasicBlock::Create(context, "loop.head"); llvm::BasicBlock *loopbody = llvm::BasicBlock::Create(context, "loop.body"); @@ -6612,8 +6481,8 @@ namespace LCompilers { llvm_utils->start_new_block(loophead); { llvm::Value *cond = builder->CreateICmpNE( - LLVM::CreateLoad(*builder, src_itr), - llvm::ConstantPointerNull::get(llvm::Type::getInt8PtrTy(context)) + llvm_utils->CreateLoad(src_itr), + llvm::ConstantPointerNull::get(llvm::Type::getInt8Ty(context)->getPointerTo()) ); builder->CreateCondBr(cond, loopbody, loopend); } @@ -6621,19 +6490,19 @@ namespace LCompilers { // body llvm_utils->start_new_block(loopbody); { - llvm::Value* curr_src = builder->CreateBitCast(LLVM::CreateLoad(*builder, src_itr), + llvm::Value* curr_src = builder->CreateBitCast(llvm_utils->CreateLoad(src_itr), el_struct_type); llvm::Value* src_el_ptr = llvm_utils->create_gep(curr_src, 0); llvm::Value* src_el = src_el_ptr; if( !LLVM::is_llvm_struct(m_el_type) ) { - src_el = LLVM::CreateLoad(*builder, src_el_ptr); + src_el = llvm_utils->CreateLoad(src_el_ptr); } llvm::Value* el_hash = get_el_hash(capacity, src_el, m_el_type, *module); resolve_collision_for_write( set, el_hash, src_el, module, m_el_type, name2memidx); - llvm::Value* src_next_ptr = LLVM::CreateLoad(*builder, llvm_utils->create_gep(curr_src, 1)); + llvm::Value* src_next_ptr = llvm_utils->CreateLoad(llvm_utils->create_gep(curr_src, 1)); LLVM::CreateStore(*builder, src_next_ptr, src_itr); } @@ -6658,8 +6527,8 @@ namespace LCompilers { * */ - llvm::Value* occupancy = LLVM::CreateLoad(*builder, get_pointer_to_occupancy(set)); - llvm::Value* capacity = LLVM::CreateLoad(*builder, get_pointer_to_capacity(set)); + llvm::Value* occupancy = llvm_utils->CreateLoad(get_pointer_to_occupancy(set)); + llvm::Value* capacity = llvm_utils->CreateLoad(get_pointer_to_capacity(set)); // Threshold hash is chosen from https://en.wikipedia.org/wiki/Hash_table#Load_factor // occupancy / capacity >= 0.6 is same as 5 * occupancy >= 3 * capacity llvm::Value* occupancy_times_5 = builder->CreateMul(occupancy, llvm::ConstantInt::get( @@ -6684,9 +6553,9 @@ namespace LCompilers { * } * */ - llvm::Value* occupancy = LLVM::CreateLoad(*builder, get_pointer_to_occupancy(set)); - llvm::Value* buckets_filled = LLVM::CreateLoad(*builder, get_pointer_to_number_of_filled_buckets(set)); - llvm::Value* rehash_condition = LLVM::CreateLoad(*builder, get_pointer_to_rehash_flag(set)); + llvm::Value* occupancy = llvm_utils->CreateLoad(get_pointer_to_occupancy(set)); + llvm::Value* buckets_filled = llvm_utils->CreateLoad(get_pointer_to_number_of_filled_buckets(set)); + llvm::Value* rehash_condition = llvm_utils->CreateLoad(get_pointer_to_rehash_flag(set)); llvm::Value* buckets_filled_times_2 = builder->CreateMul(buckets_filled, llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), llvm::APInt(32, 2))); rehash_condition = builder->CreateAnd(rehash_condition, @@ -6701,16 +6570,15 @@ namespace LCompilers { llvm::Module* module, ASR::ttype_t* el_asr_type, std::map>& name2memidx) { rehash_all_at_once_if_needed(set, module, el_asr_type, name2memidx); - llvm::Value* current_capacity = LLVM::CreateLoad(*builder, get_pointer_to_capacity(set)); + llvm::Value* current_capacity = llvm_utils->CreateLoad(get_pointer_to_capacity(set)); llvm::Value* el_hash = get_el_hash(current_capacity, el, el_asr_type, *module); this->resolve_collision_for_write(set, el_hash, el, module, el_asr_type, name2memidx); - rehash_all_at_once_if_needed(set, module, el_asr_type, name2memidx); } - llvm::Value* LLVMSetLinearProbing::resolve_collision_for_read_with_bound_check( + void LLVMSetLinearProbing::resolve_collision_for_read_with_bound_check( llvm::Value* set, llvm::Value* el_hash, llvm::Value* el, - llvm::Module& module, ASR::ttype_t* el_asr_type, bool throw_key_error, bool check_if_exists) { + llvm::Module& module, ASR::ttype_t* el_asr_type) { /** * C++ equivalent: @@ -6736,24 +6604,18 @@ namespace LCompilers { * } * */ - - get_builder0() - pos_ptr = builder0.CreateAlloca(llvm::Type::getInt32Ty(context), nullptr); llvm::Value* el_list = get_el_list(set); - llvm::Value* el_mask = LLVM::CreateLoad(*builder, get_pointer_to_mask(set)); - llvm::Value* capacity = LLVM::CreateLoad(*builder, get_pointer_to_capacity(set)); + llvm::Value* el_mask = llvm_utils->CreateLoad(get_pointer_to_mask(set)); + llvm::Value* capacity = llvm_utils->CreateLoad(get_pointer_to_capacity(set)); + pos_ptr = llvm_utils->CreateAlloca(llvm::Type::getInt32Ty(context)); llvm::Function *fn = builder->GetInsertBlock()->getParent(); - std::string s = check_if_exists ? "qq" : "pp"; - llvm::BasicBlock *thenBB = llvm::BasicBlock::Create(context, "then"+s, fn); - llvm::BasicBlock *elseBB = llvm::BasicBlock::Create(context, "else"+s); - llvm::BasicBlock *mergeBB = llvm::BasicBlock::Create(context, "ifcont"+s); - llvm::Value* el_mask_value = LLVM::CreateLoad(*builder, + llvm::BasicBlock *thenBB = llvm::BasicBlock::Create(context, "then", fn); + llvm::BasicBlock *elseBB = llvm::BasicBlock::Create(context, "else"); + llvm::BasicBlock *mergeBB = llvm::BasicBlock::Create(context, "ifcont"); + llvm::Value* el_mask_value = llvm_utils->CreateLoad( llvm_utils->create_ptr_gep(el_mask, el_hash)); llvm::Value* is_prob_not_needed = builder->CreateICmpEQ(el_mask_value, llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), llvm::APInt(8, 1))); - llvm::AllocaInst *flag_ptr = builder0.CreateAlloca(llvm::Type::getInt1Ty(context), nullptr); - LLVM::CreateStore(*builder, llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), 0), pos_ptr); - LLVM::CreateStore(*builder, llvm::ConstantInt::get(llvm::Type::getInt1Ty(context), 0), flag_ptr); builder->CreateCondBr(is_prob_not_needed, thenBB, elseBB); builder->SetInsertPoint(thenBB); { @@ -6766,20 +6628,15 @@ namespace LCompilers { llvm_utils->create_if_else(is_el_matching, [=]() { LLVM::CreateStore(*builder, el_hash, pos_ptr); }, [&]() { - if (check_if_exists) { - LLVM::CreateStore(*builder, llvm::ConstantInt::get(llvm::Type::getInt1Ty(context), 1), flag_ptr); - } else { - if (throw_key_error) { - std::string message = "The set does not contain the specified element"; - llvm::Value *fmt_ptr = builder->CreateGlobalStringPtr("KeyError: %s\n"); - llvm::Value *fmt_ptr2 = builder->CreateGlobalStringPtr(message); - print_error(context, module, *builder, {fmt_ptr, fmt_ptr2}); - int exit_code_int = 1; - llvm::Value *exit_code = llvm::ConstantInt::get(context, - llvm::APInt(32, exit_code_int)); - exit(context, module, *builder, exit_code); - } - }}); + std::string message = "The set does not contain the specified element"; + llvm::Value *fmt_ptr = builder->CreateGlobalStringPtr("KeyError: %s\n"); + llvm::Value *fmt_ptr2 = builder->CreateGlobalStringPtr(message); + print_error(context, module, *builder, {fmt_ptr, fmt_ptr2}); + int exit_code_int = 1; + llvm::Value *exit_code = llvm::ConstantInt::get(context, + llvm::APInt(32, exit_code_int)); + exit(context, module, *builder, exit_code); + }); } builder->CreateBr(mergeBB); llvm_utils->start_new_block(elseBB); @@ -6788,51 +6645,27 @@ namespace LCompilers { module, el_asr_type, true); } llvm_utils->start_new_block(mergeBB); - - llvm::Value* pos = LLVM::CreateLoad(*builder, pos_ptr); - llvm::Value* pos_mask_value = LLVM::CreateLoad(*builder, - llvm_utils->create_ptr_gep(el_mask, pos)); - llvm::Value *flag = builder->CreateOr( - builder->CreateICmpEQ(pos_mask_value, - llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), llvm::APInt(8, 0))), - LLVM::CreateLoad(*builder, flag_ptr)); - llvm::AllocaInst *is_el_matching_ptr = builder0.CreateAlloca(llvm::Type::getInt1Ty(context), nullptr); - - llvm_utils->create_if_else(flag, [&](){ - LLVM::CreateStore(*builder, llvm::ConstantInt::get(llvm::Type::getInt1Ty(context), 0), is_el_matching_ptr); - }, [&](){ + llvm::Value* pos = llvm_utils->CreateLoad(pos_ptr); // Check if the actual element is present or not - llvm::Value* item = llvm_utils->list_api->read_item(el_list, pos, false, module, - LLVM::is_llvm_struct(el_asr_type)) ; - llvm::Value *iseq =llvm_utils->is_equal_by_value(el, - item, module, el_asr_type) ; - LLVM::CreateStore(*builder, iseq, is_el_matching_ptr); - }); - - llvm::Value *is_el_matching = LLVM::CreateLoad(*builder, is_el_matching_ptr); - if (check_if_exists) { - return is_el_matching; - } + llvm::Value* is_el_matching = llvm_utils->is_equal_by_value(el, + llvm_utils->list_api->read_item(el_list, pos, false, module, + LLVM::is_llvm_struct(el_asr_type)), module, el_asr_type); llvm_utils->create_if_else(is_el_matching, []() {}, [&]() { - if (throw_key_error) { - std::string message = "The set does not contain the specified element"; - llvm::Value *fmt_ptr = builder->CreateGlobalStringPtr("KeyError: %s\n"); - llvm::Value *fmt_ptr2 = builder->CreateGlobalStringPtr(message); - print_error(context, module, *builder, {fmt_ptr, fmt_ptr2}); - int exit_code_int = 1; - llvm::Value *exit_code = llvm::ConstantInt::get(context, - llvm::APInt(32, exit_code_int)); - exit(context, module, *builder, exit_code); - } + std::string message = "The set does not contain the specified element"; + llvm::Value *fmt_ptr = builder->CreateGlobalStringPtr("KeyError: %s\n"); + llvm::Value *fmt_ptr2 = builder->CreateGlobalStringPtr(message); + print_error(context, module, *builder, {fmt_ptr, fmt_ptr2}); + int exit_code_int = 1; + llvm::Value *exit_code = llvm::ConstantInt::get(context, + llvm::APInt(32, exit_code_int)); + exit(context, module, *builder, exit_code); }); - - return nullptr; } - llvm::Value* LLVMSetSeparateChaining::resolve_collision_for_read_with_bound_check( + void LLVMSetSeparateChaining::resolve_collision_for_read_with_bound_check( llvm::Value* set, llvm::Value* el_hash, llvm::Value* el, - llvm::Module& module, ASR::ttype_t* el_asr_type, bool throw_key_error, bool check_if_exists) { + llvm::Module& module, ASR::ttype_t* el_asr_type) { /** * C++ equivalent: * @@ -6843,45 +6676,37 @@ namespace LCompilers { * } * */ - llvm::Value* elems = LLVM::CreateLoad(*builder, get_pointer_to_elems(set)); + llvm::Value* elems = llvm_utils->CreateLoad(get_pointer_to_elems(set)); llvm::Value* el_linked_list = llvm_utils->create_ptr_gep(elems, el_hash); - llvm::Value* el_mask = LLVM::CreateLoad(*builder, get_pointer_to_mask(set)); + llvm::Value* el_mask = llvm_utils->CreateLoad(get_pointer_to_mask(set)); std::string el_type_code = ASRUtils::get_type_code(el_asr_type); llvm::Type* el_struct_type = typecode2elstruct[el_type_code]; this->resolve_collision(el_hash, el, el_linked_list, el_struct_type, el_mask, module, el_asr_type); - llvm::Value* el_mask_value = LLVM::CreateLoad(*builder, + llvm::Value* el_mask_value = llvm_utils->CreateLoad( llvm_utils->create_ptr_gep(el_mask, el_hash)); llvm::Value* does_el_exist = builder->CreateICmpEQ(el_mask_value, llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), llvm::APInt(8, 1))); does_el_exist = builder->CreateAnd(does_el_exist, - builder->CreateICmpNE(LLVM::CreateLoad(*builder, chain_itr), - llvm::ConstantPointerNull::get(llvm::Type::getInt8PtrTy(context))) + builder->CreateICmpNE(llvm_utils->CreateLoad(chain_itr), + llvm::ConstantPointerNull::get(llvm::Type::getInt8Ty(context)->getPointerTo())) ); - if (check_if_exists) { - return does_el_exist; - } - llvm_utils->create_if_else(does_el_exist, []() {}, [&]() { - if (throw_key_error) { - std::string message = "The set does not contain the specified element"; - llvm::Value *fmt_ptr = builder->CreateGlobalStringPtr("KeyError: %s\n"); - llvm::Value *fmt_ptr2 = builder->CreateGlobalStringPtr(message); - print_error(context, module, *builder, {fmt_ptr, fmt_ptr2}); - int exit_code_int = 1; - llvm::Value *exit_code = llvm::ConstantInt::get(context, - llvm::APInt(32, exit_code_int)); - exit(context, module, *builder, exit_code); - } + std::string message = "The set does not contain the specified element"; + llvm::Value *fmt_ptr = builder->CreateGlobalStringPtr("KeyError: %s\n"); + llvm::Value *fmt_ptr2 = builder->CreateGlobalStringPtr(message); + print_error(context, module, *builder, {fmt_ptr, fmt_ptr2}); + int exit_code_int = 1; + llvm::Value *exit_code = llvm::ConstantInt::get(context, + llvm::APInt(32, exit_code_int)); + exit(context, module, *builder, exit_code); }); - - return nullptr; } void LLVMSetLinearProbing::remove_item( llvm::Value* set, llvm::Value* el, - llvm::Module& module, ASR::ttype_t* el_asr_type, bool throw_key_error) { + llvm::Module& module, ASR::ttype_t* el_asr_type) { /** * C++ equivalent: * @@ -6889,17 +6714,17 @@ namespace LCompilers { * el_mask[pos] = 3; // tombstone marker * occupancy -= 1; */ - llvm::Value* current_capacity = LLVM::CreateLoad(*builder, get_pointer_to_capacity(set)); + llvm::Value* current_capacity = llvm_utils->CreateLoad(get_pointer_to_capacity(set)); llvm::Value* el_hash = get_el_hash(current_capacity, el, el_asr_type, module); - this->resolve_collision_for_read_with_bound_check(set, el_hash, el, module, el_asr_type, throw_key_error); - llvm::Value* pos = LLVM::CreateLoad(*builder, pos_ptr); - llvm::Value* el_mask = LLVM::CreateLoad(*builder, get_pointer_to_mask(set)); + this->resolve_collision_for_read_with_bound_check(set, el_hash, el, module, el_asr_type); + llvm::Value* pos = llvm_utils->CreateLoad(pos_ptr); + llvm::Value* el_mask = llvm_utils->CreateLoad(get_pointer_to_mask(set)); llvm::Value* el_mask_i = llvm_utils->create_ptr_gep(el_mask, pos); llvm::Value* tombstone_marker = llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), llvm::APInt(8, 3)); LLVM::CreateStore(*builder, tombstone_marker, el_mask_i); llvm::Value* occupancy_ptr = get_pointer_to_occupancy(set); - llvm::Value* occupancy = LLVM::CreateLoad(*builder, occupancy_ptr); + llvm::Value* occupancy = llvm_utils->CreateLoad(occupancy_ptr); occupancy = builder->CreateSub(occupancy, llvm::ConstantInt::get( llvm::Type::getInt32Ty(context), llvm::APInt(32, 1))); LLVM::CreateStore(*builder, occupancy, occupancy_ptr); @@ -6907,7 +6732,7 @@ namespace LCompilers { void LLVMSetSeparateChaining::remove_item( llvm::Value* set, llvm::Value* el, - llvm::Module& module, ASR::ttype_t* el_asr_type, bool throw_key_error) { + llvm::Module& module, ASR::ttype_t* el_asr_type) { /** * C++ equivalent: * @@ -6927,11 +6752,11 @@ namespace LCompilers { * */ - llvm::Value* current_capacity = LLVM::CreateLoad(*builder, get_pointer_to_capacity(set)); + llvm::Value* current_capacity = llvm_utils->CreateLoad(get_pointer_to_capacity(set)); llvm::Value* el_hash = get_el_hash(current_capacity, el, el_asr_type, module); - this->resolve_collision_for_read_with_bound_check(set, el_hash, el, module, el_asr_type, throw_key_error); - llvm::Value* prev = LLVM::CreateLoad(*builder, chain_itr_prev); - llvm::Value* found = LLVM::CreateLoad(*builder, chain_itr); + this->resolve_collision_for_read_with_bound_check(set, el_hash, el, module, el_asr_type); + llvm::Value* prev = llvm_utils->CreateLoad(chain_itr_prev); + llvm::Value* found = llvm_utils->CreateLoad(chain_itr); llvm::Function *fn = builder->GetInsertBlock()->getParent(); llvm::BasicBlock *thenBB = llvm::BasicBlock::Create(context, "then", fn); @@ -6939,28 +6764,28 @@ namespace LCompilers { llvm::BasicBlock *mergeBB = llvm::BasicBlock::Create(context, "ifcont"); builder->CreateCondBr( - builder->CreateICmpNE(prev, llvm::ConstantPointerNull::get(llvm::Type::getInt8PtrTy(context))), + builder->CreateICmpNE(prev, llvm::ConstantPointerNull::get(llvm::Type::getInt8Ty(context)->getPointerTo())), thenBB, elseBB ); builder->SetInsertPoint(thenBB); { llvm::Type* el_struct_type = typecode2elstruct[ASRUtils::get_type_code(el_asr_type)]; found = builder->CreateBitCast(found, el_struct_type->getPointerTo()); - llvm::Value* found_next = LLVM::CreateLoad(*builder, llvm_utils->create_gep(found, 1)); + llvm::Value* found_next = llvm_utils->CreateLoad(llvm_utils->create_gep(found, 1)); prev = builder->CreateBitCast(prev, el_struct_type->getPointerTo()); LLVM::CreateStore(*builder, found_next, llvm_utils->create_gep(prev, 1)); } builder->CreateBr(mergeBB); llvm_utils->start_new_block(elseBB); { - llvm::Value* el_mask = LLVM::CreateLoad(*builder, get_pointer_to_mask(set)); + llvm::Value* el_mask = llvm_utils->CreateLoad(get_pointer_to_mask(set)); LLVM::CreateStore( *builder, llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), llvm::APInt(8, 0)), llvm_utils->create_ptr_gep(el_mask, el_hash) ); llvm::Value* num_buckets_filled_ptr = get_pointer_to_number_of_filled_buckets(set); - llvm::Value* num_buckets_filled = LLVM::CreateLoad(*builder, num_buckets_filled_ptr); + llvm::Value* num_buckets_filled = llvm_utils->CreateLoad(num_buckets_filled_ptr); num_buckets_filled = builder->CreateSub(num_buckets_filled, llvm::ConstantInt::get( llvm::Type::getInt32Ty(context), llvm::APInt(32, 1))); LLVM::CreateStore(*builder, num_buckets_filled, num_buckets_filled_ptr); @@ -6968,192 +6793,18 @@ namespace LCompilers { llvm_utils->start_new_block(mergeBB); llvm::Value* occupancy_ptr = get_pointer_to_occupancy(set); - llvm::Value* occupancy = LLVM::CreateLoad(*builder, occupancy_ptr); + llvm::Value* occupancy = llvm_utils->CreateLoad(occupancy_ptr); occupancy = builder->CreateSub(occupancy, llvm::ConstantInt::get( llvm::Type::getInt32Ty(context), llvm::APInt(32, 1))); LLVM::CreateStore(*builder, occupancy, occupancy_ptr); } - llvm::Value* LLVMSetLinearProbing::pop_item(llvm::Value *set, llvm::Module &module, - ASR::ttype_t *el_asr_type) { - llvm::Value* current_capacity = LLVM::CreateLoad(*builder, get_pointer_to_capacity(set)); - - llvm::Value* occupancy_ptr = get_pointer_to_occupancy(set); - llvm::Value* occupancy = LLVM::CreateLoad(*builder, occupancy_ptr); - llvm_utils->create_if_else(builder->CreateICmpNE(occupancy, llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), 0)), [=]() {}, [&]() { - std::string message = "The set is empty"; - llvm::Value *fmt_ptr = builder->CreateGlobalStringPtr("KeyError: %s\n"); - llvm::Value *fmt_ptr2 = builder->CreateGlobalStringPtr(message); - print_error(context, module, *builder, {fmt_ptr, fmt_ptr2}); - int exit_code_int = 1; - llvm::Value *exit_code = llvm::ConstantInt::get(context, - llvm::APInt(32, exit_code_int)); - exit(context, module, *builder, exit_code); - }); - get_builder0(); - llvm::AllocaInst *pos_ptr = builder0.CreateAlloca(llvm::Type::getInt32Ty(context), nullptr); - LLVM::CreateStore(*builder, llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), 0), pos_ptr); - - llvm::BasicBlock *loophead = llvm::BasicBlock::Create(context, "loop.head"); - llvm::BasicBlock *loopbody = llvm::BasicBlock::Create(context, "loop.body"); - llvm::BasicBlock *loopend = llvm::BasicBlock::Create(context, "loop.end"); - - llvm::Value *el_mask = LLVM::CreateLoad(*builder, get_pointer_to_mask(set)); - llvm::Value *el_list = get_el_list(set); - - // head - llvm_utils->start_new_block(loophead); - { - llvm::Value *cond = builder->CreateICmpSGT( - current_capacity, - LLVM::CreateLoad(*builder, pos_ptr) - ); - builder->CreateCondBr(cond, loopbody, loopend); - } - - // body - llvm_utils->start_new_block(loopbody); - { - llvm::Value* pos = LLVM::CreateLoad(*builder, pos_ptr); - llvm::Value* el_mask_value = LLVM::CreateLoad(*builder, - llvm_utils->create_ptr_gep(el_mask, pos)); - llvm::Value* is_el_skip = builder->CreateICmpEQ(el_mask_value, - llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), llvm::APInt(8, 3))); - llvm::Value* is_el_set = builder->CreateICmpNE(el_mask_value, - llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), llvm::APInt(8, 0))); - llvm::Value* is_el = builder->CreateAnd(is_el_set, - builder->CreateNot(is_el_skip)); - - llvm_utils->create_if_else(is_el, [&]() { - llvm::Value* el_mask_i = llvm_utils->create_ptr_gep(el_mask, pos); - llvm::Value* tombstone_marker = llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), llvm::APInt(8, 3)); - LLVM::CreateStore(*builder, tombstone_marker, el_mask_i); - occupancy = builder->CreateSub(occupancy, llvm::ConstantInt::get( - llvm::Type::getInt32Ty(context), llvm::APInt(32, 1))); - LLVM::CreateStore(*builder, occupancy, occupancy_ptr); - }, [=]() { - LLVM::CreateStore(*builder, builder->CreateAdd(pos, llvm::ConstantInt::get( - llvm::Type::getInt32Ty(context), llvm::APInt(32, 1))), pos_ptr); - }); - builder->CreateCondBr(is_el, loopend, loophead); - } - - // end - llvm_utils->start_new_block(loopend); - - llvm::Value* pos = LLVM::CreateLoad(*builder, pos_ptr); - llvm::Value *el = llvm_utils->list_api->read_item(el_list, pos, false, module, - LLVM::is_llvm_struct(el_asr_type)); - return el; - } - - llvm::Value* LLVMSetSeparateChaining::pop_item(llvm::Value *set, llvm::Module &module, - ASR::ttype_t *el_asr_type) { - llvm::Value* current_capacity = LLVM::CreateLoad(*builder, get_pointer_to_capacity(set)); - llvm::Value* occupancy_ptr = get_pointer_to_occupancy(set); - llvm::Value* occupancy = LLVM::CreateLoad(*builder, occupancy_ptr); - llvm_utils->create_if_else(builder->CreateICmpNE(occupancy, llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), 0)), []() {}, [&]() { - std::string message = "The set is empty"; - llvm::Value *fmt_ptr = builder->CreateGlobalStringPtr("KeyError: %s\n"); - llvm::Value *fmt_ptr2 = builder->CreateGlobalStringPtr(message); - print_error(context, module, *builder, {fmt_ptr, fmt_ptr2}); - int exit_code_int = 1; - llvm::Value *exit_code = llvm::ConstantInt::get(context, - llvm::APInt(32, exit_code_int)); - exit(context, module, *builder, exit_code); - }); - - get_builder0(); - llvm::AllocaInst* chain_itr = builder0.CreateAlloca(llvm::Type::getInt8PtrTy(context), nullptr); - llvm::AllocaInst* found_ptr = builder0.CreateAlloca(llvm::Type::getInt8PtrTy(context), nullptr); - llvm::AllocaInst* pos = builder0.CreateAlloca(llvm::Type::getInt32Ty(context), nullptr); - LLVM::CreateStore(*builder, - llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), 0), pos); - - llvm::BasicBlock *loophead = llvm::BasicBlock::Create(context, "loop.head"); - llvm::BasicBlock *loopbody = llvm::BasicBlock::Create(context, "loop.body"); - llvm::BasicBlock *loopend = llvm::BasicBlock::Create(context, "loop.end"); - - llvm::Value* elems = LLVM::CreateLoad(*builder, get_pointer_to_elems(set)); - llvm::Value* el_mask = LLVM::CreateLoad(*builder, get_pointer_to_mask(set)); - - // head - llvm_utils->start_new_block(loophead); - { - llvm::Value *cond = builder->CreateICmpSGT( - current_capacity, - LLVM::CreateLoad(*builder, pos_ptr) - ); - builder->CreateCondBr(cond, loopbody, loopend); - } - - // body - llvm_utils->start_new_block(loopbody); - { - llvm::Value *el_mask_value = LLVM::CreateLoad(*builder, - llvm_utils->create_ptr_gep(el_mask, LLVM::CreateLoad(*builder, pos))); - llvm::Value* el_linked_list = llvm_utils->create_ptr_gep(elems, LLVM::CreateLoad(*builder, pos)); - - llvm::Value *is_el = builder->CreateICmpEQ(el_mask_value, - llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), llvm::APInt(8, 1))); - llvm_utils->create_if_else(is_el, [&]() { - llvm::Value* el_ll_i8 = builder->CreateBitCast(el_linked_list, llvm::Type::getInt8PtrTy(context)); - LLVM::CreateStore(*builder, el_ll_i8, chain_itr); - llvm::Value* el_struct_i8 = LLVM::CreateLoad(*builder, chain_itr); - llvm::Type* el_struct_type = typecode2elstruct[ASRUtils::get_type_code(el_asr_type)]; - llvm::Value* el_struct = builder->CreateBitCast(el_struct_i8, el_struct_type->getPointerTo()); - llvm::Value* next_el_struct = LLVM::CreateLoad(*builder, llvm_utils->create_gep(el_struct, 1)); - llvm::Value *cond = builder->CreateICmpNE( - next_el_struct, - llvm::ConstantPointerNull::get(llvm::Type::getInt8PtrTy(context)) - ); - - llvm_utils->create_if_else(cond, [&](){ - llvm::Value *found = LLVM::CreateLoad(*builder, next_el_struct); - llvm::Value *prev = LLVM::CreateLoad(*builder, chain_itr); - found = builder->CreateBitCast(found, el_struct_type->getPointerTo()); - llvm::Value* found_next = LLVM::CreateLoad(*builder, llvm_utils->create_gep(found, 1)); - prev = builder->CreateBitCast(prev, el_struct_type->getPointerTo()); - LLVM::CreateStore(*builder, found_next, llvm_utils->create_gep(prev, 1)); - LLVM::CreateStore(*builder, found, found_ptr); - }, [&](){ - llvm::Value *found = LLVM::CreateLoad(*builder, chain_itr); - llvm::Type* el_struct_type = typecode2elstruct[ASRUtils::get_type_code(el_asr_type)]; - found = builder->CreateBitCast(found, el_struct_type->getPointerTo()); - LLVM::CreateStore(*builder, found, found_ptr); - LLVM::CreateStore( - *builder, - llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), llvm::APInt(8, 0)), - llvm_utils->create_ptr_gep(el_mask, LLVM::CreateLoad(*builder, pos)) - ); - llvm::Value* num_buckets_filled_ptr = get_pointer_to_number_of_filled_buckets(set); - llvm::Value* num_buckets_filled = LLVM::CreateLoad(*builder, num_buckets_filled_ptr); - num_buckets_filled = builder->CreateSub(num_buckets_filled, llvm::ConstantInt::get( - llvm::Type::getInt32Ty(context), llvm::APInt(32, 1))); - LLVM::CreateStore(*builder, num_buckets_filled, num_buckets_filled_ptr); - }); - }, [&]() { - }); - LLVM::CreateStore(*builder, builder->CreateAdd(pos, llvm::ConstantInt::get( - llvm::Type::getInt32Ty(context), llvm::APInt(32, 1))), pos_ptr); - builder->CreateCondBr(is_el, loopend, loophead); - } - - llvm::Value *el = llvm_utils->create_ptr_gep(LLVM::CreateLoad(*builder, pos_ptr), 0); - - if (LLVM::is_llvm_struct(el_asr_type)) { - return el; - } else { - return LLVM::CreateLoad(*builder, el); - } - } - void LLVMSetLinearProbing::set_deepcopy( llvm::Value* src, llvm::Value* dest, ASR::Set_t* set_type, llvm::Module* module, std::map>& name2memidx) { LCOMPILERS_ASSERT(src->getType() == dest->getType()); - llvm::Value* src_occupancy = LLVM::CreateLoad(*builder, get_pointer_to_occupancy(src)); + llvm::Value* src_occupancy = llvm_utils->CreateLoad(get_pointer_to_occupancy(src)); llvm::Value* dest_occupancy_ptr = get_pointer_to_occupancy(dest); LLVM::CreateStore(*builder, src_occupancy, dest_occupancy_ptr); @@ -7163,13 +6814,13 @@ namespace LCompilers { set_type->m_type, module, name2memidx); - llvm::Value* src_el_mask = LLVM::CreateLoad(*builder, get_pointer_to_mask(src)); + llvm::Value* src_el_mask = llvm_utils->CreateLoad(get_pointer_to_mask(src)); llvm::Value* dest_el_mask_ptr = get_pointer_to_mask(dest); llvm::DataLayout data_layout(module); size_t mask_size = data_layout.getTypeAllocSize(llvm::Type::getInt8Ty(context)); llvm::Value* llvm_mask_size = llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), llvm::APInt(32, mask_size)); - llvm::Value* src_capacity = LLVM::CreateLoad(*builder, get_pointer_to_capacity(src)); + llvm::Value* src_capacity = llvm_utils->CreateLoad(get_pointer_to_capacity(src)); llvm::Value* dest_el_mask = LLVM::lfortran_calloc(context, *module, *builder, src_capacity, llvm_mask_size); builder->CreateMemCpy(dest_el_mask, llvm::MaybeAlign(), src_el_mask, @@ -7181,11 +6832,11 @@ namespace LCompilers { llvm::Value* src, llvm::Value* dest, ASR::Set_t* set_type, llvm::Module* module, std::map>& name2memidx) { - llvm::Value* src_occupancy = LLVM::CreateLoad(*builder, get_pointer_to_occupancy(src)); - llvm::Value* src_filled_buckets = LLVM::CreateLoad(*builder, get_pointer_to_number_of_filled_buckets(src)); - llvm::Value* src_capacity = LLVM::CreateLoad(*builder, get_pointer_to_capacity(src)); - llvm::Value* src_el_mask = LLVM::CreateLoad(*builder, get_pointer_to_mask(src)); - llvm::Value* src_rehash_flag = LLVM::CreateLoad(*builder, get_pointer_to_rehash_flag(src)); + llvm::Value* src_occupancy = llvm_utils->CreateLoad(get_pointer_to_occupancy(src)); + llvm::Value* src_filled_buckets = llvm_utils->CreateLoad(get_pointer_to_number_of_filled_buckets(src)); + llvm::Value* src_capacity = llvm_utils->CreateLoad(get_pointer_to_capacity(src)); + llvm::Value* src_el_mask = llvm_utils->CreateLoad(get_pointer_to_mask(src)); + llvm::Value* src_rehash_flag = llvm_utils->CreateLoad(get_pointer_to_rehash_flag(src)); LLVM::CreateStore(*builder, src_occupancy, get_pointer_to_occupancy(dest)); LLVM::CreateStore(*builder, src_filled_buckets, get_pointer_to_number_of_filled_buckets(dest)); LLVM::CreateStore(*builder, src_capacity, get_pointer_to_capacity(dest)); @@ -7207,14 +6858,13 @@ namespace LCompilers { malloc_size = builder->CreateMul(malloc_size, llvm_el_struct_size); llvm::Value* dest_elems = LLVM::lfortran_malloc(context, *module, *builder, malloc_size); dest_elems = builder->CreateBitCast(dest_elems, el_struct_type->getPointerTo()); - get_builder0() - copy_itr = builder0.CreateAlloca(llvm::Type::getInt32Ty(context), nullptr); - next_ptr = builder0.CreateAlloca(llvm::Type::getInt32Ty(context), nullptr); + copy_itr = llvm_utils->CreateAlloca(llvm::Type::getInt32Ty(context)); + next_ptr = llvm_utils->CreateAlloca(llvm::Type::getInt32Ty(context)); llvm::Value* llvm_zero = llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), llvm::APInt(32, 0)); LLVM::CreateStore(*builder, llvm_zero, copy_itr); LLVM::CreateStore(*builder, src_capacity, next_ptr); - llvm::Value* src_elems = LLVM::CreateLoad(*builder, get_pointer_to_elems(src)); + llvm::Value* src_elems = llvm_utils->CreateLoad(get_pointer_to_elems(src)); llvm::BasicBlock *loophead = llvm::BasicBlock::Create(context, "loop.head"); llvm::BasicBlock *loopbody = llvm::BasicBlock::Create(context, "loop.body"); llvm::BasicBlock *loopend = llvm::BasicBlock::Create(context, "loop.end"); @@ -7224,15 +6874,15 @@ namespace LCompilers { { llvm::Value *cond = builder->CreateICmpSGT( src_capacity, - LLVM::CreateLoad(*builder, copy_itr)); + llvm_utils->CreateLoad(copy_itr)); builder->CreateCondBr(cond, loopbody, loopend); } // body llvm_utils->start_new_block(loopbody); { - llvm::Value* itr = LLVM::CreateLoad(*builder, copy_itr); - llvm::Value* el_mask_value = LLVM::CreateLoad(*builder, + llvm::Value* itr = llvm_utils->CreateLoad(copy_itr); + llvm::Value* el_mask_value = llvm_utils->CreateLoad( llvm_utils->create_ptr_gep(src_el_mask, itr)); LLVM::CreateStore(*builder, el_mask_value, llvm_utils->create_ptr_gep(dest_el_mask, itr)); @@ -7281,16 +6931,15 @@ namespace LCompilers { * } * */ - get_builder0() - src_itr = builder0.CreateAlloca(llvm::Type::getInt8PtrTy(context), nullptr); - dest_itr = builder0.CreateAlloca(llvm::Type::getInt8PtrTy(context), nullptr); + src_itr = llvm_utils->CreateAlloca(llvm::Type::getInt8Ty(context)->getPointerTo()); + dest_itr = llvm_utils->CreateAlloca(llvm::Type::getInt8Ty(context)->getPointerTo()); llvm::Type* el_struct_type = typecode2elstruct[ASRUtils::get_type_code(set_type->m_type)]->getPointerTo(); LLVM::CreateStore(*builder, - builder->CreateBitCast(srci, llvm::Type::getInt8PtrTy(context)), + builder->CreateBitCast(srci, llvm::Type::getInt8Ty(context)->getPointerTo()), src_itr); LLVM::CreateStore(*builder, - builder->CreateBitCast(desti, llvm::Type::getInt8PtrTy(context)), + builder->CreateBitCast(desti, llvm::Type::getInt8Ty(context)->getPointerTo()), dest_itr); llvm::BasicBlock *loophead = llvm::BasicBlock::Create(context, "loop.head"); llvm::BasicBlock *loopbody = llvm::BasicBlock::Create(context, "loop.body"); @@ -7299,8 +6948,8 @@ namespace LCompilers { llvm_utils->start_new_block(loophead); { llvm::Value *cond = builder->CreateICmpNE( - LLVM::CreateLoad(*builder, src_itr), - llvm::ConstantPointerNull::get(llvm::Type::getInt8PtrTy(context)) + llvm_utils->CreateLoad(src_itr), + llvm::ConstantPointerNull::get(llvm::Type::getInt8Ty(context)->getPointerTo()) ); builder->CreateCondBr(cond, loopbody, loopend); } @@ -7308,28 +6957,28 @@ namespace LCompilers { // body llvm_utils->start_new_block(loopbody); { - llvm::Value* curr_src = builder->CreateBitCast(LLVM::CreateLoad(*builder, src_itr), + llvm::Value* curr_src = builder->CreateBitCast(llvm_utils->CreateLoad(src_itr), el_struct_type); - llvm::Value* curr_dest = builder->CreateBitCast(LLVM::CreateLoad(*builder, dest_itr), + llvm::Value* curr_dest = builder->CreateBitCast(llvm_utils->CreateLoad(dest_itr), el_struct_type); llvm::Value* src_el_ptr = llvm_utils->create_gep(curr_src, 0); llvm::Value *src_el = src_el_ptr; if( !LLVM::is_llvm_struct(set_type->m_type) ) { - src_el = LLVM::CreateLoad(*builder, src_el_ptr); + src_el = llvm_utils->CreateLoad(src_el_ptr); } llvm::Value* dest_el_ptr = llvm_utils->create_gep(curr_dest, 0); llvm_utils->deepcopy(src_el, dest_el_ptr, set_type->m_type, module, name2memidx); - llvm::Value* src_next_ptr = LLVM::CreateLoad(*builder, llvm_utils->create_gep(curr_src, 1)); + llvm::Value* src_next_ptr = llvm_utils->CreateLoad(llvm_utils->create_gep(curr_src, 1)); llvm::Value* curr_dest_next_ptr = llvm_utils->create_gep(curr_dest, 1); LLVM::CreateStore(*builder, src_next_ptr, src_itr); llvm::Value* src_next_exists = builder->CreateICmpNE(src_next_ptr, - llvm::ConstantPointerNull::get(llvm::Type::getInt8PtrTy(context))); + llvm::ConstantPointerNull::get(llvm::Type::getInt8Ty(context)->getPointerTo())); llvm_utils->create_if_else(src_next_exists, [&]() { - llvm::Value* next_idx = LLVM::CreateLoad(*builder, next_ptr); + llvm::Value* next_idx = llvm_utils->CreateLoad(next_ptr); llvm::Value* dest_next_ptr = llvm_utils->create_ptr_gep(dest_elems, next_idx); - dest_next_ptr = builder->CreateBitCast(dest_next_ptr, llvm::Type::getInt8PtrTy(context)); + dest_next_ptr = builder->CreateBitCast(dest_next_ptr, llvm::Type::getInt8Ty(context)->getPointerTo()); LLVM::CreateStore(*builder, dest_next_ptr, curr_dest_next_ptr); LLVM::CreateStore(*builder, dest_next_ptr, dest_itr); next_idx = builder->CreateAdd(next_idx, llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), @@ -7337,7 +6986,7 @@ namespace LCompilers { LLVM::CreateStore(*builder, next_idx, next_ptr); }, [&]() { LLVM::CreateStore(*builder, - llvm::ConstantPointerNull::get(llvm::Type::getInt8PtrTy(context)), + llvm::ConstantPointerNull::get(llvm::Type::getInt8Ty(context)->getPointerTo()), curr_dest_next_ptr ); }); @@ -7349,129 +6998,8 @@ namespace LCompilers { llvm_utils->start_new_block(loopend); } - void LLVMSetLinearProbing::set_clear(llvm::Value* set, llvm::Module* module, ASR::ttype_t* el_asr_type) { - set_free(set, module, el_asr_type); - set_init(ASRUtils::get_type_code(el_asr_type), set, module, 0); - } - - void LLVMSetSeparateChaining::set_clear(llvm::Value* set, llvm::Module* module, ASR::ttype_t* el_asr_type) { - set_free(set, module, el_asr_type); - set_init_given_initial_capacity(ASRUtils::get_type_code(el_asr_type), set, module, 0); - } - - void LLVMSetLinearProbing::set_free(llvm::Value *set, llvm::Module *module, - ASR::ttype_t *el_asr_type) { - llvm::Value* el_list = get_el_list(set); - llvm_utils->list_api->free_data(el_list, el_asr_type, *module); - LLVM::lfortran_free(context, *module, *builder, LLVM::CreateLoad(*builder, get_pointer_to_mask(set))); - } - - void LLVMSetSeparateChaining::set_free(llvm::Value *set, llvm::Module *module, - ASR::ttype_t *el_asr_type) { - llvm::Value* el_mask = LLVM::CreateLoad(*builder, get_pointer_to_mask(set)); - llvm::Value* elems = LLVM::CreateLoad(*builder, get_pointer_to_elems(set)); - free_data(module, el_asr_type, LLVM::CreateLoad(*builder, get_pointer_to_capacity(set)), - el_mask, elems); - } - - void LLVMSetSeparateChaining::free_data(llvm::Module *module, - ASR::ttype_t* el_asr_type, llvm::Value *capacity, - llvm::Value *el_mask, llvm::Value *elems) { - get_builder0() - llvm::AllocaInst *chain_itr = builder0.CreateAlloca( - llvm::Type::getInt8PtrTy(context), nullptr); - llvm::AllocaInst *idx_ptr = builder0.CreateAlloca( - llvm::Type::getInt32Ty(context), nullptr); - LLVM::CreateStore(*builder, llvm::ConstantInt::get( - llvm::Type::getInt32Ty(context), llvm::APInt(32, 0)), idx_ptr); - llvm::BasicBlock *loophead = llvm::BasicBlock::Create(context, "loop.head"); - llvm::BasicBlock *loopbody = llvm::BasicBlock::Create(context, "loop.body"); - llvm::BasicBlock *loopend = llvm::BasicBlock::Create(context, "loop.end"); - - // head - llvm_utils->start_new_block(loophead); - { - llvm::Value *cond = builder->CreateICmpSGT( - capacity, - LLVM::CreateLoad(*builder, idx_ptr)); - builder->CreateCondBr(cond, loopbody, loopend); - } - - // body - llvm_utils->start_new_block(loopbody); - { - llvm::Value* idx = LLVM::CreateLoad(*builder, idx_ptr); - llvm::Value* el_mask_value = LLVM::CreateLoad(*builder, - llvm_utils->create_ptr_gep(el_mask, idx)); - - llvm::Value* is_el_set = builder->CreateICmpEQ(el_mask_value, - llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), llvm::APInt(8, 1))); - - llvm_utils->create_if_else(is_el_set, [&]() { - llvm::Value* el_i = llvm_utils->create_ptr_gep(elems, idx); - llvm::Value* el_ll_i8 = builder->CreateBitCast(el_i, llvm::Type::getInt8PtrTy(context)); - LLVM::CreateStore(*builder, el_ll_i8, chain_itr); - - // See logic for the same in LLVMDictSeparateChaining::free_data - llvm::Value* el_struct_i8 = LLVM::CreateLoad(*builder, chain_itr); - std::string el_type_code = ASRUtils::get_type_code(el_asr_type); - llvm::Type* el_struct_type = typecode2elstruct[el_type_code]; - llvm::Value* el_struct = builder->CreateBitCast(el_struct_i8, el_struct_type->getPointerTo()); - llvm::Value* next_el_struct = LLVM::CreateLoad(*builder, llvm_utils->create_gep(el_struct, 1)); - LLVM::CreateStore(*builder, next_el_struct, chain_itr); - - llvm::BasicBlock *loop2head = llvm::BasicBlock::Create(context, "loop2.head"); - llvm::BasicBlock *loop2body = llvm::BasicBlock::Create(context, "loop2.body"); - llvm::BasicBlock *loop2end = llvm::BasicBlock::Create(context, "loop2.end"); - - // head - llvm_utils->start_new_block(loop2head); - { - llvm::Value *cond = builder->CreateICmpNE( - LLVM::CreateLoad(*builder, chain_itr), - llvm::ConstantPointerNull::get(llvm::Type::getInt8PtrTy(context)) - ); - builder->CreateCondBr(cond, loop2body, loop2end); - } - - // body - llvm_utils->start_new_block(loop2body); - { - llvm::Value* el_struct_i8 = LLVM::CreateLoad(*builder, chain_itr); - std::string el_type_code = ASRUtils::get_type_code(el_asr_type); - llvm::Type* el_struct_type = typecode2elstruct[el_type_code]; - llvm::Value* el_struct = builder->CreateBitCast(el_struct_i8, el_struct_type->getPointerTo()); - llvm::Value* el_ptr = llvm_utils->create_gep(el_struct, 0); - if( LLVM::is_llvm_struct(el_asr_type) ) { - llvm_utils->free_data(el_ptr, el_asr_type, module); - } - llvm::Value* next_el_struct = LLVM::CreateLoad(*builder, llvm_utils->create_gep(el_struct, 1)); - LLVM::CreateStore(*builder, next_el_struct, chain_itr); - LLVM::lfortran_free(context, *module, *builder, el_ptr); - } - - builder->CreateBr(loop2head); - - // end - llvm_utils->start_new_block(loop2end); - }, [=]() { - }); - llvm::Value* tmp = builder->CreateAdd(idx, - llvm::ConstantInt::get(context, llvm::APInt(32, 1))); - LLVM::CreateStore(*builder, tmp, idx_ptr); - } - builder->CreateBr(loophead); - - // end - llvm_utils->start_new_block(loopend); - - LLVM::lfortran_free(context, *module, *builder, el_mask); - LLVM::lfortran_free(context, *module, *builder, elems); - - } - llvm::Value* LLVMSetInterface::len(llvm::Value* set) { - return LLVM::CreateLoad(*builder, get_pointer_to_occupancy(set)); + return llvm_utils->CreateLoad(get_pointer_to_occupancy(set)); } } // namespace LCompilers diff --git a/src/libasr/codegen/llvm_utils.h b/src/libasr/codegen/llvm_utils.h index d532382b70..c4440629dd 100644 --- a/src/libasr/codegen/llvm_utils.h +++ b/src/libasr/codegen/llvm_utils.h @@ -1,10 +1,8 @@ #ifndef LFORTRAN_LLVM_UTILS_H #define LFORTRAN_LLVM_UTILS_H -#include -#include - #include +#include #include #include @@ -20,10 +18,6 @@ namespace LCompilers { - #define get_builder0() llvm::BasicBlock &entry_block = builder->GetInsertBlock()->getParent()->getEntryBlock(); \ - llvm::IRBuilder<> builder0(context); \ - builder0.SetInsertPoint(&entry_block, entry_block.getFirstInsertionPt()); \ - // Platform dependent fast unique hash: static inline uint64_t get_hash(ASR::asr_t *node) { @@ -75,7 +69,7 @@ namespace LCompilers { llvm::Function *fn_printf = module.getFunction("_lfortran_printf"); if (!fn_printf) { llvm::FunctionType *function_type = llvm::FunctionType::get( - llvm::Type::getVoidTy(context), {llvm::Type::getInt8PtrTy(context)}, true); + llvm::Type::getVoidTy(context), {llvm::Type::getInt8Ty(context)->getPointerTo()}, true); fn_printf = llvm::Function::Create(function_type, llvm::Function::ExternalLinkage, "_lfortran_printf", &module); } @@ -88,9 +82,9 @@ namespace LCompilers { llvm::Function *fn_printf = module.getFunction("_lcompilers_string_format_fortran"); if (!fn_printf) { llvm::FunctionType *function_type = llvm::FunctionType::get( - llvm::Type::getInt8PtrTy(context), + llvm::Type::getInt8Ty(context)->getPointerTo(), {llvm::Type::getInt32Ty(context), - llvm::Type::getInt8PtrTy(context)}, true); + llvm::Type::getInt8Ty(context)->getPointerTo()}, true); fn_printf = llvm::Function::Create(function_type, llvm::Function::ExternalLinkage, "_lcompilers_string_format_fortran", &module); } @@ -98,22 +92,51 @@ namespace LCompilers { } static inline llvm::Value* lfortran_str_copy(llvm::Value* dest, llvm::Value *src, bool is_allocatable, - llvm::Module &module, llvm::IRBuilder<> &builder, llvm::LLVMContext &context) { - std::string runtime_func_name = "_lfortran_strcpy"; - llvm::Function *fn = module.getFunction(runtime_func_name); - if (!fn) { - llvm::FunctionType *function_type = llvm::FunctionType::get( - llvm::Type::getVoidTy(context), { - llvm::Type::getInt8PtrTy(context)->getPointerTo(), - llvm::Type::getInt8PtrTy(context), - llvm::Type::getInt8Ty(context) - }, false); - fn = llvm::Function::Create(function_type, - llvm::Function::ExternalLinkage, runtime_func_name, module); + llvm::Module &module, llvm::IRBuilder<> &builder, llvm::LLVMContext &context, llvm::Type* string_descriptor ) { + if(!is_allocatable){ + std::string runtime_func_name = "_lfortran_strcpy_pointer_string"; + llvm::Function *fn = module.getFunction(runtime_func_name); + if (!fn) { + llvm::FunctionType *function_type = llvm::FunctionType::get( + llvm::Type::getVoidTy(context), + { + llvm::Type::getInt8Ty(context)->getPointerTo()->getPointerTo(), + llvm::Type::getInt8Ty(context)->getPointerTo() + }, false); + fn = llvm::Function::Create(function_type, + llvm::Function::ExternalLinkage, runtime_func_name, module); + } + return builder.CreateCall(fn, {dest, src}); + } else { + std::string runtime_func_name = "_lfortran_strcpy_descriptor_string"; + llvm::Value *src_char_ptr, *dest_char_ptr, *string_size, *string_capacity; + std::vector idx { + llvm::ConstantInt::get(context, llvm::APInt(32, 0)), + llvm::ConstantInt::get(context, llvm::APInt(32, 0))}; + // Fetch char* from `src` and `dest` + Fetch string_size, string_capacity from `dest` + dest_char_ptr = builder.CreateGEP(string_descriptor, dest, idx); + src_char_ptr = builder.CreateLoad(llvm::Type::getInt8Ty(context)->getPointerTo(), + builder.CreateGEP(string_descriptor, src, idx)); + idx[1] = llvm::ConstantInt::get(context, llvm::APInt(32, 1)); + string_size = builder.CreateGEP(string_descriptor, dest, idx); + idx[1] = llvm::ConstantInt::get(context, llvm::APInt(32, 2)); + string_capacity = builder.CreateGEP(string_descriptor, dest, idx); + llvm::Function *fn = module.getFunction(runtime_func_name); + if (!fn) { + llvm::FunctionType *function_type = llvm::FunctionType::get( + llvm::Type::getVoidTy(context), + { + llvm::Type::getInt8Ty(context)->getPointerTo()->getPointerTo(), + llvm::Type::getInt8Ty(context)->getPointerTo(), + llvm::Type::getInt64Ty(context)->getPointerTo(), + llvm::Type::getInt64Ty(context)->getPointerTo() + }, false); + fn = llvm::Function::Create(function_type, + llvm::Function::ExternalLinkage, runtime_func_name, module); + } + return builder.CreateCall(fn, {dest_char_ptr, src_char_ptr, string_size, string_capacity}); } - llvm::Value* free_string = llvm::ConstantInt::get( - llvm::Type::getInt8Ty(context), llvm::APInt(8, is_allocatable)); - return builder.CreateCall(fn, {dest, src, free_string}); + } static inline void print_error(llvm::LLVMContext &context, llvm::Module &module, @@ -122,7 +145,7 @@ namespace LCompilers { llvm::Function *fn_printf = module.getFunction("_lcompilers_print_error"); if (!fn_printf) { llvm::FunctionType *function_type = llvm::FunctionType::get( - llvm::Type::getVoidTy(context), {llvm::Type::getInt8PtrTy(context)}, true); + llvm::Type::getVoidTy(context), {llvm::Type::getInt8Ty(context)->getPointerTo()}, true); fn_printf = llvm::Function::Create(function_type, llvm::Function::ExternalLinkage, "_lcompilers_print_error", &module); } @@ -154,7 +177,7 @@ namespace LCompilers { if (!fn) { llvm::FunctionType *function_type = llvm::FunctionType::get( llvm::Type::getVoidTy(context), { - llvm::Type::getInt8PtrTy(context), + llvm::Type::getInt8Ty(context)->getPointerTo(), llvm::Type::getInt1Ty(context) }, true); fn = llvm::Function::Create(function_type, @@ -166,10 +189,7 @@ namespace LCompilers { namespace LLVM { - llvm::Value* CreateLoad(llvm::IRBuilder<> &builder, llvm::Value *x); llvm::Value* CreateStore(llvm::IRBuilder<> &builder, llvm::Value *x, llvm::Value *y); - llvm::Value* CreateGEP(llvm::IRBuilder<> &builder, llvm::Value *x, std::vector &idx); - llvm::Value* CreateInBoundsGEP(llvm::IRBuilder<> &builder, llvm::Value *x, std::vector &idx); llvm::Value* lfortran_malloc(llvm::LLVMContext &context, llvm::Module &module, llvm::IRBuilder<> &builder, llvm::Value* arg_size); llvm::Value* lfortran_realloc(llvm::LLVMContext &context, llvm::Module &module, @@ -182,9 +202,8 @@ namespace LCompilers { return ASR::is_a(*asr_type) || ASR::is_a(*asr_type) || ASR::is_a(*asr_type) || - ASR::is_a(*asr_type)|| - ASR::is_a(*asr_type) || - ASR::is_a(*asr_type); + ASR::is_a(*asr_type)|| + ASR::is_a(*asr_type); } static inline bool is_llvm_pointer(const ASR::ttype_t& asr_type) { return ( ASR::is_a(asr_type) || @@ -221,6 +240,7 @@ namespace LCompilers { std::map>& name2memidx; std::unordered_map>& arr_arg_type_cache; std::map>& fname2arg_type; + std::map &ptr_type; LLVMDictInterface* dict_api_lp; LLVMDictInterface* dict_api_sc; @@ -232,6 +252,7 @@ namespace LCompilers { llvm::StructType *complex_type_4, *complex_type_8; llvm::StructType *complex_type_4_ptr, *complex_type_8_ptr; llvm::PointerType *character_type; + llvm::Type* string_descriptor; LLVMUtils(llvm::LLVMContext& context, llvm::IRBuilder<>* _builder, std::string& der_type_name_, @@ -242,16 +263,43 @@ namespace LCompilers { std::map>& name2memidx_, CompilerOptions &compiler_options_, std::unordered_map>& arr_arg_type_cache_, - std::map>& fname2arg_type_); + std::map>& fname2arg_type_, + std::map &ptr_type_); llvm::Value* create_gep(llvm::Value* ds, int idx); + llvm::Value* create_gep2(llvm::Type *t, llvm::Value* ds, int idx); + llvm::Value* create_gep(llvm::Value* ds, llvm::Value* idx); + llvm::Value* create_gep2(llvm::Type *t, llvm::Value* ds, llvm::Value* idx); + llvm::Value* create_ptr_gep(llvm::Value* ptr, int idx); + llvm::Value* create_ptr_gep2(llvm::Type* type, llvm::Value* ptr, int idx); + llvm::Value* create_ptr_gep(llvm::Value* ptr, llvm::Value* idx); + llvm::Value* create_ptr_gep2(llvm::Type* type, llvm::Value* ptr, llvm::Value* idx); + + llvm::Value* CreateLoad(llvm::Value *x); + llvm::Value* CreateLoad2(llvm::Type *t, llvm::Value *x); + llvm::Value* CreateLoad2(ASR::ttype_t *type, llvm::Value *x); + llvm::Value* CreateGEP(llvm::Value *x, std::vector &idx); + llvm::Value* CreateGEP2(llvm::Type *t, llvm::Value *x, + std::vector &idx); + llvm::Value* CreateGEP2(ASR::ttype_t *type, llvm::Value *x, int idx); + llvm::Value* CreateInBoundsGEP(llvm::Value *x, std::vector &idx); + llvm::Value* CreateInBoundsGEP2(llvm::Type *t, llvm::Value *x, + std::vector &idx); + + llvm::AllocaInst* CreateAlloca(llvm::Type* type, + llvm::Value* size=nullptr, std::string Name="", + bool is_llvm_ptr=false); + llvm::AllocaInst* CreateAlloca(llvm::IRBuilder<> &builder, + llvm::Type* type, llvm::Value* size=nullptr, std::string Name="", + bool is_llvm_ptr=false); + llvm::Type* getIntType(int a_kind, bool get_pointer=false); void start_new_block(llvm::BasicBlock *bb); @@ -277,13 +325,13 @@ namespace LCompilers { llvm::Type* getStructType(ASR::ttype_t* _type, llvm::Module* module, bool is_pointer=false); - llvm::Type* getUnionType(ASR::UnionType_t* union_type, + llvm::Type* getUnion(ASR::Union_t* union_type, llvm::Module* module, bool is_pointer=false); - llvm::Type* getUnionType(ASR::ttype_t* _type, + llvm::Type* getUnion(ASR::ttype_t* _type, llvm::Module* module, bool is_pointer=false); - llvm::Type* getClassType(ASR::ClassType_t* der_type, bool is_pointer=false); + llvm::Type* getClassType(ASR::Class_t* der_type, bool is_pointer=false); llvm::Type* getClassType(ASR::Struct_t* der_type, bool is_pointer=false); @@ -330,7 +378,7 @@ namespace LCompilers { ASR::ttype_t* asr_type, llvm::Module* module, std::map>& name2memidx); - void free_data(llvm::Value* src, ASR::ttype_t* asr_type, llvm::Module* module); + llvm::Value* convert_kind(llvm::Value* val, llvm::Type* target_type); // Note: `llvm_utils->create_if_else` and `create_loop` are optional APIs @@ -447,7 +495,7 @@ namespace LCompilers { llvm::Value* pop_last(llvm::Value* list, ASR::ttype_t* list_type, llvm::Module& module); - void list_clear(llvm::Value* list, ASR::ttype_t *item_type, llvm::Module *module); + void list_clear(llvm::Value* list); void reverse(llvm::Value* list, llvm::Module& module); @@ -463,7 +511,7 @@ namespace LCompilers { llvm::Value* count(llvm::Value* list, llvm::Value* item, ASR::ttype_t* item_type, llvm::Module& module); - void free_data(llvm::Value* list, ASR::ttype_t *item_type, llvm::Module& module); + void free_data(llvm::Value* list, llvm::Module& module); llvm::Value* check_list_equality(llvm::Value* l1, llvm::Value* l2, ASR::ttype_t *item_type, llvm::LLVMContext& context, llvm::IRBuilder<>* builder, llvm::Module& module); @@ -483,7 +531,7 @@ namespace LCompilers { llvm::LLVMContext& context; LLVMUtils* llvm_utils; - llvm::IRBuilder<>* builder; + // llvm::IRBuilder<>* builder; std::map> typecode2tupletype; @@ -571,9 +619,6 @@ namespace LCompilers { virtual llvm::Value* get_pointer_to_occupancy(llvm::Value* dict) = 0; - virtual - llvm::Value* get_pointer_to_keymask(llvm::Value* dict) = 0; - virtual llvm::Value* get_pointer_to_capacity(llvm::Value* dict) = 0; @@ -596,7 +641,7 @@ namespace LCompilers { virtual llvm::Value* resolve_collision_for_read_with_bound_check(llvm::Value* dict, llvm::Value* key_hash, llvm::Value* key, llvm::Module& module, - ASR::ttype_t* key_asr_type, ASR::ttype_t* value_asr_type, bool check_if_exists = false) = 0; + ASR::ttype_t* key_asr_type, ASR::ttype_t* value_asr_type) = 0; virtual llvm::Value* resolve_collision_for_read_with_default(llvm::Value* dict, llvm::Value* key_hash, @@ -651,10 +696,6 @@ namespace LCompilers { virtual void set_is_dict_present(bool value); - virtual - void dict_clear(llvm::Value *dict, llvm::Module *module, - ASR::ttype_t *key_asr_type, ASR::ttype_t* value_asr_type) = 0; - virtual void get_elements_list(llvm::Value* dict, llvm::Value* elements_list, ASR::ttype_t* key_asr_type, @@ -662,16 +703,6 @@ namespace LCompilers { std::map>& name2memidx, bool key_or_value) = 0; - virtual - llvm::Type* get_key_value_pair_type(ASR::ttype_t* key_asr_type, ASR::ttype_t* value_pair_type) = 0; - - virtual - llvm::Value* get_pointer_to_key_value_pairs(llvm::Value* dict) = 0; - - virtual - void dict_free(llvm::Value *dict, llvm::Module *module, ASR::ttype_t *key_asr_type, ASR::ttype_t *value_asr_type) = 0; - - virtual ~LLVMDictInterface() = 0; }; @@ -721,7 +752,7 @@ namespace LCompilers { llvm::Value* resolve_collision_for_read_with_bound_check(llvm::Value* dict, llvm::Value* key_hash, llvm::Value* key, llvm::Module& module, - ASR::ttype_t* key_asr_type, ASR::ttype_t* value_asr_type, bool check_if_exists = false); + ASR::ttype_t* key_asr_type, ASR::ttype_t* value_asr_type); llvm::Value* resolve_collision_for_read_with_default(llvm::Value* dict, llvm::Value* key_hash, llvm::Value* key, llvm::Module& module, @@ -759,21 +790,12 @@ namespace LCompilers { llvm::Value* len(llvm::Value* dict); - void dict_clear(llvm::Value *dict, llvm::Module *module, - ASR::ttype_t *key_asr_type, ASR::ttype_t* value_asr_type); - void get_elements_list(llvm::Value* dict, llvm::Value* elements_list, ASR::ttype_t* key_asr_type, ASR::ttype_t* value_asr_type, llvm::Module& module, std::map>& name2memidx, bool key_or_value); - llvm::Type* get_key_value_pair_type(ASR::ttype_t* key_asr_type, ASR::ttype_t* value_pair_type); - - llvm::Value* get_pointer_to_key_value_pairs(llvm::Value* dict); - - void dict_free(llvm::Value *dict, llvm::Module *module, ASR::ttype_t *key_asr_type, ASR::ttype_t *value_asr_type); - virtual ~LLVMDict(); }; @@ -802,14 +824,13 @@ namespace LCompilers { llvm::Value* resolve_collision_for_read_with_bound_check(llvm::Value* dict, llvm::Value* key_hash, llvm::Value* key, llvm::Module& module, - ASR::ttype_t* key_asr_type, ASR::ttype_t* value_asr_type, bool check_if_exists = false); + ASR::ttype_t* key_asr_type, ASR::ttype_t* value_asr_type); llvm::Value* resolve_collision_for_read_with_default(llvm::Value* dict, llvm::Value* key_hash, llvm::Value* key, llvm::Module& module, ASR::ttype_t* key_asr_type, ASR::ttype_t* value_asr_type, llvm::Value *def_value); - virtual ~LLVMDictOptimizedLinearProbing(); }; @@ -822,6 +843,8 @@ namespace LCompilers { llvm::Value* get_pointer_to_number_of_filled_buckets(llvm::Value* dict); + llvm::Value* get_pointer_to_key_value_pairs(llvm::Value* dict); + llvm::Value* get_pointer_to_rehash_flag(llvm::Value* dict); void deepcopy_key_value_pair_linked_list(llvm::Value* srci, llvm::Value* desti, @@ -839,13 +862,11 @@ namespace LCompilers { llvm::Type* get_key_value_pair_type(std::string key_type_code, std::string value_type_code); + llvm::Type* get_key_value_pair_type(ASR::ttype_t* key_asr_type, ASR::ttype_t* value_pair_type); + void dict_init_given_initial_capacity(std::string key_type_code, std::string value_type_code, llvm::Value* dict, llvm::Module* module, llvm::Value* initial_capacity); - void free_data(llvm::Module *module, ASR::ttype_t* key_asr_type, - ASR::ttype_t* value_asr_type, llvm::Value *capacity, - llvm::Value *key_mask, llvm::Value *key_value_pairs); - public: LLVMDictSeparateChaining( @@ -880,7 +901,7 @@ namespace LCompilers { llvm::Value* resolve_collision_for_read_with_bound_check(llvm::Value* dict, llvm::Value* key_hash, llvm::Value* key, llvm::Module& module, - ASR::ttype_t* key_asr_type, ASR::ttype_t* value_asr_type, bool check_if_exists = false); + ASR::ttype_t* key_asr_type, ASR::ttype_t* value_asr_type); llvm::Value* resolve_collision_for_read_with_default(llvm::Value* dict, llvm::Value* key_hash, llvm::Value* key, llvm::Module& module, @@ -917,21 +938,12 @@ namespace LCompilers { llvm::Value* len(llvm::Value* dict); - void dict_clear(llvm::Value *dict, llvm::Module *module, - ASR::ttype_t *key_asr_type, ASR::ttype_t* value_asr_type); - void get_elements_list(llvm::Value* dict, llvm::Value* elements_list, ASR::ttype_t* key_asr_type, ASR::ttype_t* value_asr_type, llvm::Module& module, std::map>& name2memidx, bool key_or_value); - llvm::Type* get_key_value_pair_type(ASR::ttype_t* key_asr_type, ASR::ttype_t* value_pair_type); - - llvm::Value* get_pointer_to_key_value_pairs(llvm::Value* dict); - - void dict_free(llvm::Value *dict, llvm::Module *module, ASR::ttype_t *key_asr_type, ASR::ttype_t *value_asr_type); - virtual ~LLVMDictSeparateChaining(); }; @@ -979,9 +991,6 @@ namespace LCompilers { virtual llvm::Value* get_pointer_to_capacity(llvm::Value* set) = 0; - virtual - llvm::Value* get_pointer_to_mask(llvm::Value* set) = 0; - llvm::Value* get_el_hash(llvm::Value* capacity, llvm::Value* el, ASR::ttype_t* el_asr_type, llvm::Module& module); @@ -1008,17 +1017,14 @@ namespace LCompilers { std::map>& name2memidx); virtual - llvm::Value* resolve_collision_for_read_with_bound_check( + void resolve_collision_for_read_with_bound_check( llvm::Value* set, llvm::Value* el_hash, llvm::Value* el, - llvm::Module& module, ASR::ttype_t* el_asr_type, bool throw_key_error, bool check_if_exists = false) = 0; + llvm::Module& module, ASR::ttype_t* el_asr_type) = 0; virtual void remove_item( llvm::Value* set, llvm::Value* el, - llvm::Module& module, ASR::ttype_t* el_asr_type, bool throw_key_error) = 0; - - virtual - llvm::Value* pop_item(llvm::Value* set, llvm::Module& module, ASR::ttype_t* el_asr_type) = 0; + llvm::Module& module, ASR::ttype_t* el_asr_type) = 0; virtual void set_deepcopy( @@ -1029,18 +1035,12 @@ namespace LCompilers { virtual llvm::Value* len(llvm::Value* set); - virtual - void set_clear(llvm::Value *set, llvm::Module *module, ASR::ttype_t *el_asr_type) = 0; - virtual bool is_set_present(); virtual void set_is_set_present(bool value); - virtual - void set_free(llvm::Value *set, llvm::Module *module, ASR::ttype_t *el_asr_type) = 0; - virtual ~LLVMSetInterface() = 0; }; @@ -1088,25 +1088,19 @@ namespace LCompilers { llvm::Value* set, llvm::Module* module, ASR::ttype_t* el_asr_type, std::map>& name2memidx); - llvm::Value* resolve_collision_for_read_with_bound_check( + void resolve_collision_for_read_with_bound_check( llvm::Value* set, llvm::Value* el_hash, llvm::Value* el, - llvm::Module& module, ASR::ttype_t* el_asr_type, bool throw_key_error, bool check_if_exists = false); + llvm::Module& module, ASR::ttype_t* el_asr_type); void remove_item( llvm::Value* set, llvm::Value* el, - llvm::Module& module, ASR::ttype_t* el_asr_type, bool throw_key_error); - - llvm::Value* pop_item(llvm::Value* set, llvm::Module& module, ASR::ttype_t* el_asr_type); + llvm::Module& module, ASR::ttype_t* el_asr_type); void set_deepcopy( llvm::Value* src, llvm::Value* dest, ASR::Set_t* set_type, llvm::Module* module, std::map>& name2memidx); - void set_clear(llvm::Value *set, llvm::Module *module, ASR::ttype_t *el_asr_type); - - void set_free(llvm::Value *set, llvm::Module *module, ASR::ttype_t *el_asr_type); - ~LLVMSetLinearProbing(); }; @@ -1140,10 +1134,6 @@ namespace LCompilers { ASR::Set_t* set_type, llvm::Module* module, std::map>& name2memidx); - void free_data(llvm::Module *module, - ASR::ttype_t* el_asr_type, llvm::Value *capacity, - llvm::Value *el_mask, llvm::Value *elems); - public: LLVMSetSeparateChaining( @@ -1179,25 +1169,19 @@ namespace LCompilers { llvm::Value* set, llvm::Module* module, ASR::ttype_t* el_asr_type, std::map>& name2memidx); - llvm::Value* resolve_collision_for_read_with_bound_check( + void resolve_collision_for_read_with_bound_check( llvm::Value* set, llvm::Value* el_hash, llvm::Value* el, - llvm::Module& module, ASR::ttype_t* el_asr_type, bool throw_key_error, bool check_if_exists = false); + llvm::Module& module, ASR::ttype_t* el_asr_type); void remove_item( llvm::Value* set, llvm::Value* el, - llvm::Module& module, ASR::ttype_t* el_asr_type, bool throw_key_error); - - llvm::Value* pop_item(llvm::Value* set, llvm::Module& module, ASR::ttype_t* el_asr_type); + llvm::Module& module, ASR::ttype_t* el_asr_type); void set_deepcopy( llvm::Value* src, llvm::Value* dest, ASR::Set_t* set_type, llvm::Module* module, std::map>& name2memidx); - void set_clear(llvm::Value *set, llvm::Module *module, ASR::ttype_t *el_asr_type); - - void set_free(llvm::Value *set, llvm::Module *module, ASR::ttype_t *el_asr_type); - ~LLVMSetSeparateChaining(); }; diff --git a/src/libasr/codegen/wasm_assembler.h b/src/libasr/codegen/wasm_assembler.h index bc5f40bab2..fb0638e758 100644 --- a/src/libasr/codegen/wasm_assembler.h +++ b/src/libasr/codegen/wasm_assembler.h @@ -1,6 +1,7 @@ #include #include #include +#include namespace LCompilers { diff --git a/src/libasr/codegen/wasm_to_wat.cpp b/src/libasr/codegen/wasm_to_wat.cpp index 4410a5c8f7..e760c06779 100644 --- a/src/libasr/codegen/wasm_to_wat.cpp +++ b/src/libasr/codegen/wasm_to_wat.cpp @@ -1,4 +1,3 @@ -#include #include #include diff --git a/src/libasr/codegen/wasm_to_x64.cpp b/src/libasr/codegen/wasm_to_x64.cpp index 3eb67ec66e..c7eaa40c7b 100644 --- a/src/libasr/codegen/wasm_to_x64.cpp +++ b/src/libasr/codegen/wasm_to_x64.cpp @@ -1,4 +1,3 @@ -#include #include #include diff --git a/src/libasr/codegen/wasm_to_x86.cpp b/src/libasr/codegen/wasm_to_x86.cpp index ac3c62ca6e..b04ed4339d 100644 --- a/src/libasr/codegen/wasm_to_x86.cpp +++ b/src/libasr/codegen/wasm_to_x86.cpp @@ -1,4 +1,3 @@ -#include #include #include diff --git a/src/libasr/compiler_tester/tester.py b/src/libasr/compiler_tester/tester.py index bd6d7e62e5..e3c08a698a 100644 --- a/src/libasr/compiler_tester/tester.py +++ b/src/libasr/compiler_tester/tester.py @@ -125,6 +125,14 @@ def _compare_eq_dict( ) return explanation +def test_for_duplicates(test_data): + tests = test_data["test"] + filenames = [t["filename"] for t in tests] + if len(set(filenames)) != len(filenames): + print("There are duplicate test filenames:") + duplicates = [item for item in set(filenames) if filenames.count(item) > 1] + print(duplicates) + sys.exit(1) def fixdir(s: bytes) -> bytes: local_dir = os.getcwd() @@ -314,7 +322,12 @@ def run_test(testname, basename, cmd, infile, update_reference=False, raise FileNotFoundError( f"The output json file '{jo}' for {testname} does not exist") - do = json.load(open(jo)) + try: + do = json.load(open(jo)) + except json.decoder.JSONDecodeError: + print("JSON failed to be decoded") + print(f"Filename: {jo}") + raise if update_reference: do_update_reference(jo, jr, do) return @@ -388,8 +401,6 @@ def tester_main(compiler, single_test, is_lcompilers_executable_installed=False) help="Skip LLVM tests") parser.add_argument("--skip-run-with-dbg", action="store_true", help="Skip runtime tests with debugging information enabled") - parser.add_argument("--skip-cpptranslate", action="store_true", - help="Skip tests for ast_openmp that depend on cpptranslate") parser.add_argument("-s", "--sequential", action="store_true", help="Run all tests sequentially") parser.add_argument("--no-color", action="store_true", @@ -411,7 +422,6 @@ def tester_main(compiler, single_test, is_lcompilers_executable_installed=False) verbose = args.verbose no_llvm = args.no_llvm skip_run_with_dbg = args.skip_run_with_dbg - skip_cpptranslate = args.skip_cpptranslate global no_color no_color = args.no_color @@ -420,6 +430,7 @@ def tester_main(compiler, single_test, is_lcompilers_executable_installed=False) os.environ["PATH"] = os.path.join(SRC_DIR, "bin") \ + os.pathsep + os.environ["PATH"] test_data = toml.load(open(os.path.join(ROOT_DIR, "tests", "tests.toml"))) + test_for_duplicates(test_data) filtered_tests = test_data["test"] if specific_tests: filtered_tests = [test for test in filtered_tests if any( @@ -445,7 +456,6 @@ def tester_main(compiler, single_test, is_lcompilers_executable_installed=False) verbose=verbose, no_llvm=no_llvm, skip_run_with_dbg=True, - skip_cpptranslate=True, no_color=True) filtered_tests = [test for test in filtered_tests if 'extrafiles' not in test] @@ -459,7 +469,6 @@ def tester_main(compiler, single_test, is_lcompilers_executable_installed=False) verbose=verbose, no_llvm=no_llvm, skip_run_with_dbg=skip_run_with_dbg, - skip_cpptranslate=skip_cpptranslate, no_color=no_color) # run in parallel else: @@ -472,7 +481,6 @@ def tester_main(compiler, single_test, is_lcompilers_executable_installed=False) verbose=verbose, no_llvm=no_llvm, skip_run_with_dbg=skip_run_with_dbg, - skip_cpptranslate=skip_cpptranslate, no_color=no_color) with ThreadPoolExecutor() as ex: futures = ex.map(single_tester_partial_args, filtered_tests) diff --git a/src/libasr/config.h.in b/src/libasr/config.h.in index f2e453edc4..365cd60682 100644 --- a/src/libasr/config.h.in +++ b/src/libasr/config.h.in @@ -12,6 +12,7 @@ /* Define if LLVM is enabled */ #cmakedefine HAVE_LFORTRAN_LLVM +#cmakedefine HAVE_LFORTRAN_MLIR /* Define if RAPIDJSON is found */ #cmakedefine HAVE_LFORTRAN_RAPIDJSON @@ -24,6 +25,7 @@ #cmakedefine HAVE_LFORTRAN_LINK #cmakedefine HAVE_LFORTRAN_MACHO #cmakedefine HAVE_LFORTRAN_UNWIND +#cmakedefine HAVE_LFORTRAN_LLVM_STACKTRACE /* Define if cxxabi.h is present */ #cmakedefine HAVE_LFORTRAN_DEMANGLE diff --git a/src/libasr/containers.h b/src/libasr/containers.h index 502e5532fc..205a8ab52a 100644 --- a/src/libasr/containers.h +++ b/src/libasr/containers.h @@ -119,6 +119,21 @@ struct Vec { n++; } + void push_front(Allocator &al, T x) { + LCOMPILERS_ASSERT(reserve_called == vec_called_const); + if (n == max) { + size_t max2 = 2*max; + T* p2 = al.allocate(max2); + std::memcpy(p2+1, p, sizeof(T) * n); + p = p2; + max = max2; + } else { + std::memmove(p+1, p, sizeof(T) * n); + } + p[0] = x; + n++; + } + size_t size() const { return n; } diff --git a/src/libasr/diagnostics.cpp b/src/libasr/diagnostics.cpp index 6e129b6d34..c773bed7d6 100644 --- a/src/libasr/diagnostics.cpp +++ b/src/libasr/diagnostics.cpp @@ -61,17 +61,32 @@ bool Diagnostics::has_error() const { return false; } +bool Diagnostics::has_warning() const { + for (auto &d : this->diagnostics) { + if (d.level == Level::Warning) return true; + } + return false; +} + +bool Diagnostics::has_style() const { + for (auto &d : this->diagnostics) { + if (d.level == Level::Style) return true; + } + return false; +} + std::string Diagnostics::render(LocationManager &lm, const CompilerOptions &compiler_options) { std::string out; for (auto &d : this->diagnostics) { - if (compiler_options.no_warnings && d.level != Level::Error) { - continue; - } if (compiler_options.error_format == "human") { - out += render_diagnostic_human(d, lm, compiler_options.use_colors, - compiler_options.show_stacktrace); - if (&d != &this->diagnostics.back()) out += "\n"; + if ((compiler_options.disable_style && d.level == Level::Style) || (compiler_options.no_warnings && d.level == Level::Warning)) { + out += ""; + } else { + out += render_diagnostic_human(d, lm, compiler_options.use_colors, + compiler_options.show_stacktrace); + if (&d != &this->diagnostics.back()) out += "\n"; + } } else if (compiler_options.error_format == "short") { out += render_diagnostic_short(d, lm); } else { @@ -80,7 +95,7 @@ std::string Diagnostics::render(LocationManager &lm, } if (compiler_options.error_format == "human") { if (this->diagnostics.size() > 0 && !compiler_options.no_error_banner) { - if (!compiler_options.no_warnings || has_error()) { + if ((!compiler_options.disable_style && has_style()) || (!compiler_options.no_warnings && has_warning()) || has_error()) { std::string bold = ColorsANSI::BOLD; std::string reset = ColorsANSI::RESET; if (!compiler_options.use_colors) { @@ -89,7 +104,7 @@ std::string Diagnostics::render(LocationManager &lm, } out += "\n\n"; out += bold + "Note" + reset - + ": Please report unclear or confusing messages as bugs at\nhttps://github.com/lcompilers/lpython/issues.\n"; + + ": Please report unclear, confusing or incorrect messages as bugs at\nhttps://github.com/lfortran/lfortran/issues.\n"; } } } diff --git a/src/libasr/diagnostics.h b/src/libasr/diagnostics.h index 002e66216f..0a06cb8615 100644 --- a/src/libasr/diagnostics.h +++ b/src/libasr/diagnostics.h @@ -51,7 +51,7 @@ struct Label { Label(const std::string &message, const std::vector &locations, bool primary=true) : primary{primary}, message{message} { for (auto &loc : locations) { - spans.push_back(Span(loc)); + spans.emplace_back(loc); } } }; @@ -122,15 +122,13 @@ struct Diagnostics { // Returns true iff diagnostics contains at least one error message bool has_error() const; + bool has_warning() const; + bool has_style() const; void add(const Diagnostic &d) { diagnostics.push_back(d); } - void clear() { - diagnostics.clear(); - } - void message_label(const std::string &message, const std::vector &locations, const std::string &error_label, @@ -189,6 +187,10 @@ struct Diagnostics { message_label(message, locations, error_label, Level::Style, Stage::Parser); } + + void clear() { + diagnostics.clear(); + } }; struct ColorsANSI { diff --git a/src/libasr/gen_pass.py b/src/libasr/gen_pass.py index abccd1ccbd..8695e14a4d 100644 --- a/src/libasr/gen_pass.py +++ b/src/libasr/gen_pass.py @@ -1,6 +1,9 @@ passes = [ + "array_struct_temporary", "replace_arr_slice", + "replace_openmp", "replace_function_call_in_declaration", + "replace_array_passed_in_function_call", "replace_array_op", "replace_class_constructor", "dead_code_removal", @@ -35,7 +38,8 @@ "replace_where", "unique_symbols", "insert_deallocate", - "promote_allocatable_to_nonallocatable" + "promote_allocatable_to_nonallocatable", + "replace_with_compile_time_values" ] diff --git a/src/libasr/intrinsic_func_registry_util_gen.py b/src/libasr/intrinsic_func_registry_util_gen.py index b33dc8f772..750b6c833a 100644 --- a/src/libasr/intrinsic_func_registry_util_gen.py +++ b/src/libasr/intrinsic_func_registry_util_gen.py @@ -29,7 +29,7 @@ "Mod": [ { "args": [("int", "int"), ("real", "real")], - "ret_type_arg_idx": 0 + "ret_type_arg_idx": "dynamic" }, ], "Trailz": [ @@ -38,28 +38,28 @@ "ret_type_arg_idx": 0 }, ], - "Modulo": [ + "Spacing": [ { - "args": [("int", "int"), ("real", "real")], + "args": [("real",)], "ret_type_arg_idx": 0 }, ], - "BesselJ0": [ + "Modulo": [ { - "args": [("real",)], + "args": [("int", "int"), ("real", "real")], "ret_type_arg_idx": 0 }, ], - "BesselJ1": [ + "BesselJN": [ { - "args": [("real",)], - "ret_type_arg_idx": 0 + "args": [("int", "real")], + "ret_type_arg_idx": 1 }, ], - "BesselY0": [ + "BesselYN": [ { - "args": [("real",)], - "ret_type_arg_idx": 0 + "args": [("int", "real")], + "ret_type_arg_idx": 1 }, ], "Mvbits": [ @@ -68,6 +68,12 @@ "ret_type_arg_idx": 3 }, ], + "MoveAlloc": [ + { + "args": [("any", "any")], + "ret_type_arg_idx": 0 + }, + ], "Leadz": [ { "args": [("int",)], @@ -83,6 +89,79 @@ "Hypot": [ { "args": [("real", "real")], + "ret_type_arg_idx": 0, + "same_kind_arg" : 2 + } + ], + "Trunc": [ + { + "args": [("real",)], + "ret_type_arg_idx": 0 + } + ], + "Gamma": [ + { + "args": [("real",)], + "ret_type_arg_idx": 0 + } + ], + "LogGamma": [ + { + "args": [("real",)], + "ret_type_arg_idx": 0 + } + ], + "Log10": [ + { + "args": [("real",)], + "ret_type_arg_idx": 0 + } + ], + "Erf": [ + { + "args": [("real",)], + "ret_type_arg_idx": 0 + } + ], + "Erfc": [ + { + "args": [("real",)], + "ret_type_arg_idx": 0 + } + ], + "Exp": [ + { + "args": [("real",), ("complex",)], + "ret_type_arg_idx": 0 + }, + ], + "ErfcScaled": [ + { + "args": [("real",)], + "ret_type_arg_idx": 0 + }, + ], + "Atan2": [ + { + "args": [("real", "real")], + "ret_type_arg_idx": 0 + } + ], + "Fix": [ + { + "args": [("real",)], + "ret_type_arg_idx": 0 + } + ], + "Exp2": [ + { + "args": [("real",)], + "ret_type_arg_idx": 0 + } + ], + "Expm1": [ + { + "args": [("real",)], "ret_type_arg_idx": 0 } ], @@ -104,6 +183,13 @@ "return": "int32" } ], + "Logical": [ + { + "args": [("bool", )], + "ret_type_arg_idx": 0, + "kind_arg": True + } + ], "Digits": [ { "args": [("int",), ("real",)], @@ -167,7 +253,8 @@ "Sign": [ { "args": [("int", "int"), ("real", "real")], - "ret_type_arg_idx": 0 + "ret_type_arg_idx": 0, + "same_kind_arg": 2 }, ], "Radix": [ @@ -176,16 +263,35 @@ "return": "int32" }, ], + "OutOfRange": [ + { + "args": [("int", "real", "bool"), ("real", "real", "bool"), ("int", "int", "bool"), ("real", "int", "bool")], + "return": "logical" + }, + ], + "StorageSize": [ + { + "args": [("any",)], + "return": "int32", + "kind_arg": True + }, + ], + "Nearest": [ + { + "args": [("real", "real")], + "ret_type_arg_idx": 0 + }, + ], "Adjustl": [ { "args": [("char",)], - "return": "character(-1)" + "ret_type_arg_idx": 0 } ], "Adjustr": [ { "args": [("char",)], - "return": "character(-1)" + "ret_type_arg_idx": 0 } ], "Aint": [ @@ -195,6 +301,18 @@ "kind_arg": True } ], + "Isnan": [ + { + "args": [("real",)], + "return": "logical", + } + ], + "SameTypeAs": [ + { + "args": [("any", "any")], + "return": "logical" + } + ], "Nint": [ { "args": [("real",)], @@ -202,6 +320,12 @@ "kind_arg": True } ], + "Idnint": [ + { + "args": [("real",)], + "return": "int32" + } + ], "Anint": [ { "args": [("real",)], @@ -223,16 +347,154 @@ "kind_arg": True } ], + "Asind": [ + { + "args": [("real",)], + "ret_type_arg_idx": 0 + } + ], + "Acosd": [ + { + "args": [("real",)], + "ret_type_arg_idx": 0 + } + ], + "Atand": [ + { + "args": [("real",)], + "ret_type_arg_idx": 0 + } + ], + "Sind": [ + { + "args": [("real",)], + "ret_type_arg_idx": 0 + } + ], + "Cosd": [ + { + "args": [("real",)], + "ret_type_arg_idx": 0 + } + ], + "Tand": [ + { + "args": [("real",)], + "ret_type_arg_idx": 0 + } + ], + "BesselJ0": [ + { + "args": [("real",)], + "ret_type_arg_idx": 0 + }, + ], + "BesselJ1": [ + { + "args": [("real",)], + "ret_type_arg_idx": 0 + }, + ], + "BesselY0": [ + { + "args": [("real",)], + "ret_type_arg_idx": 0 + }, + ], + "BesselY1": [ + { + "args": [("real",)], + "ret_type_arg_idx": 0 + }, + ], "Sqrt": [ { "args": [("real",), ("complex",)], "ret_type_arg_idx": 0 }, ], + "Sin": [ + { + "args": [("real",), ("complex",)], + "ret_type_arg_idx": 0 + }, + ], + "Cos": [ + { + "args": [("real",), ("complex",)], + "ret_type_arg_idx": 0 + }, + ], + "Tan": [ + { + "args": [("real",), ("complex",)], + "ret_type_arg_idx": 0 + }, + ], + "Asin": [ + { + "args": [("real",), ("complex",)], + "ret_type_arg_idx": 0 + }, + ], + "Acos": [ + { + "args": [("real",), ("complex",)], + "ret_type_arg_idx": 0 + }, + ], + "Atan": [ + { + "args": [("real",), ("complex",)], + "ret_type_arg_idx": 0 + }, + ], + "Sinh": [ + { + "args": [("real",), ("complex",)], + "ret_type_arg_idx": 0 + }, + ], + "Cosh": [ + { + "args": [("real",), ("complex",)], + "ret_type_arg_idx": 0 + }, + ], + "Tanh": [ + { + "args": [("real",), ("complex",)], + "ret_type_arg_idx": 0 + }, + ], + "Asinh": [ + { + "args": [("real",), ("complex",)], + "ret_type_arg_idx": 0 + }, + ], + "Acosh": [ + { + "args": [("real",), ("complex",)], + "ret_type_arg_idx": 0 + }, + ], + "Atanh": [ + { + "args": [("real",), ("complex",)], + "ret_type_arg_idx": 0 + }, + ], + "Log": [ + { + "args": [("real",), ("complex",)], + "ret_type_arg_idx": 0 + }, + ], "Sngl": [ { "args": [("real",)], - "return": "real32" + "return": "real32", } ], "SignFromValue": [ @@ -316,19 +578,40 @@ "Iand": [ { "args": [("int", "int")], - "ret_type_arg_idx": 0 + "ret_type_arg_idx": 0, + "same_kind_arg": 2 + }, + ], + "And": [ + { + "args": [("int", "int"),("bool","bool")], + "ret_type_arg_idx": 0, }, ], "Ior": [ { "args": [("int", "int")], - "ret_type_arg_idx": 0 + "ret_type_arg_idx": 0, + "same_kind_arg": 2 + }, + ], + "Or": [ + { + "args": [("int", "int"), ("bool", "bool")], + "ret_type_arg_idx": 0, }, ], "Ieor": [ { "args": [("int", "int")], - "ret_type_arg_idx": 0 + "ret_type_arg_idx": 0, + "same_kind_arg": 2 + }, + ], + "Xor": [ + { + "args": [("int", "int"), ("bool", "bool")], + "ret_type_arg_idx": 0, }, ], "Ibclr": [ @@ -380,12 +663,30 @@ "kind_arg": True }, ], + "Dreal": [ + { + "args": [("complex64",)], + "return": "real64", + }, + ], "Rank": [ { "args": [("any",)], "return": "int32" } ], + "BitSize": [ + { + "args": [("int",)], + "ret_type_arg_idx": 0 + } + ], + "NewLine": [ + { + "args": [("char",)], + "return": "character(-1)" + } + ], "Range": [ { "args": [("int",), ("real",), ("complex",)], @@ -454,9 +755,22 @@ "kind_arg": True } ], + "Merge": [ + { + "args": [("any", "any", "bool")], + "ret_type_arg_idx": 0 + } + ], + "Mergebits": [ + { + "args": [("int", "int", "int")], + "ret_type_arg_idx": 0, + "same_kind_arg": 3 + } + ], "Ishftc": [ { - "args": [("int", "int")], + "args": [("int", "int", "int")], "ret_type_arg_idx": 0 }, ], @@ -474,6 +788,13 @@ "kind_arg": True } ], + "Achar": [ + { + "args": [("int",)], + "return": "character(1)", + "kind_arg": True + } + ], "Exponent": [ { "args": [("real",)], @@ -501,33 +822,76 @@ "Dshiftl": [ { "args": [("int", "int", "int",)], - "ret_type_arg_idx": 0 - }, - ], - "Popcnt": [ - { - "args": [("int",)], - "return": "int32", - }, - ], - "Poppar": [ - { - "args": [("int",)], - "return": "int32", + "ret_type_arg_idx": 0, + "same_kind_arg": 2 }, - ], - + ], + "Dshiftr": [ + { + "args": [("int", "int", "int",)], + "ret_type_arg_idx": 0 + }, + ], + "Popcnt": [ + { + "args": [("int",)], + "return": "int32", + }, + ], + "Poppar": [ + { + "args": [("int",)], + "return": "int32", + }, + ], + "Real": [ + { + "args": [("int",), ("real",), ("complex",)], + "return": "real32", + "kind_arg": True, + "real_32_except_complex": True + }, + ], + "Int": [ + { + "args": [("int",), ("real",), ("complex",)], + "return": "int32", + "kind_arg": True + } + ], + "StringLenTrim": [ + { + "args": [("char",)], + "return": "int32", + "kind_arg": True + } + ], + "StringTrim": [ + { + "args": [("char",)], + "ret_type_arg_idx": 0 + } + ], } skip_create_func = ["Partition"] compile_time_only_fn = [ "Epsilon", "Radix", + "IsContiguous", + "StorageSize", "Range", "Precision", "Rank", "Tiny", "Huge", + "BitSize", + "NewLine", + "Kind", + "MaxExponent", + "MinExponent", + "SameTypeAs", + "Digits", ] type_to_asr_type_check = { @@ -538,6 +902,7 @@ "bool": "is_logical", "char": "is_character", "complex": "is_complex", + "complex64": "is_complex<8>", "dict": "ASR::is_a", "list": "ASR::is_a", "tuple": "ASR::is_a" @@ -559,6 +924,11 @@ def compute_arg_types(indent, no_of_args, args_arr): for i in range(no_of_args): src += indent + f"ASR::ttype_t *arg_type{i} = ASRUtils::expr_type({args_arr}[{i}]);\n" +def compute_arg_kinds(indent, no_of_args): + global src + for i in range(no_of_args): + src += indent + f"int kind{i} = ASRUtils::extract_kind_from_ttype_t(arg_type{i});\n" + def compute_arg_condition(no_of_args, args_lists): condition = [] cond_in_msg = [] @@ -573,9 +943,16 @@ def compute_arg_condition(no_of_args, args_lists): cond_in_msg.append(", ".join(subcond_in_msg)) return (f"({') || ('.join(condition)})", f"({') or ('.join(cond_in_msg)})") +def compute_kind_condition(no_of_args): + condition = [] + for i in range(1, no_of_args): + condition.append(f"kind0 == kind{i}") + return f"({') && ('.join(condition)})" + def add_verify_arg_type_src(func_name): global src arg_infos = intrinsic_funcs_args[func_name] + same_kind_arg = arg_infos[0].get("same_kind_arg", False) no_of_args_msg = "" for i, arg_info in enumerate(arg_infos): args_lists = arg_info["args"] @@ -588,6 +965,10 @@ def add_verify_arg_type_src(func_name): compute_arg_types(3 * indent, no_of_args, "x.m_args") condition, cond_in_msg = compute_arg_condition(no_of_args, args_lists) src += 3 * indent + f'ASRUtils::require_impl({condition}, "Unexpected args, {func_name} expects {cond_in_msg} as arguments", x.base.base.loc, diagnostics);\n' + if same_kind_arg: + compute_arg_kinds(3 * indent, same_kind_arg) + condition = compute_kind_condition(same_kind_arg) + src += 3 * indent + f'ASRUtils::require_impl({condition}, "Kind of all the arguments of {func_name} must be the same", x.base.base.loc, diagnostics);\n' src += 2 * indent + "}\n" src += 2 * indent + "else {\n" src += 3 * indent + f'ASRUtils::require_impl(false, "Unexpected number of args, {func_name} takes {no_of_args_msg} arguments, found " + std::to_string(x.n_args), x.base.base.loc, diagnostics);\n' @@ -617,6 +998,7 @@ def add_create_func_arg_type_src(func_name): for i, arg_info in enumerate(arg_infos): args_lists = arg_info["args"] kind_arg = arg_info.get("kind_arg", False) + same_kind_arg = arg_info.get("same_kind_arg", False) no_of_args = len(args_lists[0]) no_of_args_msg += " or " if i > 0 else "" no_of_args_msg += f"{no_of_args + int(kind_arg)}" @@ -628,6 +1010,13 @@ def add_create_func_arg_type_src(func_name): src += 4 * indent + f'append_error(diag, "Unexpected args, {func_name} expects {cond_in_msg} as arguments", loc);\n' src += 4 * indent + f'return nullptr;\n' src += 3 * indent + '}\n' + if same_kind_arg: + compute_arg_kinds(3 * indent, same_kind_arg) + condition = compute_kind_condition(same_kind_arg) + src += 3 * indent + f'if(!({condition}))' + ' {\n' + src += 4 * indent + f'append_error(diag, "Kind of all the arguments of {func_name} must be the same", loc);\n' + src += 4 * indent + f'return nullptr;\n' + src += 3 * indent + '}\n' src += 2 * indent + "}\n" src += 2 * indent + "else {\n" src += 3 * indent + f'append_error(diag, "Unexpected number of args, {func_name} takes {no_of_args_msg} arguments, found " + std::to_string(args.size()), loc);\n' @@ -647,19 +1036,37 @@ def add_create_func_return_src(func_name): else: src += indent * 2 + "ASRUtils::ExprStmtDuplicator expr_duplicator(al);\n" src += indent * 2 + "expr_duplicator.allow_procedure_calls = true;\n" - src += indent * 2 + f"ASR::ttype_t* type_ = expr_duplicator.duplicate_ttype(expr_type(args[{ret_type_arg_idx}]));\n" + if ( ret_type_arg_idx == "dynamic"): + src += indent * 2 + f"int upper_kind = 0;\n" + src += indent * 2 + f"for(size_t i=0;i(*expr_type(args[1])) || !extract_value(args[1], kind)) {\n" + src += indent * 3 + "if (!ASR::is_a(*expr_type(args[1])) || !extract_value(ASRUtils::expr_value(args[1]), kind)) {\n" src += indent * 4 + f'append_error(diag, "`kind` argument of the `{func_name}` function must be a scalar Integer constant", args[1]->base.loc);\n' src += indent * 4 + "return nullptr;\n" src += indent * 3 + "}\n" src += indent * 3 + "set_kind_to_ttype_t(return_type, kind);\n" src += indent * 2 + "}\n" + real_32_except_complex = arg_infos[0].get("real_32_except_complex", False) + if real_32_except_complex: + src += indent * 2 + "else { \n" + src += indent * 3 + "ASR::ttype_t* arg_type = ASRUtils::expr_type(args[0]);\n" + src += indent * 3 + "if (is_complex(*arg_type)) { \n" + src += indent * 4 + "int kind = ASRUtils::extract_kind_from_ttype_t(arg_type); \n" + src += indent * 4 + "set_kind_to_ttype_t(return_type, kind); \n" + src += indent * 3 + "} \n" + src += indent * 2 + "} \n" src += indent * 2 + "ASR::expr_t *m_value = nullptr;\n" src += indent * 2 + f"Vec m_args; m_args.reserve(al, {no_of_args});\n" for _i in range(no_of_args): @@ -667,16 +1074,34 @@ def add_create_func_return_src(func_name): if func_name in compile_time_only_fn: src += indent * 2 + f"return_type = ASRUtils::extract_type(return_type);\n" src += indent * 2 + f"m_value = eval_{func_name}(al, loc, return_type, args, diag);\n" + src += indent * 3 + "if (diag.has_error()) {\n" + src += indent * 4 + f"return nullptr;\n" + src += indent * 3 + "}\n" src += indent * 2 + "return ASR::make_TypeInquiry_t(al, loc, "\ f"static_cast(IntrinsicElementalFunctions::{func_name}), "\ "ASRUtils::expr_type(m_args[0]), m_args[0], return_type, m_value);\n" else: + src += indent * 2 + f"for( size_t i = 0; i < {no_of_args}; i++ ) " + "{\n" + src += indent * 3 + "ASR::ttype_t* type = ASRUtils::expr_type(args[i]);\n" + src += indent * 3 + "if (ASRUtils::is_array(type)) {\n" + src += indent * 4 + "ASR::dimension_t* m_dims = nullptr;\n" + src += indent * 4 + "size_t n_dims = ASRUtils::extract_dimensions_from_ttype(type, m_dims);\n" + src += indent * 4 + "return_type = ASRUtils::make_Array_t_util(al, type->base.loc, " + src += "return_type, m_dims, n_dims, ASR::abiType::Source, false, " + src += "ASR::array_physical_typeType::DescriptorArray);\n" + src += indent * 4 + "break;\n" + src += indent * 3 + "}\n" + src += indent * 2 + "}\n" + src += indent * 2 + "if (all_args_evaluated(m_args)) {\n" src += indent * 3 + f"Vec args_values; args_values.reserve(al, {no_of_args});\n" for _i in range(no_of_args): src += indent * 3 + f"args_values.push_back(al, expr_value(m_args[{_i}]));\n" src += indent * 3 + f"m_value = eval_{func_name}(al, loc, return_type, args_values, diag);\n" + src += indent * 3 + "if (diag.has_error()) {\n" + src += indent * 4 + f"return nullptr;\n" + src += indent * 3 + "}\n" src += indent * 2 + "}\n" if "null" in intrinsic_funcs_ret_type.get(func_name, []): src += indent * 2 + f"return ASR::make_Expr_t(al, loc, ASRUtils::EXPR(ASR::make_IntrinsicElementalFunction_t(al, loc, static_cast(IntrinsicElementalFunctions::{func_name}), m_args.p, m_args.n, 0, return_type, m_value)));\n" @@ -717,6 +1142,7 @@ def get_registry_funcs_src(): HEAD = """#ifndef LIBASR_PASS_INTRINSIC_FUNC_REG_UTIL_H #define LIBASR_PASS_INTRINSIC_FUNC_REG_UTIL_H +#include #include namespace LCompilers { diff --git a/src/libasr/location.h b/src/libasr/location.h index fa3a684178..1fab1a7cc4 100644 --- a/src/libasr/location.h +++ b/src/libasr/location.h @@ -115,6 +115,7 @@ struct LocationManager { // imported then the location starts from the size of the previous file. // For example: file_ends = [120, 200, 350] std::vector file_ends; // position of all ends of files + // TODO: store file_ends of input files // For a given Location, we use the `file_ends` and `bisection` to determine // the file (files' index), which the location is from. Then we use this index into // the `files` vector and use `in_newlines` and other information to @@ -128,7 +129,7 @@ struct LocationManager { uint32_t output_to_input_pos(uint32_t out_pos, bool show_last) const { // Determine where the error is from using position, i.e., loc uint32_t index = bisection(file_ends, out_pos); - if (index == file_ends.size()) index -= 1; + if (index != 0 && index == file_ends.size()) index -= 1; if (files[index].out_start.size() == 0) return 0; uint32_t interval = bisection(files[index].out_start, out_pos)-1; uint32_t rel_pos = out_pos - files[index].out_start[interval]; @@ -159,6 +160,59 @@ struct LocationManager { } } + uint32_t input_to_output_pos(uint32_t in_pos, bool show_last) const { + + // Determine where the error is from using position, i.e., loc + uint32_t index = bisection(file_ends, in_pos); // seems this is with respect to output, TODO: change it to input file ends + if (index != 0 && index == file_ends.size()) index -= 1; + if (files[index].in_start.size() == 0) return 0; + uint32_t interval = bisection(files[index].in_start, in_pos)-1; + uint32_t rel_pos = in_pos - files[index].in_start[interval]; + uint32_t out_pos = files[index].out_start[interval] + rel_pos; + if (files[index].preprocessor) { + // If preprocessor was used, do one more remapping + uint32_t interval0 = bisection(files[index].in_start0, in_pos)-1; + if (files[index].interval_type0[interval0] == 0) { + // 1:1 interval + uint32_t rel_pos0 = in_pos - files[index].in_start0[interval0]; + uint32_t out_pos0 = files[index].out_start0[interval0] + rel_pos0; + return out_pos0; + } else { + // many to many interval + uint32_t out_pos0; + if (in_pos == files[index].in_start0[interval0+1]-1 || show_last) { + // The end of the interval in "out" code + // Return the end of the interval in "in" code + out_pos0 = files[index].out_start0[interval0]+files[index].out_start0[interval0]-1; + } else { + // Otherwise return the beginning of the interval in "in" + out_pos0 = files[index].out_start0[interval0]; + } + return out_pos0; + } + } else { + return out_pos; + } + } + + // Converts given line and column to the position in the original code + // `line` and `col` starts from 1 + // uses precomputed `in_newlines` to compute the position + uint64_t linecol_to_pos(uint16_t line, uint16_t col) { + // use in_newlines and compute pos + uint64_t pos = 0; + uint64_t l = 1; + while(true) { + if (l == line) break; + if (l >= files[0].in_newlines.size()) return 0; + l++; + } + if ( l == 1 ) pos = 0; + else pos = files[0].in_newlines[l-2]; + pos = pos + col; + return pos; + } + // Converts a linear position `position` to a (line, col) tuple // `position` starts from 0 // `line` and `col` starts from 1 @@ -167,7 +221,7 @@ struct LocationManager { std::string &filename) const { // Determine where the error is from using position, i.e., loc uint32_t index = bisection(file_ends, position); - if (index == file_ends.size()) index -= 1; + if (index != 0 && index == file_ends.size()) index -= 1; filename = files[index].in_filename; // Get the actual location by subtracting the previous file size. if (index > 0) position -= file_ends[index - 1]; diff --git a/src/libasr/lsp.cpp b/src/libasr/lsp.cpp new file mode 100644 index 0000000000..6a25bdb44a --- /dev/null +++ b/src/libasr/lsp.cpp @@ -0,0 +1,546 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + +namespace LCompilers { + +LSP::DiagnosticSeverity diagnostic_level_to_lsp_severity(diag::Level level) +{ + switch (level) { + case diag::Level::Error: + return LSP::DiagnosticSeverity::Error; + case diag::Level::Warning: + return LSP::DiagnosticSeverity::Warning; + case diag::Level::Note: + return LSP::DiagnosticSeverity::Information; + case diag::Level::Help: + return LSP::DiagnosticSeverity::Hint; + default: + return LSP::DiagnosticSeverity::Warning; + } +} + +LSP::SymbolKind asr_symbol_type_to_lsp_symbol_kind(ASR::symbolType symbol_type) +{ + switch (symbol_type) { + case ASR::symbolType::Module: + return LSP::SymbolKind::Module; + case ASR::symbolType::Function: + return LSP::SymbolKind::Function; + case ASR::symbolType::GenericProcedure: + return LSP::SymbolKind::Function; + case ASR::symbolType::CustomOperator: + return LSP::SymbolKind::Operator; + case ASR::symbolType::Struct: + return LSP::SymbolKind::Struct; + case ASR::symbolType::Enum: + return LSP::SymbolKind::Enum; + case ASR::symbolType::Variable: + return LSP::SymbolKind::Variable; + case ASR::symbolType::Class: + return LSP::SymbolKind::Class; + case ASR::symbolType::ClassProcedure: + return LSP::SymbolKind::Method; + case ASR::symbolType::Template: + return LSP::SymbolKind::TypeParameter; + default: + return LSP::SymbolKind::Function; + } +} + +enum LFortranJSONType { + kArrayType, kObjectType +}; + +class LFortranJSON { +private: + LFortranJSONType type; + std::string json_value; + std::vector> object_members; + std::vector array_values; + bool rebuild_needed; + +public: + LFortranJSON(LFortranJSONType type) : type(type), rebuild_needed(true) { + if (type == kArrayType) { + json_value = "[]"; + } else { + json_value = "{}"; + } + } + void SetObject() { + type = kObjectType; + object_members.clear(); + json_value = "{}"; + rebuild_needed = false; + } + void SetArray() { + type = kArrayType; + array_values.clear(); + json_value = "[]"; + rebuild_needed = false; + } + void AddMember(std::string key, int v) { + object_members.push_back({key, std::to_string(v)}); + rebuild_needed = true; + } + void AddMember(std::string key, uint32_t v) { + object_members.push_back({key, std::to_string(v)}); + rebuild_needed = true; + } + void AddMember(std::string key, std::string v) { + object_members.push_back({key, "\"" + v + "\""}); + rebuild_needed = true; + } + void AddMember(std::string key, LFortranJSON v) { + object_members.push_back({key, v.GetValue()}); + rebuild_needed = true; + } + void PushBack(LFortranJSON v) { + array_values.push_back(v.GetValue()); + rebuild_needed = true; + } + std::string GetValue() { + if (rebuild_needed) { + RebuildJSON(); + rebuild_needed = false; + } + return json_value; + } + +private: + void RebuildJSON() { + if (type == kObjectType) { + json_value = "{"; + for (size_t i = 0; i < object_members.size(); i++) { + json_value += "\"" + object_members[i].first + "\":" + object_members[i].second; + if (i < object_members.size() - 1) { + json_value += ","; + } + } + json_value += "}"; + } else if (type == kArrayType) { + json_value = "["; + for (size_t i = 0; i < array_values.size(); i++) { + json_value += array_values[i]; + if (i < array_values.size() - 1) { + json_value += ","; + } + } + json_value += "]"; + } + } +}; + +template +void populate_symbol_lists(T* x, LCompilers::LocationManager lm, std::vector &symbol_lists) { + LCompilers::document_symbols loc; + for (auto &a : x->m_symtab->get_scope()) { + std::string symbol_name = a.first; + uint32_t first_line; + uint32_t last_line; + uint32_t first_column; + uint32_t last_column; + std::string filename; + lm.pos_to_linecol(a.second->base.loc.first, first_line, + first_column, filename); + lm.pos_to_linecol(a.second->base.loc.last, last_line, + last_column, filename); + loc.first_column = first_column; + loc.last_column = last_column; + loc.first_line = first_line; + loc.last_line = last_line; + loc.symbol_name = symbol_name; + loc.filename = filename; + loc.symbol_type = a.second->type; + symbol_lists.push_back(loc); + if ( LCompilers::ASR::is_a(*a.second) ) { + LCompilers::ASR::Module_t *m = LCompilers::ASR::down_cast(a.second); + populate_symbol_lists(m, lm, symbol_lists); + } else if ( LCompilers::ASR::is_a(*a.second) ) { + LCompilers::ASR::Function_t *f = LCompilers::ASR::down_cast(a.second); + populate_symbol_lists(f, lm, symbol_lists); + } else if ( LCompilers::ASR::is_a(*a.second) ) { + LCompilers::ASR::Program_t *p = LCompilers::ASR::down_cast(a.second); + populate_symbol_lists(p, lm, symbol_lists); + } + } +} + +int get_symbols(const std::string &infile, CompilerOptions &compiler_options) +{ + std::string input = read_file(infile); + LCompilers::FortranEvaluator fe(compiler_options); + std::vector symbol_lists; + + LCompilers::LocationManager lm; + { + LCompilers::LocationManager::FileLocations fl; + fl.in_filename = infile; + lm.files.push_back(fl); + lm.file_ends.push_back(input.size()); + } + { + LCompilers::diag::Diagnostics diagnostics; + LCompilers::Result + x = fe.get_asr2(input, lm, diagnostics); + if (x.ok) { + populate_symbol_lists(x.result, lm, symbol_lists); + } else { + std::cout << "{}"; + return 0; + } + } + + LFortranJSON test_output(LFortranJSONType::kArrayType); + LFortranJSON range_object(LFortranJSONType::kObjectType); + LFortranJSON start_detail(LFortranJSONType::kObjectType); + LFortranJSON end_detail(LFortranJSONType::kObjectType); + LFortranJSON location_object(LFortranJSONType::kObjectType); + LFortranJSON test_capture(LFortranJSONType::kObjectType); + + test_output.SetArray(); + + for (auto symbol : symbol_lists) { + uint32_t start_character = symbol.first_column; + uint32_t start_line = symbol.first_line; + uint32_t end_character = symbol.last_column; + uint32_t end_line = symbol.last_line; + std::string name = symbol.symbol_name; + LSP::SymbolKind kind = asr_symbol_type_to_lsp_symbol_kind(symbol.symbol_type); + + range_object.SetObject(); + + start_detail.SetObject(); + start_detail.AddMember("character", start_character); + start_detail.AddMember("line", start_line); + range_object.AddMember("start", start_detail); + + end_detail.SetObject(); + end_detail.AddMember("character", end_character); + end_detail.AddMember("line", end_line); + range_object.AddMember("end", end_detail); + + location_object.SetObject(); + location_object.AddMember("range", range_object); + location_object.AddMember("uri", "uri"); + + test_capture.SetObject(); + test_capture.AddMember("kind", kind); + test_capture.AddMember("location", location_object); + test_capture.AddMember("name", name); + test_capture.AddMember("filename", symbol.filename); + test_output.PushBack(test_capture); + } + std::cout << test_output.GetValue(); + + return 0; +} + +int get_errors(const std::string &infile, CompilerOptions &compiler_options) +{ + std::string input = read_file(infile); + LCompilers::FortranEvaluator fe(compiler_options); + + LCompilers::LocationManager lm; + { + LCompilers::LocationManager::FileLocations fl; + fl.in_filename = infile; + lm.files.push_back(fl); + lm.file_ends.push_back(input.size()); + } + LCompilers::diag::Diagnostics diagnostics; + { + LCompilers::Result + result = fe.get_asr2(input, lm, diagnostics); + } + + std::vector diag_lists; + LCompilers::error_highlight h; + for (auto &d : diagnostics.diagnostics) { + if (compiler_options.no_warnings && d.level != LCompilers::diag::Level::Error) { + continue; + } + h.message = d.message; + h.severity = d.level; + for (auto label : d.labels) { + for (auto span : label.spans) { + uint32_t first_line; + uint32_t first_column; + uint32_t last_line; + uint32_t last_column; + std::string filename; + lm.pos_to_linecol(span.loc.first, first_line, first_column, + filename); + lm.pos_to_linecol(span.loc.last, last_line, last_column, + filename); + h.first_column = first_column; + h.last_column = last_column; + h.first_line = first_line; + h.last_line = last_line; + h.filename = filename; + diag_lists.push_back(h); + } + } + } + + LFortranJSON range_obj(LFortranJSONType::kObjectType); + LFortranJSON start_detail(LFortranJSONType::kObjectType); + LFortranJSON end_detail(LFortranJSONType::kObjectType); + LFortranJSON diag_results(LFortranJSONType::kArrayType); + LFortranJSON diag_capture(LFortranJSONType::kObjectType); + LFortranJSON message_send(LFortranJSONType::kObjectType); + LFortranJSON all_errors(LFortranJSONType::kArrayType); + all_errors.SetArray(); + + message_send.SetObject(); + message_send.AddMember("uri", "uri"); + + for (auto diag : diag_lists) { + uint32_t start_line = diag.first_line; + uint32_t start_column = diag.first_column; + uint32_t end_line = diag.last_line; + uint32_t end_column = diag.last_column; + LSP::DiagnosticSeverity severity = diagnostic_level_to_lsp_severity(diag.severity); + std::string msg = diag.message; + + range_obj.SetObject(); + + start_detail.SetObject(); + start_detail.AddMember("line", start_line); + start_detail.AddMember("character", start_column); + range_obj.AddMember("start", start_detail); + + end_detail.SetObject(); + end_detail.AddMember("line", end_line); + end_detail.AddMember("character", end_column); + range_obj.AddMember("end", end_detail); + + diag_capture.SetObject(); + diag_capture.AddMember("source", "lpyth"); + diag_capture.AddMember("range", range_obj); + diag_capture.AddMember("message", msg); + diag_capture.AddMember("severity", severity); + + all_errors.PushBack(diag_capture); + } + message_send.AddMember("diagnostics", all_errors); + std::cout << message_send.GetValue(); + + return 0; +} + +bool is_id_chr(const char c) +{ + return (('a' <= c) && (c <= 'z')) + || (('A' <= c) && (c <= 'Z')) + || (('0' <= c) && (c <= '9')) + || (c == '_'); +} + +int get_definitions(const std::string &infile, LCompilers::CompilerOptions &compiler_options) +{ + std::string input = read_file(infile); + LCompilers::FortranEvaluator fe(compiler_options); + std::vector symbol_lists; + + LCompilers::LocationManager lm; + { + LCompilers::LocationManager::FileLocations fl; + fl.in_filename = infile; + lm.files.push_back(fl); + lm.file_ends.push_back(input.size()); + } + { + LCompilers::diag::Diagnostics diagnostics; + LCompilers::Result + x = fe.get_asr2(input, lm, diagnostics); + if (x.ok) { + // populate_symbol_lists(x.result, lm, symbol_lists); + uint16_t l = std::stoi(compiler_options.line); + uint16_t c = std::stoi(compiler_options.column); + uint64_t input_pos = lm.linecol_to_pos(l, c); + if (c > 0 && input_pos > 0 && !is_id_chr(input[input_pos]) && is_id_chr(input[input_pos - 1])) { + // input_pos is to the right of the word boundary + input_pos--; + } + uint64_t output_pos = lm.input_to_output_pos(input_pos, false); + LCompilers::ASR::asr_t* asr = fe.handle_lookup_name(x.result, output_pos); + LCompilers::document_symbols loc; + if (!ASR::is_a(*asr)) { + std::cout << "[]"; + return 0; + } + ASR::symbol_t* s = ASR::down_cast(asr); + std::string symbol_name = ASRUtils::symbol_name( s ); + uint32_t first_line; + uint32_t last_line; + uint32_t first_column; + uint32_t last_column; + std::string filename; + lm.pos_to_linecol(lm.output_to_input_pos(asr->loc.first, false), first_line, + first_column, filename); + lm.pos_to_linecol(lm.output_to_input_pos(asr->loc.last, true), last_line, + last_column, filename); + loc.first_column = first_column; + loc.last_column = last_column; + loc.first_line = first_line; + loc.last_line = last_line; + loc.symbol_name = symbol_name; + loc.filename = filename; + loc.symbol_type = s->type; + symbol_lists.push_back(loc); + } else { + std::cout << "[]"; + return 0; + } + } + + LFortranJSON start_detail(LFortranJSONType::kObjectType); + LFortranJSON range_object(LFortranJSONType::kObjectType); + LFortranJSON end_detail(LFortranJSONType::kObjectType); + LFortranJSON location_object(LFortranJSONType::kObjectType); + LFortranJSON test_capture(LFortranJSONType::kObjectType); + LFortranJSON test_output(LFortranJSONType::kArrayType); + + test_output.SetArray(); + + for (auto symbol : symbol_lists) { + uint32_t start_character = symbol.first_column; + uint32_t start_line = symbol.first_line; + uint32_t end_character = symbol.last_column; + uint32_t end_line = symbol.last_line; + std::string name = symbol.symbol_name; + LSP::SymbolKind kind = asr_symbol_type_to_lsp_symbol_kind(symbol.symbol_type); + + range_object.SetObject(); + + start_detail.SetObject(); + start_detail.AddMember("character", start_character); + start_detail.AddMember("line", start_line); + range_object.AddMember("start", start_detail); + + end_detail.SetObject(); + end_detail.AddMember("character", end_character); + end_detail.AddMember("line", end_line); + range_object.AddMember("end", end_detail); + + location_object.SetObject(); + location_object.AddMember("range", range_object); + location_object.AddMember("uri", symbol.filename); + + test_capture.SetObject(); + test_capture.AddMember("kind", kind); + test_capture.AddMember("location", location_object); + test_capture.AddMember("name", name); + test_capture.AddMember("filename", symbol.filename); + test_output.PushBack(test_capture); + } + + std::cout << test_output.GetValue(); + + return 0; +} + +int get_all_occurences(const std::string &infile, LCompilers::CompilerOptions &compiler_options) +{ + std::string input = read_file(infile); + LCompilers::FortranEvaluator fe(compiler_options); + std::vector symbol_lists; + + LCompilers::LocationManager lm; + { + LCompilers::LocationManager::FileLocations fl; + fl.in_filename = infile; + lm.files.push_back(fl); + lm.file_ends.push_back(input.size()); + } + { + LCompilers::diag::Diagnostics diagnostics; + LCompilers::Result + x = fe.get_asr2(input, lm, diagnostics); + if (x.ok) { + // populate_symbol_lists(x.result, lm, symbol_lists); + uint16_t l = std::stoi(compiler_options.line); + uint16_t c = std::stoi(compiler_options.column); + uint64_t input_pos = lm.linecol_to_pos(l, c); + uint64_t output_pos = lm.input_to_output_pos(input_pos, false); + LCompilers::ASR::asr_t* asr = fe.handle_lookup_name(x.result, output_pos); + LCompilers::document_symbols loc; + if (!ASR::is_a(*asr)) { + std::cout << "[]"; + return 0; + } + ASR::symbol_t* s = ASR::down_cast(asr); + std::string symbol_name = ASRUtils::symbol_name( s ); + LCompilers::LFortran::OccurenceCollector occ(symbol_name, symbol_lists, lm); + occ.visit_TranslationUnit(*x.result); + } else { + std::cout << "[]"; + return 0; + } + } + + LFortranJSON start_detail(LFortranJSONType::kObjectType); + LFortranJSON range_object(LFortranJSONType::kObjectType); + LFortranJSON end_detail(LFortranJSONType::kObjectType); + LFortranJSON location_object(LFortranJSONType::kObjectType); + LFortranJSON test_capture(LFortranJSONType::kObjectType); + LFortranJSON test_output(LFortranJSONType::kArrayType); + + test_output.SetArray(); + + for (auto symbol : symbol_lists) { + uint32_t start_character = symbol.first_column; + uint32_t start_line = symbol.first_line; + uint32_t end_character = symbol.last_column; + uint32_t end_line = symbol.last_line; + std::string name = symbol.symbol_name; + LSP::SymbolKind kind = asr_symbol_type_to_lsp_symbol_kind(symbol.symbol_type); + + range_object.SetObject(); + + start_detail.SetObject(); + start_detail.AddMember("character", start_character); + start_detail.AddMember("line", start_line); + range_object.AddMember("start", start_detail); + + end_detail.SetObject(); + end_detail.AddMember("character", end_character); + end_detail.AddMember("line", end_line); + range_object.AddMember("end", end_detail); + + location_object.SetObject(); + location_object.AddMember("range", range_object); + location_object.AddMember("uri", "uri"); + + test_capture.SetObject(); + test_capture.AddMember("kind", kind); + test_capture.AddMember("location", location_object); + test_capture.AddMember("name", name); + test_output.PushBack(test_capture); + } + + std::cout << test_output.GetValue(); + + return 0; +} + +} + diff --git a/src/libasr/lsp_interface.h b/src/libasr/lsp_interface.h index fdb35ad7ec..1857879d17 100644 --- a/src/libasr/lsp_interface.h +++ b/src/libasr/lsp_interface.h @@ -3,7 +3,49 @@ #include +#include +#include + namespace LCompilers { + namespace LSP { + // These are the latest definitions per the LSP 3.17 spec. + + enum DiagnosticSeverity { + Error = 1, + Warning = 2, + Information = 3, + Hint = 4 + }; + + enum SymbolKind { + File = 1, + Module = 2, + Namespace = 3, + Package = 4, + Class = 5, + Method = 6, + Property = 7, + Field = 8, + Constructor = 9, + Enum = 10, + Interface = 11, + Function = 12, + Variable = 13, + Constant = 14, + String = 15, + Number = 16, + Boolean = 17, + Array = 18, + Object = 19, + Key = 20, + Null = 21, + EnumMember = 22, + Struct = 23, + Event = 24, + Operator = 25, + TypeParameter = 26 + }; + } // namespace LSP struct error_highlight { std::string message; @@ -12,8 +54,9 @@ namespace LCompilers { uint32_t last_line; uint32_t last_column; std::string filename; - uint32_t severity; + diag::Level severity; }; + struct document_symbols { std::string symbol_name; uint32_t first_line; @@ -21,6 +64,7 @@ namespace LCompilers { uint32_t last_line; uint32_t last_column; std::string filename; + ASR::symbolType symbol_type; }; } // namespace LCompilers diff --git a/src/libasr/modfile.cpp b/src/libasr/modfile.cpp index 25864da1ca..7865254bc9 100644 --- a/src/libasr/modfile.cpp +++ b/src/libasr/modfile.cpp @@ -11,7 +11,7 @@ namespace LCompilers { const std::string lfortran_modfile_type_string = "LCompilers Modfile"; -inline void save_asr(const ASR::TranslationUnit_t &m, std::string& asr_string) { +inline void save_asr(const ASR::TranslationUnit_t &m, std::string& asr_string, LCompilers::LocationManager lm) { #ifdef WITH_LFORTRAN_BINARY_MODFILES BinaryWriter b; #else @@ -33,6 +33,71 @@ inline void save_asr(const ASR::TranslationUnit_t &m, std::string& asr_string) { // Export ASR: // Currently empty. + // Full LocationManager: + b.write_int32(lm.files.size()); + for(auto file: lm.files) { + // std::vector files; + b.write_string(file.in_filename); + b.write_int32(file.current_line); + + // std::vector out_start + b.write_int32(file.out_start.size()); + for(auto i: file.out_start) { + b.write_int32(i); + } + + // std::vector in_start + b.write_int32(file.in_start.size()); + for(auto i: file.in_start) { + b.write_int32(i); + } + + // std::vector in_newlines + b.write_int32(file.in_newlines.size()); + for(auto i: file.in_newlines) { + b.write_int32(i); + } + + // bool preprocessor + b.write_int32(file.preprocessor); + + // std::vector out_start0 + b.write_int32(file.out_start0.size()); + for(auto i: file.out_start0) { + b.write_int32(i); + } + + // std::vector in_start0 + b.write_int32(file.in_start0.size()); + for(auto i: file.in_start0) { + b.write_int32(i); + } + + // std::vector in_size0 + b.write_int32(file.in_size0.size()); + for(auto i: file.in_size0) { + b.write_int32(i); + } + + // std::vector interval_type0 + b.write_int32(file.interval_type0.size()); + for(auto i: file.interval_type0) { + b.write_int32(i); + } + + // std::vector in_newlines0 + b.write_int32(file.in_newlines0.size()); + for(auto i: file.in_newlines0) { + b.write_int32(i); + } + } + + // std::vector file_ends + b.write_int32(lm.file_ends.size()); + for(auto i: lm.file_ends) { + b.write_int32(i); + } + // Full ASR: b.write_string(serialize(m)); @@ -51,7 +116,7 @@ inline void save_asr(const ASR::TranslationUnit_t &m, std::string& asr_string) { Comments below show some possible future improvements to the mod format. */ -std::string save_modfile(const ASR::TranslationUnit_t &m) { +std::string save_modfile(const ASR::TranslationUnit_t &m, LCompilers::LocationManager lm) { LCOMPILERS_ASSERT(m.m_symtab->get_scope().size()== 1); for (auto &a : m.m_symtab->get_scope()) { LCOMPILERS_ASSERT(ASR::is_a(*a.second)); @@ -59,17 +124,18 @@ std::string save_modfile(const ASR::TranslationUnit_t &m) { } std::string asr_string; - save_asr(m, asr_string); + save_asr(m, asr_string, lm); return asr_string; } -std::string save_pycfile(const ASR::TranslationUnit_t &m) { +std::string save_pycfile(const ASR::TranslationUnit_t &m, LCompilers::LocationManager lm) { std::string asr_string; - save_asr(m, asr_string); + save_asr(m, asr_string, lm); return asr_string; } -inline void load_serialised_asr(const std::string &s, std::string& asr_binary) { +inline void load_serialised_asr(const std::string &s, std::string& asr_binary, + LCompilers::LocationManager &lm) { #ifdef WITH_LFORTRAN_BINARY_MODFILES BinaryReader b(s); #else @@ -83,23 +149,87 @@ inline void load_serialised_asr(const std::string &s, std::string& asr_binary) { if (version != LFORTRAN_VERSION) { throw LCompilersException("Incompatible format: LFortran Modfile was generated using version '" + version + "', but current LFortran version is '" + LFORTRAN_VERSION + "'"); } + LCompilers::LocationManager serialized_lm; + int32_t n_files = b.read_int32(); + std::vector files; + for(int i=0; i(asr); return tu; } ASR::TranslationUnit_t* load_pycfile(Allocator &al, const std::string &s, - bool load_symtab_id) { + bool load_symtab_id, LCompilers::LocationManager &lm) { std::string asr_binary; - load_serialised_asr(s, asr_binary); - ASR::asr_t *asr = deserialize_asr(al, asr_binary, load_symtab_id); + load_serialised_asr(s, asr_binary, lm); + uint32_t offset = 0; + ASR::asr_t *asr = deserialize_asr(al, asr_binary, load_symtab_id, offset); ASR::TranslationUnit_t *tu = ASR::down_cast2(asr); return tu; diff --git a/src/libasr/modfile.h b/src/libasr/modfile.h index b331af42c9..87780e221b 100644 --- a/src/libasr/modfile.h +++ b/src/libasr/modfile.h @@ -6,16 +6,16 @@ namespace LCompilers { // Save a module to a modfile - std::string save_modfile(const ASR::TranslationUnit_t &m); + std::string save_modfile(const ASR::TranslationUnit_t &m, LCompilers::LocationManager lm); - std::string save_pycfile(const ASR::TranslationUnit_t &m); + std::string save_pycfile(const ASR::TranslationUnit_t &m, LCompilers::LocationManager lm); // Load a module from a modfile ASR::TranslationUnit_t* load_modfile(Allocator &al, const std::string &s, - bool load_symtab_id, SymbolTable &symtab); + bool load_symtab_id, SymbolTable &symtab, LCompilers::LocationManager &lm); ASR::TranslationUnit_t* load_pycfile(Allocator &al, const std::string &s, - bool load_symtab_id); + bool load_symtab_id, LCompilers::LocationManager &lm); } // namespace LCompilers diff --git a/src/libasr/pass/arr_slice.cpp b/src/libasr/pass/arr_slice.cpp index 45cfef3c9b..a1705a6a89 100644 --- a/src/libasr/pass/arr_slice.cpp +++ b/src/libasr/pass/arr_slice.cpp @@ -7,7 +7,6 @@ #include #include -#include namespace LCompilers { @@ -103,7 +102,7 @@ class ReplaceArraySection: public ASR::BaseExprReplacer { slice_counter += 1; char* new_var_name = s2c(al, new_name); ASR::ttype_t* slice_asr_type = get_array_from_slice(x, x_arr_var); - ASR::asr_t* slice_asr = ASR::make_Variable_t(al, x->base.base.loc, current_scope, new_var_name, nullptr, 0, + ASR::asr_t* slice_asr = ASRUtils::make_Variable_t_util(al, x->base.base.loc, current_scope, new_var_name, nullptr, 0, ASR::intentType::Local, nullptr, nullptr, ASR::storage_typeType::Default, slice_asr_type, nullptr, ASR::abiType::Source, ASR::accessType::Public, ASR::presenceType::Required, false); diff --git a/src/libasr/pass/array_op.cpp b/src/libasr/pass/array_op.cpp index ee313777db..3f53ec950c 100644 --- a/src/libasr/pass/array_op.cpp +++ b/src/libasr/pass/array_op.cpp @@ -8,2034 +8,1039 @@ #include #include +#include + #include -#include -/* -This ASR pass replaces operations over arrays with do loops. -The function `pass_replace_array_op` transforms the ASR tree in-place. +namespace LCompilers { -Converts: +class ArrayVarAddressReplacer: public ASR::BaseExprReplacer { - c = a + b + public: -to: + Allocator& al; + Vec& vars; - do i = lbound(a), ubound(a) - c(i) = a(i) + b(i) - end do + ArrayVarAddressReplacer(Allocator& al_, Vec& vars_): + al(al_), vars(vars_) { + call_replacer_on_value = false; + } -The code below might seem intriguing because of minor but crucial -details. Generally for any node, first, its children are visited. -If any child contains operations over arrays then, the do loop -pass is added for performing the operation element wise. For storing -the result, either a new variable is created or a result variable -available from the parent node is used. Once done, this result variable -is used by the parent node in place of the child node from which it was -made available. Consider the example below for better understanding. + void replace_ArraySize(ASR::ArraySize_t* /*x*/) { -Say, BinOp(BinOp(Arr1 Add Arr2) Add Arr3) is the expression we want -to visit. Then, first BinOp(Arr1 Add Arr2) will be visited and its -result will be stored (not actually, just extra ASR do loop node will be added) -in a new variable, Say Result1. Then this Result1 will be used as follows, -BinOp(Result1 Add Arr3). Imagine, this overall expression is further -assigned to some Fortran variable as, Assign(Var1, BinOp(Result1 Add Arr3)). -In this case a new variable will not be created to store the result of RHS, just Var1 -will be used as the final destination and a do loop pass will be added as follows, -do i = lbound(Var1), ubound(Var1) + } -Var1(i) = Result1(i) + Arr3(i) + void replace_ArrayBound(ASR::ArrayBound_t* /*x*/) { -end do + } -Note that once the control will reach the above loop, the loop for -Result1 would have already been executed. + void replace_Var(ASR::Var_t* x) { + if( ASRUtils::is_array(ASRUtils::symbol_type(x->m_v)) ) { + vars.push_back(al, current_expr); + } + } -All the nodes should be implemented using the above logic to track -array operations and perform the do loop pass. As of now, some of the -nodes are implemented and more are yet to be implemented with time. -*/ + void replace_StructInstanceMember(ASR::StructInstanceMember_t* x) { + if( !ASRUtils::is_array(x->m_type) ) { + return ; + } + if( ASRUtils::is_array(ASRUtils::symbol_type(x->m_m)) ) { + vars.push_back(al, current_expr); + } else { + ASR::BaseExprReplacer::replace_StructInstanceMember(x); + } + } -namespace LCompilers { + void replace_ArrayItem(ASR::ArrayItem_t* /*x*/) { + } -using ASR::down_cast; -using ASR::is_a; + void replace_IntrinsicArrayFunction(ASR::IntrinsicArrayFunction_t* /*x*/) { + } -class ReplaceArrayOp: public ASR::BaseExprReplacer { + void replace_FunctionCall(ASR::FunctionCall_t* x) { + if( !ASRUtils::is_elemental(x->m_name) ) { + return ; + } - private: + ASR::BaseExprReplacer::replace_FunctionCall(x); + } - Allocator& al; - Vec& pass_result; - size_t result_counter; - bool& use_custom_loop_params; - Vec& result_lbound; - Vec& result_ubound; - Vec& result_inc; - ASR::dimension_t* op_dims; size_t op_n_dims; - ASR::expr_t* op_expr; - std::map& resultvar2value; - bool realloc_lhs; +}; - public: +class ArrayVarAddressCollector: public ASR::CallReplacerOnExpressionsVisitor { - SymbolTable* current_scope; - ASR::expr_t* result_var; - ASR::ttype_t* result_type; + private: - ReplaceArrayOp(Allocator& al_, Vec& pass_result_, - bool& use_custom_loop_params_, - Vec& result_lbound_, - Vec& result_ubound_, - Vec& result_inc_, - std::map& resultvar2value_, - bool realloc_lhs_) : - al(al_), pass_result(pass_result_), - result_counter(0), use_custom_loop_params(use_custom_loop_params_), - result_lbound(result_lbound_), result_ubound(result_ubound_), - result_inc(result_inc_), op_dims(nullptr), op_n_dims(0), - op_expr(nullptr), resultvar2value(resultvar2value_), - realloc_lhs(realloc_lhs_), current_scope(nullptr), - result_var(nullptr), result_type(nullptr) {} - - template - void create_do_loop(const Location& loc, int var_rank, int result_rank, - Vec& idx_vars, Vec& loop_vars, - Vec& idx_vars_value1, Vec& idx_vars_value2, std::vector& loop_var_indices, - Vec& doloop_body, ASR::expr_t* op_expr1, ASR::expr_t* op_expr2, int op_expr_dim_offset, - LOOP_BODY loop_body) { - PassUtils::create_idx_vars(idx_vars_value1, var_rank, loc, al, current_scope, "_v"); - if (op_expr2 != nullptr) { - PassUtils::create_idx_vars(idx_vars_value2, var_rank, loc, al, current_scope, "_u"); - } - if( use_custom_loop_params ) { - PassUtils::create_idx_vars(idx_vars, loop_vars, loop_var_indices, - result_ubound, result_inc, - loc, al, current_scope, "_t"); - } else { - PassUtils::create_idx_vars(idx_vars, result_rank, loc, al, current_scope, "_t"); - loop_vars.from_pointer_n_copy(al, idx_vars.p, idx_vars.size()); - } - ASR::stmt_t* doloop = nullptr; - LCOMPILERS_ASSERT(result_rank >= var_rank); - // LCOMPILERS_ASSERT(var_rank == (int) loop_vars.size()); - ASR::ttype_t* int32_type = ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)); - ASR::expr_t* const_1 = ASRUtils::EXPR(ASR::make_IntegerConstant_t(al, loc, 1, int32_type)); - if (var_rank == (int) loop_vars.size()) { - for( int i = var_rank - 1; i >= 0; i-- ) { - // TODO: Add an If debug node to check if the lower and upper bounds of both the arrays are same. - ASR::do_loop_head_t head; - head.m_v = loop_vars[i]; - if( use_custom_loop_params ) { - int j = loop_var_indices[i]; - head.m_start = result_lbound[j]; - head.m_end = result_ubound[j]; - head.m_increment = result_inc[j]; - } else { - ASR::expr_t* var = result_var; - if (ASR::is_a(*result_var)) { - ASR::ComplexConstructor_t* cc = ASR::down_cast(result_var); - var = cc->m_re; - } - head.m_start = PassUtils::get_bound(var, i + 1, "lbound", al); - head.m_end = PassUtils::get_bound(var, i + 1, "ubound", al); - head.m_increment = nullptr; - } - head.loc = head.m_v->base.loc; - doloop_body.reserve(al, 1); - if( doloop == nullptr ) { - loop_body(); - } else { - if( var_rank > 0 ) { - ASR::expr_t* idx_lb = PassUtils::get_bound(op_expr1, i + op_expr_dim_offset, "lbound", al); - ASR::stmt_t* set_to_one = ASRUtils::STMT(ASR::make_Assignment_t( - al, loc, idx_vars_value1[i+1], idx_lb, nullptr)); - doloop_body.push_back(al, set_to_one); - - if (op_expr2 != nullptr) { - ASR::expr_t* idx_lb2 = PassUtils::get_bound(op_expr2, i + op_expr_dim_offset, "lbound", al); - ASR::stmt_t* set_to_one2 = ASRUtils::STMT(ASR::make_Assignment_t( - al, loc, idx_vars_value2[i+1], idx_lb2, nullptr)); - doloop_body.push_back(al, set_to_one2); - } - } - doloop_body.push_back(al, doloop); - } - if( var_rank > 0 ) { - ASR::expr_t* inc_expr = ASRUtils::EXPR(ASR::make_IntegerBinOp_t( - al, loc, idx_vars_value1[i], ASR::binopType::Add, const_1, int32_type, nullptr)); - ASR::stmt_t* assign_stmt = ASRUtils::STMT(ASR::make_Assignment_t( - al, loc, idx_vars_value1[i], inc_expr, nullptr)); - doloop_body.push_back(al, assign_stmt); - - if (op_expr2 != nullptr) { - ASR::expr_t* inc_expr2 = ASRUtils::EXPR(ASR::make_IntegerBinOp_t( - al, loc, idx_vars_value2[i], ASR::binopType::Add, const_1, int32_type, nullptr)); - ASR::stmt_t* assign_stmt2 = ASRUtils::STMT(ASR::make_Assignment_t( - al, loc, idx_vars_value2[i], inc_expr2, nullptr)); - doloop_body.push_back(al, assign_stmt2); - } - } - doloop = ASRUtils::STMT(ASR::make_DoLoop_t(al, loc, nullptr, head, doloop_body.p, doloop_body.size(), nullptr, 0)); - } - if( var_rank > 0 ) { - ASR::expr_t* expr = op_expr1; - if (ASR::is_a(*op_expr1)) { - ASR::ComplexConstructor_t* cc = ASR::down_cast(op_expr1); - expr = cc->m_re; - } - ASR::expr_t* idx_lb = PassUtils::get_bound(expr, 1, "lbound", al); - ASR::stmt_t* set_to_one = ASRUtils::STMT(ASR::make_Assignment_t(al, loc, idx_vars_value1[0], idx_lb, nullptr)); - pass_result.push_back(al, set_to_one); - - if (op_expr2 != nullptr) { - ASR::expr_t* idx_lb2 = PassUtils::get_bound(op_expr2, 1, "lbound", al); - ASR::stmt_t* set_to_one2 = ASRUtils::STMT(ASR::make_Assignment_t(al, loc, idx_vars_value2[0], idx_lb2, nullptr)); - pass_result.push_back(al, set_to_one2); - } - } - pass_result.push_back(al, doloop); - } else if (var_rank == 0) { - for( int i = loop_vars.size() - 1; i >= 0; i-- ) { - // TODO: Add an If debug node to check if the lower and upper bounds of both the arrays are same. - ASR::do_loop_head_t head; - head.m_v = loop_vars[i]; - if( use_custom_loop_params ) { - int j = loop_var_indices[i]; - head.m_start = result_lbound[j]; - head.m_end = result_ubound[j]; - head.m_increment = result_inc[j]; - } else { - head.m_start = PassUtils::get_bound(result_var, i + 1, "lbound", al); - head.m_end = PassUtils::get_bound(result_var, i + 1, "ubound", al); - head.m_increment = nullptr; - } - head.loc = head.m_v->base.loc; - doloop_body.reserve(al, 1); - if( doloop == nullptr ) { - loop_body(); - } else { - doloop_body.push_back(al, doloop); - } - doloop = ASRUtils::STMT(ASR::make_DoLoop_t(al, loc, nullptr, head, doloop_body.p, doloop_body.size(), nullptr, 0)); - } - pass_result.push_back(al, doloop); - } + ArrayVarAddressReplacer replacer; + + public: + void call_replacer() { + replacer.current_expr = current_expr; + replacer.replace_expr(*current_expr); } - template - void replace_vars_helper(T* x) { - if( op_expr == *current_expr ) { - ASR::ttype_t* current_expr_type = ASRUtils::expr_type(*current_expr); - op_n_dims = ASRUtils::extract_dimensions_from_ttype(current_expr_type, op_dims); - } - if( !(result_var != nullptr && PassUtils::is_array(result_var) && - resultvar2value.find(result_var) != resultvar2value.end() && - resultvar2value[result_var] == &(x->base)) ) { - return ; - } + ArrayVarAddressCollector(Allocator& al_, Vec& vars_): + replacer(al_, vars_) { + visit_expr_after_replacement = false; + } - const Location& loc = x->base.base.loc; - if( (ASR::is_a(*ASRUtils::expr_type(result_var)) && - ASRUtils::is_array(ASRUtils::expr_type(*current_expr)) && realloc_lhs && - !use_custom_loop_params) || - (ASR::is_a(*ASRUtils::expr_type(result_var)) && - ASRUtils::is_array(ASRUtils::expr_type(*current_expr)) && - ASR::is_a(*ASRUtils::expr_type(*current_expr))) ) { - ASR::ttype_t* result_var_type = ASRUtils::expr_type(result_var); - Vec result_var_m_dims; - size_t result_var_n_dims = ASRUtils::extract_n_dims_from_ttype(result_var_type); - result_var_m_dims.reserve(al, result_var_n_dims); - ASR::alloc_arg_t result_alloc_arg; - result_alloc_arg.loc = loc; - result_alloc_arg.m_a = result_var; - for( size_t i = 0; i < result_var_n_dims; i++ ) { - ASR::dimension_t result_var_dim; - result_var_dim.loc = loc; - result_var_dim.m_start = make_ConstantWithKind( - make_IntegerConstant_t, make_Integer_t, 1, 4, loc); - result_var_dim.m_length = ASRUtils::get_size(*current_expr, i + 1, al); - result_var_m_dims.push_back(al, result_var_dim); - } - result_alloc_arg.m_dims = result_var_m_dims.p; - result_alloc_arg.n_dims = result_var_n_dims; - result_alloc_arg.m_len_expr = nullptr; - result_alloc_arg.m_type = nullptr; - Vec alloc_result_args; alloc_result_args.reserve(al, 1); - alloc_result_args.push_back(al, result_alloc_arg); - pass_result.push_back(al, ASRUtils::STMT(ASR::make_ReAlloc_t( - al, loc, alloc_result_args.p, 1))); - } - int var_rank = PassUtils::get_rank(*current_expr); - int result_rank = PassUtils::get_rank(result_var); - Vec idx_vars, loop_vars, idx_vars_value; - std::vector loop_var_indices; - Vec doloop_body; - create_do_loop(loc, var_rank, result_rank, idx_vars, - loop_vars, idx_vars_value, idx_vars_value, loop_var_indices, doloop_body, - *current_expr, nullptr, 2, - [=, &idx_vars_value, &idx_vars, &doloop_body]() { - ASR::expr_t* ref = nullptr; - if( var_rank > 0 ) { - if (ASR::is_a(**current_expr)) { - ASR::ComplexConstructor_t* cc = ASR::down_cast(*current_expr); - ASR::expr_t* re = PassUtils::create_array_ref(cc->m_re, idx_vars_value, al, current_scope); - ASR::expr_t* im = PassUtils::create_array_ref(cc->m_im, idx_vars_value, al, current_scope); - ref = ASRUtils::EXPR(ASR::make_ComplexConstructor_t(al, loc, re, im, cc->m_type, cc->m_value)); - *current_expr = ref; - } else { - ref = PassUtils::create_array_ref(*current_expr, idx_vars_value, al, current_scope); - } - } else { - ref = *current_expr; - } - LCOMPILERS_ASSERT(result_var != nullptr); - ASR::expr_t* res = PassUtils::create_array_ref(result_var, idx_vars, al, current_scope); - ASR::stmt_t* assign = ASRUtils::STMT(ASR::make_Assignment_t(al, loc, res, ref, nullptr)); - doloop_body.push_back(al, assign); - }); - *current_expr = nullptr; - result_var = nullptr; - use_custom_loop_params = false; + void visit_Allocate(const ASR::Allocate_t& /*x*/) { } - #define allocate_result_var(op_arg, op_dims_arg, op_n_dims_arg, result_var_created, reset_bounds) if( ASR::is_a(*ASRUtils::expr_type(result_var)) || \ - ASR::is_a(*ASRUtils::expr_type(result_var)) ) { \ - bool is_dimension_empty = false; \ - for( int i = 0; i < op_n_dims_arg; i++ ) { \ - if( op_dims_arg->m_length == nullptr ) { \ - is_dimension_empty = true; \ - break; \ - } \ - } \ - ASR::ttype_t* int32_type = ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)); \ - Vec alloc_args; \ - alloc_args.reserve(al, 1); \ - if( !is_dimension_empty ) { \ - ASR::alloc_arg_t alloc_arg; \ - alloc_arg.loc = loc; \ - alloc_arg.m_len_expr = nullptr; \ - alloc_arg.m_type = nullptr; \ - alloc_arg.m_a = result_var; \ - alloc_arg.m_dims = op_dims_arg; \ - alloc_arg.n_dims = op_n_dims_arg; \ - alloc_args.push_back(al, alloc_arg); \ - op_dims = op_dims_arg; \ - op_n_dims = op_n_dims_arg; \ - } else { \ - Vec alloc_dims; \ - alloc_dims.reserve(al, op_n_dims_arg); \ - for( int i = 0; i < op_n_dims_arg; i++ ) { \ - ASR::dimension_t alloc_dim; \ - alloc_dim.loc = loc; \ - if( reset_bounds && result_var_created ) { \ - alloc_dim.m_start = make_ConstantWithKind(make_IntegerConstant_t, make_Integer_t, 1, 4, loc); \ - } else { \ - alloc_dim.m_start = PassUtils::get_bound(op_arg, i + 1, "lbound", al); \ - alloc_dim.m_start = CastingUtil::perform_casting(alloc_dim.m_start, \ - int32_type, al, loc); \ - } \ - ASR::expr_t* lbound = PassUtils::get_bound(op_arg, i + 1, "lbound", al); \ - lbound = CastingUtil::perform_casting(lbound, int32_type, al, loc); \ - ASR::expr_t* ubound = PassUtils::get_bound(op_arg, i + 1, "ubound", al); \ - ubound = CastingUtil::perform_casting(ubound, int32_type, al, loc); \ - alloc_dim.m_length = ASRUtils::compute_length_from_start_end(al, lbound, ubound); \ - alloc_dims.push_back(al, alloc_dim); \ - } \ - ASR::alloc_arg_t alloc_arg; \ - alloc_arg.loc = loc; \ - alloc_arg.m_len_expr = nullptr; \ - alloc_arg.m_type = nullptr; \ - alloc_arg.m_a = result_var; \ - alloc_arg.m_dims = alloc_dims.p; \ - alloc_arg.n_dims = alloc_dims.size(); \ - alloc_args.push_back(al, alloc_arg); \ - op_dims = alloc_dims.p; \ - op_n_dims = alloc_dims.size(); \ - } \ - Vec to_be_deallocated; \ - to_be_deallocated.reserve(al, alloc_args.size()); \ - for( size_t i = 0; i < alloc_args.size(); i++ ) { \ - to_be_deallocated.push_back(al, alloc_args.p[i].m_a); \ - } \ - pass_result.push_back(al, ASRUtils::STMT(ASR::make_ExplicitDeallocate_t( \ - al, loc, to_be_deallocated.p, to_be_deallocated.size()))); \ - pass_result.push_back(al, ASRUtils::STMT(ASR::make_Allocate_t(al, \ - loc, alloc_args.p, alloc_args.size(), nullptr, nullptr, nullptr))); \ + void visit_ExplicitDeallocate(const ASR::ExplicitDeallocate_t& /*x*/) { } - void replace_StructInstanceMember(ASR::StructInstanceMember_t* x) { - if( ASRUtils::is_array(ASRUtils::expr_type(x->m_v)) && - !ASRUtils::is_array(ASRUtils::symbol_type(x->m_m)) ) { - ASR::BaseExprReplacer::replace_StructInstanceMember(x); - const Location& loc = x->base.base.loc; - ASR::expr_t* arr_expr = x->m_v; - ASR::dimension_t* arr_expr_dims = nullptr; int arr_expr_n_dims; int n_dims; - arr_expr_n_dims = ASRUtils::extract_dimensions_from_ttype(x->m_type, arr_expr_dims); - n_dims = arr_expr_n_dims; - - if( result_var == nullptr ) { - bool allocate = false; - ASR::ttype_t* result_var_type = get_result_type(x->m_type, - arr_expr_dims, arr_expr_n_dims, loc, x->class_type, allocate); - if( allocate ) { - result_var_type = ASRUtils::TYPE(ASR::make_Allocatable_t(al, loc, - ASRUtils::type_get_past_allocatable(result_var_type))); - } - result_var = PassUtils::create_var( - result_counter, "_array_struct_instance_member", loc, - result_var_type, al, current_scope); - result_counter += 1; - if( allocate ) { - allocate_result_var(arr_expr, arr_expr_dims, arr_expr_n_dims, true, false); - } - } + void visit_ImplicitDeallocate(const ASR::ImplicitDeallocate_t& /*x*/) { + } - Vec idx_vars, idx_vars_value, loop_vars; - Vec doloop_body; - std::vector loop_var_indices; - int result_rank = PassUtils::get_rank(result_var); - op_expr = arr_expr; - create_do_loop(loc, n_dims, result_rank, idx_vars, - loop_vars, idx_vars_value, idx_vars_value, loop_var_indices, doloop_body, - op_expr, nullptr, 2, [=, &arr_expr, &idx_vars, &idx_vars_value, &doloop_body]() { - ASR::expr_t* ref = PassUtils::create_array_ref(arr_expr, idx_vars_value, al); - LCOMPILERS_ASSERT(result_var != nullptr); - ASR::expr_t* res = PassUtils::create_array_ref(result_var, idx_vars, al); - ASR::expr_t* op_el_wise = ASRUtils::EXPR(ASR::make_StructInstanceMember_t( - al, loc, ref, x->m_m, ASRUtils::extract_type(x->m_type), nullptr)); - ASR::stmt_t* assign = ASRUtils::STMT(ASR::make_Assignment_t(al, loc, res, op_el_wise, nullptr)); - doloop_body.push_back(al, assign); - }); - *current_expr = result_var; - result_var = nullptr; - } else { - replace_vars_helper(x); + void visit_SubroutineCall(const ASR::SubroutineCall_t& x) { + if( !PassUtils::is_elemental(x.m_name) ) { + return ; } } - void replace_Var(ASR::Var_t* x) { - replace_vars_helper(x); + void visit_Associate(const ASR::Associate_t& /*x*/) { } - void replace_ArrayItem(ASR::ArrayItem_t* x) { - replace_vars_helper(x); + void visit_CPtrToPointer(const ASR::CPtrToPointer_t& /*x*/) { } - void replace_ComplexConstructor(ASR::ComplexConstructor_t* x) { - LCOMPILERS_ASSERT( !ASRUtils::is_array(x->m_type) ); - replace_vars_helper(x); - } +}; - void replace_ArrayBroadcast(ASR::ArrayBroadcast_t* x) { - ASR::expr_t** current_expr_copy_161 = current_expr; - current_expr = &(x->m_array); - replace_expr(x->m_array); - current_expr = current_expr_copy_161; - *current_expr = x->m_array; +class FixTypeVisitor: public ASR::CallReplacerOnExpressionsVisitor { + public: + + FixTypeVisitor(Allocator& al_) { + (void)al_; // Explicitly mark the parameter as unused } - template - void create_do_loop(const Location& loc, int result_rank, - Vec& idx_vars, Vec& idx_vars_value, - Vec& loop_vars, std::vector& loop_var_indices, - Vec& doloop_body, ASR::expr_t* op_expr, LOOP_BODY loop_body) { - PassUtils::create_idx_vars(idx_vars_value, result_rank, loc, al, current_scope, "_v"); - if( use_custom_loop_params ) { - PassUtils::create_idx_vars(idx_vars, loop_vars, loop_var_indices, - result_ubound, result_inc, loc, al, current_scope, "_t"); - } else { - PassUtils::create_idx_vars(idx_vars, result_rank, loc, al, current_scope, "_t"); - loop_vars.from_pointer_n_copy(al, idx_vars.p, idx_vars.size()); + void visit_StructType(const ASR::StructType_t& x) { + std::string derived_type_name = ASRUtils::symbol_name(x.m_derived_type); + if( x.m_derived_type == current_scope->resolve_symbol(derived_type_name) ) { + return ; } - ASR::stmt_t* doloop = nullptr; - ASR::ttype_t* int32_type = ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)); - ASR::expr_t* const_1 = ASRUtils::EXPR(ASR::make_IntegerConstant_t(al, loc, 1, int32_type)); - for( int i = (int) loop_vars.size() - 1; i >= 0; i-- ) { - // TODO: Add an If debug node to check if the lower and upper bounds of both the arrays are same. - ASR::do_loop_head_t head; - head.m_v = loop_vars[i]; - if( use_custom_loop_params ) { - int j = loop_var_indices[i]; - head.m_start = result_lbound[j]; - head.m_end = result_ubound[j]; - head.m_increment = result_inc[j]; - } else { - head.m_start = PassUtils::get_bound(result_var, i + 1, "lbound", al); - head.m_end = PassUtils::get_bound(result_var, i + 1, "ubound", al); - head.m_increment = nullptr; - } - head.loc = head.m_v->base.loc; - doloop_body.reserve(al, 1); - if( doloop == nullptr ) { - loop_body(); - } else { - if( ASRUtils::is_array(ASRUtils::expr_type(op_expr)) ) { - ASR::expr_t* idx_lb = PassUtils::get_bound(op_expr, i + 1, "lbound", al); - LCOMPILERS_ASSERT(idx_vars_value[i + 1] != nullptr); - ASR::stmt_t* set_to_one = ASRUtils::STMT(ASR::make_Assignment_t( - al, loc, idx_vars_value[i + 1], idx_lb, nullptr)); - doloop_body.push_back(al, set_to_one); - } - doloop_body.push_back(al, doloop); - } - if( ASRUtils::is_array(ASRUtils::expr_type(op_expr)) ) { - ASR::expr_t* inc_expr = ASRUtils::EXPR(ASR::make_IntegerBinOp_t( - al, loc, idx_vars_value[i], ASR::binopType::Add, const_1, int32_type, nullptr)); - ASR::stmt_t* assign_stmt = ASRUtils::STMT(ASR::make_Assignment_t( - al, loc, idx_vars_value[i], inc_expr, nullptr)); - doloop_body.push_back(al, assign_stmt); - } - doloop = ASRUtils::STMT(ASR::make_DoLoop_t(al, loc, nullptr, head, doloop_body.p, doloop_body.size(), nullptr, 0)); - } - if( ASRUtils::is_array(ASRUtils::expr_type(op_expr)) ) { - ASR::expr_t* idx_lb = PassUtils::get_bound(op_expr, 1, "lbound", al); - ASR::stmt_t* set_to_one = ASRUtils::STMT(ASR::make_Assignment_t(al, loc, idx_vars_value[0], idx_lb, nullptr)); - pass_result.push_back(al, set_to_one); - } - pass_result.push_back(al, doloop); + ASR::StructType_t& xx = const_cast(x); + xx.m_derived_type = current_scope->resolve_symbol(derived_type_name); } - template - void create_do_loop_for_const_val(const Location& loc, int result_rank, - Vec& idx_vars, - Vec& loop_vars, std::vector& loop_var_indices, - Vec& doloop_body, LOOP_BODY loop_body) { - if ( use_custom_loop_params ) { - PassUtils::create_idx_vars(idx_vars, loop_vars, loop_var_indices, - result_ubound, result_inc, loc, al, current_scope, "_t"); - } else { - PassUtils::create_idx_vars(idx_vars, result_rank, loc, al, current_scope, "_t"); - loop_vars.from_pointer_n_copy(al, idx_vars.p, idx_vars.size()); + void visit_Cast(const ASR::Cast_t& x) { + ASR::CallReplacerOnExpressionsVisitor::visit_Cast(x); + ASR::Cast_t& xx = const_cast(x); + if( !ASRUtils::is_array(ASRUtils::expr_type(x.m_arg)) && + ASRUtils::is_array(x.m_type) ) { + xx.m_type = ASRUtils::type_get_past_array(xx.m_type); + xx.m_value = nullptr; } + } - ASR::stmt_t* doloop = nullptr; - for ( int i = (int) loop_vars.size() - 1; i >= 0; i-- ) { - // TODO: Add an If debug node to check if the lower and upper bounds of both the arrays are same. - ASR::do_loop_head_t head; - head.m_v = loop_vars[i]; - if ( use_custom_loop_params ) { - int j = loop_var_indices[i]; - head.m_start = result_lbound[j]; - head.m_end = result_ubound[j]; - head.m_increment = result_inc[j]; - } else { - head.m_start = PassUtils::get_bound(result_var, i + 1, "lbound", al); - head.m_end = PassUtils::get_bound(result_var, i + 1, "ubound", al); - head.m_increment = nullptr; - } - head.loc = head.m_v->base.loc; - doloop_body.reserve(al, 1); - if ( doloop == nullptr ) { - loop_body(); - } else { - doloop_body.push_back(al, doloop); - } - doloop = ASRUtils::STMT(ASR::make_DoLoop_t(al, loc, nullptr, head, doloop_body.p, doloop_body.size(), nullptr, 0)); + void visit_IntrinsicElementalFunction(const ASR::IntrinsicElementalFunction_t& x) { + ASR::CallReplacerOnExpressionsVisitor::visit_IntrinsicElementalFunction(x); + ASR::IntrinsicElementalFunction_t& xx = const_cast(x); + if( !ASRUtils::is_array(ASRUtils::expr_type(x.m_args[0])) ) { + xx.m_type = ASRUtils::extract_type(xx.m_type); + xx.m_value = nullptr; } - pass_result.push_back(al, doloop); } - template - void replace_Constant(T* x) { - if( !(result_var != nullptr && PassUtils::is_array(result_var) && - resultvar2value.find(result_var) != resultvar2value.end() && - resultvar2value[result_var] == &(x->base)) ) { + void visit_FunctionCall(const ASR::FunctionCall_t& x) { + ASR::CallReplacerOnExpressionsVisitor::visit_FunctionCall(x); + if( !PassUtils::is_elemental(x.m_name) ) { return ; } - - const Location& loc = x->base.base.loc; - int n_dims = PassUtils::get_rank(result_var); - Vec idx_vars, loop_vars; - std::vector loop_var_indices; - Vec doloop_body; - create_do_loop_for_const_val(loc, n_dims, idx_vars, - loop_vars, loop_var_indices, doloop_body, - [=, &idx_vars, &doloop_body] () { - ASR::expr_t* ref = *current_expr; - ASR::expr_t* res = PassUtils::create_array_ref(result_var, idx_vars, al, current_scope); - ASR::stmt_t* assign = ASRUtils::STMT(ASR::make_Assignment_t(al, loc, res, ref, nullptr)); - doloop_body.push_back(al, assign); - }); - result_var = nullptr; - use_custom_loop_params = false; - *current_expr = nullptr; + ASR::FunctionCall_t& xx = const_cast(x); + if( !ASRUtils::is_array(ASRUtils::expr_type(x.m_args[0].m_value)) ) { + xx.m_type = ASRUtils::extract_type(xx.m_type); + xx.m_value = nullptr; + } } - void replace_IntegerConstant(ASR::IntegerConstant_t* x) { - replace_Constant(x); + template + void visit_ArrayOp(const T& x) { + T& xx = const_cast(x); + if( !ASRUtils::is_array(ASRUtils::expr_type(xx.m_left)) && + !ASRUtils::is_array(ASRUtils::expr_type(xx.m_right)) ) { + xx.m_type = ASRUtils::extract_type(xx.m_type); + xx.m_value = nullptr; + } } - void replace_StringConstant(ASR::StringConstant_t* x) { - replace_Constant(x); + void visit_RealBinOp(const ASR::RealBinOp_t& x) { + ASR::CallReplacerOnExpressionsVisitor::visit_RealBinOp(x); + visit_ArrayOp(x); } - void replace_RealConstant(ASR::RealConstant_t* x) { - replace_Constant(x); + void visit_RealCompare(const ASR::RealCompare_t& x) { + ASR::CallReplacerOnExpressionsVisitor::visit_RealCompare(x); + visit_ArrayOp(x); } - void replace_ComplexConstant(ASR::ComplexConstant_t* x) { - replace_Constant(x); + void visit_IntegerCompare(const ASR::IntegerCompare_t& x) { + ASR::CallReplacerOnExpressionsVisitor::visit_IntegerCompare(x); + visit_ArrayOp(x); } - void replace_LogicalConstant(ASR::LogicalConstant_t* x) { - replace_Constant(x); + void visit_ComplexCompare(const ASR::ComplexCompare_t& x) { + ASR::CallReplacerOnExpressionsVisitor::visit_ComplexCompare(x); + visit_ArrayOp(x); } - template - ASR::expr_t* generate_element_wise_operation(const Location& loc, ASR::expr_t* left, ASR::expr_t* right, T* x) { - ASR::ttype_t* x_m_type = ASRUtils::type_get_past_array(x->m_type); - switch( x->class_type ) { - case ASR::exprType::IntegerBinOp: - return ASRUtils::EXPR(ASR::make_IntegerBinOp_t( - al, loc, left, (ASR::binopType)x->m_op, - right, x_m_type, nullptr)); - - case ASR::exprType::UnsignedIntegerBinOp: - return ASRUtils::EXPR(ASR::make_UnsignedIntegerBinOp_t( - al, loc, left, (ASR::binopType)x->m_op, - right, x_m_type, nullptr)); - - case ASR::exprType::RealBinOp: - return ASRUtils::EXPR(ASR::make_RealBinOp_t( - al, loc, left, (ASR::binopType)x->m_op, - right, x_m_type, nullptr)); - - case ASR::exprType::ComplexBinOp: - return ASRUtils::EXPR(ASR::make_ComplexBinOp_t( - al, loc, left, (ASR::binopType)x->m_op, - right, x_m_type, nullptr)); - - case ASR::exprType::LogicalBinOp: - return ASRUtils::EXPR(ASR::make_LogicalBinOp_t( - al, loc, left, (ASR::logicalbinopType)x->m_op, - right, x_m_type, nullptr)); - - case ASR::exprType::IntegerCompare: - return ASRUtils::EXPR(ASR::make_IntegerCompare_t( - al, loc, left, (ASR::cmpopType)x->m_op, - right, x_m_type, nullptr)); - - case ASR::exprType::UnsignedIntegerCompare: - return ASRUtils::EXPR(ASR::make_UnsignedIntegerCompare_t( - al, loc, left, (ASR::cmpopType)x->m_op, - right, x_m_type, nullptr)); - - case ASR::exprType::RealCompare: - return ASRUtils::EXPR(ASR::make_RealCompare_t( - al, loc, left, (ASR::cmpopType)x->m_op, - right, x_m_type, nullptr)); - - case ASR::exprType::ComplexCompare: - return ASRUtils::EXPR(ASR::make_ComplexCompare_t( - al, loc, left, (ASR::cmpopType)x->m_op, - right, x_m_type, nullptr)); - - case ASR::exprType::LogicalCompare: - return ASRUtils::EXPR(ASR::make_LogicalCompare_t( - al, loc, left, (ASR::cmpopType)x->m_op, - right, x_m_type, nullptr)); - case ASR::exprType::StringCompare: - return ASRUtils::EXPR(ASR::make_StringCompare_t( - al, loc, left, (ASR::cmpopType)x->m_op, - right, x_m_type, nullptr)); - default: - throw LCompilersException("The desired operation is not supported yet for arrays."); - } + void visit_StringCompare(const ASR::StringCompare_t& x) { + ASR::CallReplacerOnExpressionsVisitor::visit_StringCompare(x); + visit_ArrayOp(x); } - ASR::ttype_t* get_result_type(ASR::ttype_t* op_type, - ASR::dimension_t* dims, size_t n_dims, - const Location& loc, ASR::exprType class_type, - bool& allocate) { - - Vec result_dims; - bool is_fixed_size_array = ASRUtils::is_fixed_size_array(dims, n_dims); - if( is_fixed_size_array || ASRUtils::is_dimension_dependent_only_on_arguments(dims, n_dims) ) { - result_dims.from_pointer_n(dims, n_dims); - } else { - allocate = true; - result_dims.reserve(al, n_dims); - for( size_t i = 0; i < n_dims; i++ ) { - ASR::dimension_t result_dim; - result_dim.loc = loc; - result_dim.m_length = nullptr; - result_dim.m_start = nullptr; - result_dims.push_back(al, result_dim); - } - } - - op_dims = result_dims.p; - op_n_dims = result_dims.size(); - - switch( class_type ) { - case ASR::exprType::RealCompare: - case ASR::exprType::ComplexCompare: - case ASR::exprType::LogicalCompare: - case ASR::exprType::IntegerCompare: { - ASR::ttype_t* logical_type_t = ASRUtils::TYPE( - ASR::make_Logical_t(al, loc, 4)); - logical_type_t = ASRUtils::make_Array_t_util(al, loc, - logical_type_t, result_dims.p, result_dims.size()); - return logical_type_t; - } - default: { - if( allocate || is_fixed_size_array ) { - op_type = ASRUtils::type_get_past_pointer(op_type); - } - return ASRUtils::duplicate_type(al, op_type, &result_dims); - } - } + void visit_LogicalBinOp(const ASR::LogicalBinOp_t& x) { + ASR::CallReplacerOnExpressionsVisitor::visit_LogicalBinOp(x); + visit_ArrayOp(x); } - void replace_ArraySection(ASR::ArraySection_t* x) { - Vec x_dims; - x_dims.reserve(al, x->n_args); - const Location& loc = x->base.base.loc; - ASRUtils::ASRBuilder builder(al, loc); - ASR::ttype_t* int32_type = ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)); - ASR::expr_t* i32_one = ASRUtils::EXPR(ASR::make_IntegerConstant_t( - al, loc, 1, int32_type)); - Vec empty_dims; - empty_dims.reserve(al, x->n_args); - for( size_t i = 0; i < x->n_args; i++ ) { - if( x->m_args[i].m_step != nullptr ) { - - ASR::dimension_t empty_dim; - empty_dim.loc = loc; - empty_dim.m_start = nullptr; - empty_dim.m_length = nullptr; - empty_dims.push_back(al, empty_dim); - - ASR::dimension_t x_dim; - x_dim.loc = loc; - x_dim.m_start = x->m_args[i].m_left; - ASR::expr_t* start_value = ASRUtils::expr_value(x_dim.m_start); - ASR::expr_t* end_value = ASRUtils::expr_value(x->m_args[i].m_right); - ASR::expr_t* step_value = ASRUtils::expr_value(x->m_args[i].m_step); - ASR::expr_t* length_value = nullptr; - if( ASRUtils::is_value_constant(start_value) && - ASRUtils::is_value_constant(end_value) && - ASRUtils::is_value_constant(step_value) ) { - int64_t const_start = -1; - if( !ASRUtils::extract_value(start_value, const_start) ) { - LCOMPILERS_ASSERT(false); - } - int64_t const_end = -1; - if( !ASRUtils::extract_value(end_value, const_end) ) { - LCOMPILERS_ASSERT(false); - } - int64_t const_step = -1; - if( !ASRUtils::extract_value(step_value, const_step) ) { - LCOMPILERS_ASSERT(false); - } - length_value = make_ConstantWithKind(make_IntegerConstant_t, make_Integer_t, - ((const_end - const_start)/const_step) + 1, 4, loc); - } - - ASR::expr_t* m_right = x->m_args[i].m_right; - ASR::expr_t* m_left = x->m_args[i].m_left; - ASR::expr_t* m_step = x->m_args[i].m_step; - m_right = CastingUtil::perform_casting(m_right, int32_type, al, loc); - m_left = CastingUtil::perform_casting(m_left, int32_type, al, loc); - m_step = CastingUtil::perform_casting(m_step, int32_type, al, loc); - x_dim.m_length = builder.ElementalAdd(builder.ElementalDiv( - builder.ElementalSub(m_right, m_left, loc), - m_step, loc), i32_one, loc, length_value); - x_dims.push_back(al, x_dim); - } - } - if( op_expr == *current_expr ) { - op_dims = x_dims.p; - op_n_dims = x_dims.size(); - } - - ASR::ttype_t* x_m_type; - if (op_expr && ASRUtils::is_simd_array(op_expr)) { - x_m_type = ASRUtils::expr_type(op_expr); - } else { - x_m_type = ASRUtils::TYPE(ASR::make_Pointer_t(al, loc, - ASRUtils::type_get_past_allocatable(ASRUtils::duplicate_type(al, - ASRUtils::type_get_past_pointer(x->m_type), &empty_dims)))); + void visit_StructInstanceMember(const ASR::StructInstanceMember_t& x) { + ASR::CallReplacerOnExpressionsVisitor::visit_StructInstanceMember(x); + if( !ASRUtils::is_array(x.m_type) ) { + return ; } - ASR::expr_t* array_section_pointer = PassUtils::create_var( - result_counter, "_array_section_pointer_", loc, - x_m_type, al, current_scope); - result_counter += 1; - if (op_expr && ASRUtils::is_simd_array(op_expr)) { - pass_result.push_back(al, ASRUtils::STMT(ASR::make_Assignment_t( - al, loc, array_section_pointer, *current_expr, nullptr))); - } else { - pass_result.push_back(al, ASRUtils::STMT(ASRUtils::make_Associate_t_util( - al, loc, array_section_pointer, *current_expr))); + if( !ASRUtils::is_array(ASRUtils::expr_type(x.m_v)) && + !ASRUtils::is_array(ASRUtils::symbol_type(x.m_m)) ) { + ASR::StructInstanceMember_t& xx = const_cast(x); + xx.m_type = ASRUtils::extract_type(x.m_type); } - *current_expr = array_section_pointer; + } - // Might get used in other replace_* methods as well. - // In that case put it into macro - for( auto& itr: resultvar2value ) { - if( itr.second == (ASR::expr_t*)(&x->base) ) { - itr.second = *current_expr; - } + void visit_RealUnaryMinus(const ASR::RealUnaryMinus_t& x){ + if( !ASRUtils::is_array(x.m_type) ) { + return ; } - BaseExprReplacer::replace_expr(*current_expr); + ASR::CallReplacerOnExpressionsVisitor::visit_RealUnaryMinus(x); + ASR::RealUnaryMinus_t& xx = const_cast(x); + xx.m_type = ASRUtils::extract_type(x.m_type); } - template - void replace_ArrayOpCommon(T* x, std::string res_prefix) { - bool is_left_simd = ASRUtils::is_simd_array(x->m_left); - bool is_right_simd = ASRUtils::is_simd_array(x->m_right); - if ( is_left_simd && is_right_simd ) { - return; - } else if ( ( is_left_simd && !is_right_simd) || - (!is_left_simd && is_right_simd) ) { - ASR::expr_t** current_expr_copy = current_expr; - ASR::expr_t* op_expr_copy = op_expr; - if (is_left_simd) { - // Replace ArraySection, case: a = a + b(:4) - if (ASR::is_a(*x->m_right)) { - current_expr = &(x->m_right); - op_expr = x->m_left; - this->replace_expr(x->m_right); - } - } else { - // Replace ArraySection, case: a = b(:4) + a - if (ASR::is_a(*x->m_left)) { - current_expr = &(x->m_left); - op_expr = x->m_right; - this->replace_expr(x->m_left); - } - } - current_expr = current_expr_copy; - op_expr = op_expr_copy; - return; - } - const Location& loc = x->base.base.loc; - bool current_status = use_custom_loop_params; - use_custom_loop_params = false; - ASR::dimension_t *left_dims; int rank_left; - ASR::dimension_t *right_dims; int rank_right; - ASR::expr_t* result_var_copy = result_var; - ASR::dimension_t* op_dims_copy = op_dims; - size_t op_n_dims_copy = op_n_dims; - ASR::expr_t* op_expr_copy = op_expr; - - ASR::expr_t** current_expr_copy_35 = current_expr; - op_dims = nullptr; - op_n_dims = 0; - current_expr = &(x->m_left); - op_expr = *current_expr; - result_var = nullptr; - this->replace_expr(x->m_left); - ASR::expr_t* left = *current_expr; - if (!is_a(*x->m_left)) { - left_dims = op_dims; - rank_left = op_n_dims; - } else { - left_dims = nullptr; - rank_left = 0; - } - current_expr = current_expr_copy_35; - - ASR::expr_t** current_expr_copy_36 = current_expr; - op_dims = nullptr; - op_n_dims = 0; - current_expr = &(x->m_right); - op_expr = *current_expr; - result_var = nullptr; - this->replace_expr(x->m_right); - ASR::expr_t* right = *current_expr; - if (!is_a(*x->m_right)) { - right_dims = op_dims; - rank_right = op_n_dims; - } else { - right_dims = nullptr; - rank_right = 0; - } - current_expr = current_expr_copy_36; - - op_dims = op_dims_copy; - op_n_dims = op_n_dims_copy; - op_expr = op_expr_copy; - - use_custom_loop_params = current_status; - result_var = result_var_copy; - - bool new_result_var_created = false; - - if( rank_left == 0 && rank_right == 0 ) { - if( result_var != nullptr ) { - ASR::stmt_t* auxiliary_assign_stmt_ = nullptr; - std::string name = current_scope->get_unique_name( - "__libasr_created_scalar_auxiliary_variable"); - *current_expr = PassUtils::create_auxiliary_variable_for_expr( - *current_expr, name, al, current_scope, auxiliary_assign_stmt_); - LCOMPILERS_ASSERT(auxiliary_assign_stmt_ != nullptr); - pass_result.push_back(al, auxiliary_assign_stmt_); - resultvar2value[result_var] = *current_expr; - replace_Var(ASR::down_cast(*current_expr)); - } + void visit_IntegerUnaryMinus(const ASR::IntegerUnaryMinus_t& x){ + if( !ASRUtils::is_array(x.m_type) ) { return ; } + ASR::CallReplacerOnExpressionsVisitor::visit_IntegerUnaryMinus(x); + ASR::IntegerUnaryMinus_t& xx = const_cast(x); + xx.m_type = ASRUtils::extract_type(x.m_type); + } +}; - if( rank_left > 0 && rank_right > 0 ) { - - if( rank_left != rank_right ) { - // TODO: This should be checked by verify() and thus should not happen - throw LCompilersException("Cannot generate loop for operands " - "of different shapes"); - } +class ReplaceArrayOp: public ASR::BaseExprReplacer { - if( result_var == nullptr ) { - bool allocate = false; - ASR::ttype_t* result_var_type = get_result_type(x->m_type, - left_dims, rank_left, loc, x->class_type, allocate); - if( allocate ) { - result_var_type = ASRUtils::TYPE(ASR::make_Allocatable_t(al, loc, - ASRUtils::type_get_past_allocatable(result_var_type))); - } - result_var = PassUtils::create_var(result_counter, res_prefix, loc, - result_var_type, al, current_scope); - result_counter += 1; - if( allocate ) { - allocate_result_var(left, left_dims, rank_left, true, true); - } - new_result_var_created = true; - } - *current_expr = result_var; - - int result_rank = PassUtils::get_rank(result_var); - Vec idx_vars, idx_vars_value_left, idx_vars_value_right, loop_vars; - std::vector loop_var_indices; - Vec doloop_body; - bool use_custom_loop_params_copy = use_custom_loop_params; - if( new_result_var_created ) { - use_custom_loop_params = false; - } - create_do_loop(loc, rank_left, result_rank, idx_vars, - loop_vars, idx_vars_value_left, idx_vars_value_right, loop_var_indices, doloop_body, left, right, 1, - [=, &left, &right, &idx_vars_value_left, &idx_vars_value_right, &idx_vars, &doloop_body]() { - ASR::expr_t* ref_1 = PassUtils::create_array_ref(left, idx_vars_value_left, al, current_scope); - ASR::expr_t* ref_2 = PassUtils::create_array_ref(right, idx_vars_value_right, al, current_scope); - ASR::expr_t* res = PassUtils::create_array_ref(result_var, idx_vars, al, current_scope); - ASR::expr_t* op_el_wise = generate_element_wise_operation(loc, ref_1, ref_2, x); - ASR::stmt_t* assign = ASRUtils::STMT(ASR::make_Assignment_t(al, loc, res, op_el_wise, nullptr)); - doloop_body.push_back(al, assign); - }); - if( new_result_var_created ) { - use_custom_loop_params = use_custom_loop_params_copy; - } - } else if( (rank_left == 0 && rank_right > 0) || - (rank_right == 0 && rank_left > 0) ) { - ASR::expr_t *arr_expr = nullptr, *other_expr = nullptr; - int n_dims = 0; - ASR::dimension_t* arr_expr_dims; int arr_expr_n_dims; - if( rank_left > 0 ) { - arr_expr = left; - arr_expr_dims = left_dims; - arr_expr_n_dims = rank_left; - other_expr = right; - n_dims = rank_left; - } else { - arr_expr = right; - arr_expr_dims = right_dims; - arr_expr_n_dims = rank_right; - other_expr = left; - n_dims = rank_right; - } - if( !ASR::is_a(*other_expr) ) { - ASR::stmt_t* auxiliary_assign_stmt_ = nullptr; - std::string name = current_scope->get_unique_name( - "__libasr_created_scalar_auxiliary_variable"); - other_expr = PassUtils::create_auxiliary_variable_for_expr( - other_expr, name, al, current_scope, auxiliary_assign_stmt_); - LCOMPILERS_ASSERT(auxiliary_assign_stmt_ != nullptr); - pass_result.push_back(al, auxiliary_assign_stmt_); - } - if( result_var == nullptr ) { - bool allocate = false; - ASR::ttype_t* result_var_type = get_result_type(x->m_type, - arr_expr_dims, arr_expr_n_dims, loc, x->class_type, allocate); - if( allocate ) { - result_var_type = ASRUtils::TYPE(ASR::make_Allocatable_t(al, loc, - ASRUtils::type_get_past_allocatable(result_var_type))); - } - result_var = PassUtils::create_var(result_counter, res_prefix, loc, - result_var_type, al, current_scope); - result_counter += 1; - if( allocate ) { - allocate_result_var(arr_expr, arr_expr_dims, arr_expr_n_dims, true, true); - } - new_result_var_created = true; - } - *current_expr = result_var; + private: - ASR::expr_t* op_expr = nullptr; - if( rank_left > 0 ) { - op_expr = left; - } else { - op_expr = right; - } + Allocator& al; + Vec& pass_result; - Vec idx_vars, idx_vars_value, loop_vars; - Vec doloop_body; - std::vector loop_var_indices; - int result_rank = PassUtils::get_rank(result_var); - bool use_custom_loop_params_copy = use_custom_loop_params; - if( new_result_var_created ) { - use_custom_loop_params = false; - } - create_do_loop(loc, n_dims, result_rank, idx_vars, - loop_vars, idx_vars_value, idx_vars_value, loop_var_indices, doloop_body, - op_expr, nullptr, 2, [=, &arr_expr, &idx_vars, &idx_vars_value, &doloop_body]() { - ASR::expr_t* ref = PassUtils::create_array_ref(arr_expr, idx_vars_value, al, current_scope); - ASR::expr_t* res = PassUtils::create_array_ref(result_var, idx_vars, al, current_scope); - ASR::expr_t *lexpr = nullptr, *rexpr = nullptr; - if( rank_left > 0 ) { - lexpr = ref; - rexpr = other_expr; - } else { - rexpr = ref; - lexpr = other_expr; - } - ASR::expr_t* op_el_wise = generate_element_wise_operation(loc, lexpr, rexpr, x); - ASR::stmt_t* assign = ASRUtils::STMT(ASR::make_Assignment_t(al, loc, res, op_el_wise, nullptr)); - doloop_body.push_back(al, assign); - }); - if( new_result_var_created ) { - use_custom_loop_params = use_custom_loop_params_copy; - } - } - if( !new_result_var_created ) { - use_custom_loop_params = false; - } - result_var = nullptr; - } + public: + SymbolTable* current_scope; + ASR::expr_t* result_expr; + bool& remove_original_stmt; + ReplaceArrayOp(Allocator& al_, Vec& pass_result_, + bool& remove_original_stmt_): + al(al_), pass_result(pass_result_), + current_scope(nullptr), result_expr(nullptr), + remove_original_stmt(remove_original_stmt_) {} + + #define remove_original_stmt_if_size_0(type) if( ASRUtils::get_fixed_size_of_array(type) == 0 ) { \ + remove_original_stmt = true; \ + return ; \ + } \ - void replace_Cast(ASR::Cast_t* x) { - if( x->m_kind == ASR::cast_kindType::ListToArray ) { - return ; - } + void replace_ArrayConstant(ASR::ArrayConstant_t* x) { + remove_original_stmt_if_size_0(x->m_type) + pass_result.reserve(al, x->m_n_data); const Location& loc = x->base.base.loc; - ASR::Cast_t* x_ = x; - if( ASR::is_a(*x->m_arg) ) { - *current_expr = x->m_arg; - ASR::ArrayReshape_t* array_reshape_t = ASR::down_cast(x->m_arg); - ASR::array_physical_typeType array_reshape_ptype = ASRUtils::extract_physical_type(array_reshape_t->m_type); - Vec m_dims_vec; - ASR::dimension_t* m_dims; - size_t n_dims = ASRUtils::extract_dimensions_from_ttype(ASRUtils::expr_type(array_reshape_t->m_array), m_dims); - m_dims_vec.from_pointer_n(m_dims, n_dims); - array_reshape_t->m_array = ASRUtils::EXPR(ASR::make_Cast_t(al, x->base.base.loc, - array_reshape_t->m_array, x->m_kind, ASRUtils::duplicate_type(al, x->m_type, &m_dims_vec, - array_reshape_ptype, true), nullptr)); - n_dims = ASRUtils::extract_dimensions_from_ttype(array_reshape_t->m_type, m_dims); - m_dims_vec.from_pointer_n(m_dims, n_dims); - array_reshape_t->m_type = ASRUtils::duplicate_type(al, x->m_type, &m_dims_vec, array_reshape_ptype, true); - x_ = ASR::down_cast(array_reshape_t->m_array); - current_expr = &array_reshape_t->m_array; - result_var = nullptr; - } - ASR::expr_t* result_var_copy = result_var; - result_var = nullptr; - BaseExprReplacer::replace_Cast(x_); - result_var = result_var_copy; - ASR::expr_t* tmp_val = x_->m_arg; - - bool is_arg_array = PassUtils::is_array(tmp_val); - bool is_result_var_array = result_var && PassUtils::is_array(result_var); - if( !is_arg_array && !is_result_var_array ) { - result_var = nullptr; - return ; + LCOMPILERS_ASSERT(result_expr != nullptr); + ASR::ttype_t* result_type = ASRUtils::expr_type(result_expr); + ASR::ttype_t* result_element_type = ASRUtils::extract_type(result_type); + for( int64_t i = 0; i < ASRUtils::get_fixed_size_of_array(x->m_type); i++ ) { + ASR::expr_t* x_i = ASRUtils::fetch_ArrayConstant_value(al, x, i); + Vec array_index_args; + array_index_args.reserve(al, 1); + ASR::array_index_t array_index_arg; + array_index_arg.loc = loc; + array_index_arg.m_left = nullptr; + array_index_arg.m_right = make_ConstantWithKind( + make_IntegerConstant_t, make_Integer_t, i + 1, 4, loc); + array_index_arg.m_step = nullptr; + array_index_args.push_back(al, array_index_arg); + ASR::expr_t* y_i = ASRUtils::EXPR(ASRUtils::make_ArrayItem_t_util(al, loc, + result_expr, array_index_args.p, array_index_args.size(), + result_element_type, ASR::arraystorageType::ColMajor, nullptr)); + pass_result.push_back(al, ASRUtils::STMT(ASR::make_Assignment_t(al, loc, y_i, x_i, nullptr))); } + } - if( result_var == nullptr ) { - PassUtils::fix_dimension(x_, tmp_val); - result_var = PassUtils::create_var(result_counter, std::string("_implicit_cast_res"), - loc, *current_expr, al, current_scope); - ASR::dimension_t* allocate_dims = nullptr; - int n_dims = ASRUtils::extract_dimensions_from_ttype(x_->m_type, allocate_dims); - allocate_result_var(x_->m_arg, allocate_dims, n_dims, true, true); - result_counter += 1; - } else { - ASR::ttype_t* result_var_type = ASRUtils::expr_type(result_var); - if( realloc_lhs && is_arg_array && ASRUtils::is_allocatable(result_var_type)) { - Vec result_var_m_dims; - size_t result_var_n_dims = ASRUtils::extract_n_dims_from_ttype(result_var_type); - result_var_m_dims.reserve(al, result_var_n_dims); - ASR::alloc_arg_t result_alloc_arg; - result_alloc_arg.loc = loc; - result_alloc_arg.m_a = result_var; - for( size_t i = 0; i < result_var_n_dims; i++ ) { - ASR::dimension_t result_var_dim; - result_var_dim.loc = loc; - result_var_dim.m_start = make_ConstantWithKind( - make_IntegerConstant_t, make_Integer_t, 1, 4, loc); - result_var_dim.m_length = ASRUtils::get_size(tmp_val, i + 1, al); - result_var_m_dims.push_back(al, result_var_dim); - } - result_alloc_arg.m_dims = result_var_m_dims.p; - result_alloc_arg.n_dims = result_var_n_dims; - result_alloc_arg.m_len_expr = nullptr; - result_alloc_arg.m_type = nullptr; - Vec alloc_result_args; alloc_result_args.reserve(al, 1); - alloc_result_args.push_back(al, result_alloc_arg); - pass_result.push_back(al, ASRUtils::STMT(ASR::make_ReAlloc_t( - al, loc, alloc_result_args.p, 1))); + bool are_all_elements_scalars(ASR::expr_t** args, size_t n) { + for( size_t i = 0; i < n; i++ ) { + if (ASR::is_a(*args[i])) { + return false; } - } - - int n_dims = PassUtils::get_rank(result_var); - Vec idx_vars, loop_vars, idx_vars_value; - std::vector loop_var_indices; - Vec doloop_body; - create_do_loop(loc, n_dims, idx_vars, idx_vars_value, - loop_vars, loop_var_indices, doloop_body, tmp_val, - [=, &tmp_val, &idx_vars, &idx_vars_value, &is_arg_array, &doloop_body] () { - ASR::expr_t* ref = tmp_val; - if( is_arg_array ) { - ref = PassUtils::create_array_ref(tmp_val, idx_vars_value, al, current_scope); + if( ASRUtils::is_array(ASRUtils::expr_type(args[i])) ) { + return false; } - ASR::expr_t* res = PassUtils::create_array_ref(result_var, idx_vars, al, current_scope); - ASR::ttype_t* x_m_type = ASRUtils::duplicate_type_without_dims( - al, x_->m_type, x_->m_type->base.loc); - ASR::expr_t* impl_cast_el_wise = ASRUtils::EXPR(ASR::make_Cast_t( - al, loc, ref, x->m_kind, x_m_type, nullptr)); - ASR::stmt_t* assign = ASRUtils::STMT(ASR::make_Assignment_t(al, loc, res, impl_cast_el_wise, nullptr)); - doloop_body.push_back(al, assign); - }); - *current_expr = result_var; - if( op_expr == &(x->base) ) { - op_dims = nullptr; - op_n_dims = ASRUtils::extract_dimensions_from_ttype(x->m_type, op_dims); } - result_var = nullptr; - use_custom_loop_params = false; + return true; } - template - void replace_UnaryOp(T* x, int unary_type, std::string res_prefix) { - ASR::expr_t* result_var_copy = result_var; - result_var = nullptr; - - ASR::expr_t** current_expr_copy_22 = current_expr; - current_expr = &(x->m_arg); - self().replace_expr(x->m_arg); - current_expr = current_expr_copy_22; - - result_var = nullptr; - ASR::expr_t** current_expr_copy_23 = current_expr; - current_expr = &(x->m_value); - self().replace_expr(x->m_value); - current_expr = current_expr_copy_23; - - result_var = result_var_copy; - - ASR::expr_t* operand = x->m_arg; - int rank_operand = PassUtils::get_rank(operand); - if( rank_operand == 0 ) { - const Location& loc = x->base.base.loc; - if (result_var) { - int n_dims = PassUtils::get_rank(result_var); - if (n_dims != 0) { - Vec idx_vars, loop_vars; - std::vector loop_var_indices; - Vec doloop_body; - create_do_loop_for_const_val(loc, n_dims, idx_vars, - loop_vars, loop_var_indices, doloop_body, - [=, &idx_vars, &doloop_body] () { - ASR::expr_t* ref = ASRUtils::EXPR((ASR::asr_t*)x); - ASR::expr_t* res = PassUtils::create_array_ref(result_var, idx_vars, al, current_scope); - ASR::stmt_t* assign = ASRUtils::STMT(ASR::make_Assignment_t(al, loc, res, ref, nullptr)); - doloop_body.push_back(al, assign); - }); - result_var = nullptr; - use_custom_loop_params = false; - *current_expr = nullptr; - } + void replace_ArrayConstructor(ASR::ArrayConstructor_t* x) { + // TODO: Remove this because the ArrayConstructor node should + // be replaced with its value already (if present) in array_struct_temporary pass. + if( x->m_value == nullptr ) { + if( !are_all_elements_scalars(x->m_args, x->n_args) ) { + PassUtils::ReplacerUtils::replace_ArrayConstructor_( + al, x, result_expr, &pass_result, current_scope); + return ; } - return ; - } - const Location& loc = x->base.base.loc; - bool result_var_created = false; - if( rank_operand > 0 ) { - if( result_var == nullptr ) { - bool allocate = false; - ASR::dimension_t *operand_dims = nullptr; - rank_operand = ASRUtils::extract_dimensions_from_ttype( - ASRUtils::expr_type(operand), operand_dims); - ASR::ttype_t* result_var_type = get_result_type(x->m_type, - operand_dims, rank_operand, loc, x->class_type, allocate); - if( allocate ) { - result_var_type = ASRUtils::TYPE(ASR::make_Allocatable_t(al, loc, - ASRUtils::type_get_past_allocatable(result_var_type))); - } - result_var = PassUtils::create_var(result_counter, res_prefix, - loc, result_var_type, al, current_scope); - result_counter += 1; - if( allocate ) { - allocate_result_var(operand, operand_dims, rank_operand, true, true); - } - result_var_created = true; - } - *current_expr = result_var; - if( op_expr == &(x->base) ) { - op_dims = nullptr; - op_n_dims = ASRUtils::extract_dimensions_from_ttype( - ASRUtils::expr_type(*current_expr), op_dims); + if( !ASRUtils::is_fixed_size_array(x->m_type) ) { + PassUtils::ReplacerUtils::replace_ArrayConstructor_( + al, x, result_expr, &pass_result, current_scope); + return ; } + } - Vec idx_vars, loop_vars, idx_vars_value; - std::vector loop_var_indices; - Vec doloop_body; - create_do_loop(loc, rank_operand, idx_vars, idx_vars_value, - loop_vars, loop_var_indices, doloop_body, operand, - [=, &operand, &idx_vars, &idx_vars_value, &x, &doloop_body] () { - ASR::expr_t* ref = PassUtils::create_array_ref(operand, idx_vars_value, al, current_scope); - ASR::expr_t* res = PassUtils::create_array_ref(result_var, idx_vars, al, current_scope); - ASR::expr_t* op_el_wise = nullptr; - ASR::ttype_t* x_m_type = ASRUtils::type_get_past_array(x->m_type); - if (unary_type == 0) { - op_el_wise = ASRUtils::EXPR(ASR::make_IntegerUnaryMinus_t(al, loc, - ref, x_m_type, nullptr)); - } else if (unary_type == 1) { - op_el_wise = ASRUtils::EXPR(ASR::make_RealUnaryMinus_t(al, loc, - ref, x_m_type, nullptr)); - } else if (unary_type == 2) { - op_el_wise = ASRUtils::EXPR(ASR::make_ComplexUnaryMinus_t(al, loc, - ref, x_m_type, nullptr)); - } else if (unary_type == 3) { - op_el_wise = ASRUtils::EXPR(ASR::make_IntegerBitNot_t(al, loc, - ref, x_m_type, nullptr)); - } else if (unary_type == 4) { - op_el_wise = ASRUtils::EXPR(ASR::make_LogicalNot_t(al, loc, - ref, x_m_type, nullptr)); - } - ASR::stmt_t* assign = ASRUtils::STMT(ASR::make_Assignment_t(al, loc, res, - op_el_wise, nullptr)); - doloop_body.push_back(al, assign); - }); - result_var = nullptr; - if( !result_var_created ) { - use_custom_loop_params = false; - } + ASR::ttype_t* arr_type = nullptr; + ASR::ArrayConstant_t* arr_value = nullptr; + if( x->m_value ) { + arr_value = ASR::down_cast(x->m_value); + arr_type = arr_value->m_type; + } else { + arr_type = x->m_type; } - } - void replace_IntegerUnaryMinus(ASR::IntegerUnaryMinus_t* x) { - replace_UnaryOp(x, 0, "_integer_unary_op_res"); - } + remove_original_stmt_if_size_0(arr_type) - void replace_RealUnaryMinus(ASR::RealUnaryMinus_t* x) { - replace_UnaryOp(x, 1, "_real_unary_op_res"); - } + pass_result.reserve(al, x->n_args); + const Location& loc = x->base.base.loc; + LCOMPILERS_ASSERT(result_expr != nullptr); - void replace_ComplexUnaryMinus(ASR::ComplexUnaryMinus_t* x) { - replace_UnaryOp(x, 2, "_complex_unary_op_res"); - } + ASR::ttype_t* result_type = ASRUtils::expr_type(result_expr); + ASRUtils::ExprStmtDuplicator duplicator(al); + ASR::ttype_t* result_element_type = ASRUtils::extract_type(result_type); + result_element_type = duplicator.duplicate_ttype(result_element_type); - void replace_IntegerBitNot(ASR::IntegerBitNot_t* x) { - replace_UnaryOp(x, 3, "_integerbitnot_unary_op_res"); - } + FixTypeVisitor fix_type_visitor(al); + fix_type_visitor.current_scope = current_scope; + fix_type_visitor.visit_ttype(*result_element_type); - void replace_LogicalNot(ASR::LogicalNot_t* x) { - replace_UnaryOp(x, 4, "_logicalnot_unary_op_res"); + for( int64_t i = 0; i < ASRUtils::get_fixed_size_of_array(arr_type); i++ ) { + ASR::expr_t* x_i = nullptr; + if( x->m_value ) { + x_i = ASRUtils::fetch_ArrayConstant_value(al, arr_value, i); + } else { + x_i = x->m_args[i]; + } + LCOMPILERS_ASSERT(!ASRUtils::is_array(ASRUtils::expr_type(x_i))); + Vec array_index_args; + array_index_args.reserve(al, 1); + ASR::array_index_t array_index_arg; + array_index_arg.loc = loc; + array_index_arg.m_left = nullptr; + array_index_arg.m_right = make_ConstantWithKind( + make_IntegerConstant_t, make_Integer_t, i + 1, 4, loc); + array_index_arg.m_step = nullptr; + array_index_args.push_back(al, array_index_arg); + ASR::expr_t* y_i = ASRUtils::EXPR(ASRUtils::make_ArrayItem_t_util(al, loc, + result_expr, array_index_args.p, array_index_args.size(), + result_element_type, ASR::arraystorageType::ColMajor, nullptr)); + pass_result.push_back(al, ASRUtils::STMT(ASR::make_Assignment_t(al, loc, y_i, x_i, nullptr))); + } } - void replace_RealBinOp(ASR::RealBinOp_t* x) { - replace_ArrayOpCommon(x, "_real_bin_op_res"); - } +}; - void replace_IntegerBinOp(ASR::IntegerBinOp_t* x) { - replace_ArrayOpCommon(x, "_integer_bin_op_res"); +ASR::expr_t* at(Vec& vec, int64_t index) { + index = index + vec.size(); + if( index < 0 ) { + return nullptr; } + return vec[index]; +} - void replace_UnsignedIntegerBinOp(ASR::UnsignedIntegerBinOp_t* x) { - replace_ArrayOpCommon(x, "_unsigned_integer_bin_op_res"); - } +class ArrayOpVisitor: public ASR::CallReplacerOnExpressionsVisitor { + private: - void replace_ComplexBinOp(ASR::ComplexBinOp_t* x) { - replace_ArrayOpCommon(x, "_complex_bin_op_res"); - } + Allocator& al; + ReplaceArrayOp replacer; + Vec pass_result; + Vec* parent_body; + bool realloc_lhs; + bool remove_original_stmt; - void replace_LogicalBinOp(ASR::LogicalBinOp_t* x) { - replace_ArrayOpCommon(x, "_logical_bin_op_res"); - } + public: - void replace_IntegerCompare(ASR::IntegerCompare_t* x) { - replace_ArrayOpCommon(x, "_integer_comp_op_res"); + void call_replacer() { + replacer.current_expr = current_expr; + replacer.current_scope = current_scope; + replacer.replace_expr(*current_expr); } - void replace_UnsignedIntegerCompare(ASR::UnsignedIntegerCompare_t* x) { - replace_ArrayOpCommon(x, "_unsigned_integer_comp_op_res"); + ArrayOpVisitor(Allocator& al_, bool realloc_lhs_): + al(al_), replacer(al, pass_result, remove_original_stmt), + parent_body(nullptr), realloc_lhs(realloc_lhs_), + remove_original_stmt(false) { + pass_result.n = 0; + pass_result.reserve(al, 0); } - void replace_RealCompare(ASR::RealCompare_t* x) { - replace_ArrayOpCommon(x, "_real_comp_op_res"); + void visit_Variable(const ASR::Variable_t& /*x*/) { + // Do nothing } - void replace_ComplexCompare(ASR::ComplexCompare_t* x) { - replace_ArrayOpCommon(x, "_complex_comp_op_res"); + void transform_stmts(ASR::stmt_t **&m_body, size_t &n_body) { + bool remove_original_stmt_copy = remove_original_stmt; + Vec body; + body.reserve(al, n_body); + if( parent_body ) { + for (size_t j=0; j < pass_result.size(); j++) { + parent_body->push_back(al, pass_result[j]); + } + } + for (size_t i = 0; i < n_body; i++) { + pass_result.n = 0; + pass_result.reserve(al, 1); + remove_original_stmt = false; + Vec* parent_body_copy = parent_body; + parent_body = &body; + visit_stmt(*m_body[i]); + parent_body = parent_body_copy; + if( pass_result.size() > 0 ) { + for (size_t j=0; j < pass_result.size(); j++) { + body.push_back(al, pass_result[j]); + } + } else { + if( !remove_original_stmt ) { + body.push_back(al, m_body[i]); + remove_original_stmt = false; + } + } + } + m_body = body.p; + n_body = body.size(); + pass_result.n = 0; + remove_original_stmt = remove_original_stmt_copy; } - void replace_LogicalCompare(ASR::LogicalCompare_t* x) { - replace_ArrayOpCommon(x, "_logical_comp_op_res"); + bool call_replace_on_expr(ASR::exprType expr_type) { + switch( expr_type ) { + case ASR::exprType::ArrayConstant: + case ASR::exprType::ArrayConstructor: { + return true; + } + default: { + return false; + } + } } - void replace_StringCompare(ASR::StringCompare_t* x) { - replace_ArrayOpCommon(x, "_string_comp_op_res"); + void increment_index_variables(std::unordered_map>& var2indices, + size_t var_with_maxrank, int64_t loop_depth, + Vec& do_loop_body, const Location& loc) { + ASR::expr_t* step = make_ConstantWithKind(make_IntegerConstant_t, make_Integer_t, 1, 4, loc); + for( size_t i = 0; i < var2indices.size(); i++ ) { + if( i == var_with_maxrank ) { + continue; + } + ASR::expr_t* index_var = at(var2indices[i], loop_depth); + if( index_var == nullptr ) { + continue; + } + ASR::expr_t* plus_one = ASRUtils::EXPR(ASR::make_IntegerBinOp_t(al, loc, index_var, + ASR::binopType::Add, step, ASRUtils::expr_type(index_var), nullptr)); + ASR::stmt_t* increment = ASRUtils::STMT(ASR::make_Assignment_t( + al, loc, index_var, plus_one, nullptr)); + do_loop_body.push_back(al, increment); + } } - template - void replace_intrinsic_function(T* x) { - LCOMPILERS_ASSERT(current_scope != nullptr); - const Location& loc = x->base.base.loc; - std::vector array_mask(x->n_args, false); - bool at_least_one_array = false; - for( size_t iarg = 0; iarg < x->n_args; iarg++ ) { - array_mask[iarg] = ASRUtils::is_array( - ASRUtils::expr_type(x->m_args[iarg])); - at_least_one_array = at_least_one_array || array_mask[iarg]; - } - if (!at_least_one_array) { - if (result_var) { - // Scalar arguments - ASR::stmt_t* auxiliary_assign_stmt_ = nullptr; - std::string name = current_scope->get_unique_name( - "__libasr_created_scalar_auxiliary_variable"); - *current_expr = PassUtils::create_auxiliary_variable_for_expr( - *current_expr, name, al, current_scope, auxiliary_assign_stmt_); - LCOMPILERS_ASSERT(auxiliary_assign_stmt_ != nullptr); - pass_result.push_back(al, auxiliary_assign_stmt_); - resultvar2value[result_var] = *current_expr; - replace_Var(ASR::down_cast(*current_expr)); + void set_index_variables(std::unordered_map>& var2indices, + Vec& vars_expr, size_t var_with_maxrank, size_t max_rank, + int64_t loop_depth, Vec& dest_vec, const Location& loc) { + for( size_t i = 0; i < var2indices.size(); i++ ) { + if( i == var_with_maxrank ) { + continue; } - return ; + ASR::expr_t* index_var = at(var2indices[i], loop_depth); + if( index_var == nullptr ) { + continue; + } + ASR::expr_t* lbound = PassUtils::get_bound(vars_expr[i], + loop_depth + max_rank + 1, "lbound", al); + ASR::stmt_t* set_index_var = ASRUtils::STMT(ASR::make_Assignment_t( + al, loc, index_var, lbound, nullptr)); + dest_vec.push_back(al, set_index_var); } - std::string res_prefix = "_elemental_func_call_res"; - ASR::expr_t* result_var_copy = result_var; - bool is_all_rank_0 = true; - std::vector operands; - ASR::expr_t *operand = nullptr, *first_array_operand = nullptr; - int common_rank = 0; - bool are_all_rank_same = true; - for( size_t iarg = 0; iarg < x->n_args; iarg++ ) { - result_var = nullptr; - ASR::expr_t** current_expr_copy_9 = current_expr; - current_expr = &(x->m_args[iarg]); - self().replace_expr(x->m_args[iarg]); - operand = *current_expr; - current_expr = current_expr_copy_9; - operands.push_back(operand); - int rank_operand = PassUtils::get_rank(operand); - if( rank_operand > 0 && first_array_operand == nullptr ) { - first_array_operand = operand; + } + + enum IndexType { + ScalarIndex, ArrayIndex + }; + + void set_index_variables(std::unordered_map>& var2indices, + std::unordered_map>& index2var, + size_t var_with_maxrank, size_t max_rank, int64_t loop_depth, + Vec& dest_vec, const Location& loc) { + for( size_t i = 0; i < var2indices.size(); i++ ) { + if( i == var_with_maxrank ) { + continue; } - if( common_rank == 0 ) { - common_rank = rank_operand; + ASR::expr_t* index_var = at(var2indices[i], loop_depth); + if( index_var == nullptr ) { + continue; } - if( common_rank != rank_operand && - rank_operand > 0 ) { - are_all_rank_same = false; + size_t bound_dim = loop_depth + max_rank + 1; + if( index2var[index_var].second == IndexType::ArrayIndex ) { + bound_dim = 1; } - array_mask[iarg] = (rank_operand > 0); - is_all_rank_0 = is_all_rank_0 && (rank_operand <= 0); - } - if( is_all_rank_0 ) { - return ; - } - if( !are_all_rank_same ) { - throw LCompilersException("Broadcasting support not yet available " - "for different shape arrays."); - } - result_var = result_var_copy; - bool result_var_created = false; - if( result_var == nullptr ) { - if (x->m_type && !ASRUtils::is_array(x->m_type)) { - ASR::ttype_t* sibling_type = ASRUtils::expr_type(operand); - ASR::dimension_t* m_dims; int ndims; - PassUtils::get_dim_rank(sibling_type, m_dims, ndims); - ASR::ttype_t* arr_type = ASRUtils::make_Array_t_util( - al, loc, x->m_type, m_dims, ndims); - if( ASRUtils::extract_physical_type(arr_type) == - ASR::array_physical_typeType::DescriptorArray ) { - arr_type = ASRUtils::TYPE(ASR::make_Allocatable_t(al, loc, arr_type)); - } - result_var = PassUtils::create_var(result_counter, res_prefix, - loc, arr_type, al, current_scope); + ASR::expr_t* lbound; + if( !ASRUtils::is_array(ASRUtils::expr_type(index2var[index_var].first)) ){ + lbound = index2var[index_var].first; } else { - result_var = PassUtils::create_var(result_counter, res_prefix, - loc, *current_expr, al, current_scope); + lbound = PassUtils::get_bound( + index2var[index_var].first, bound_dim, "lbound", al); } - result_counter += 1; - operand = first_array_operand; - ASR::dimension_t* m_dims; - int n_dims = ASRUtils::extract_dimensions_from_ttype( - ASRUtils::expr_type(first_array_operand), m_dims); - allocate_result_var(operand, m_dims, n_dims, true, false); - result_var_created = true; - } - *current_expr = result_var; - if( op_expr == &(x->base) ) { - op_dims = nullptr; - op_n_dims = ASRUtils::extract_dimensions_from_ttype( - ASRUtils::expr_type(*current_expr), op_dims); + ASR::stmt_t* set_index_var = ASRUtils::STMT(ASR::make_Assignment_t( + al, loc, index_var, lbound, nullptr)); + dest_vec.push_back(al, set_index_var); } + } - - Vec idx_vars, loop_vars, idx_vars_value; - std::vector loop_var_indices; - Vec doloop_body; - create_do_loop(loc, common_rank, idx_vars, idx_vars_value, - loop_vars, loop_var_indices, doloop_body, first_array_operand, - [=, &operands, &idx_vars, &idx_vars_value, &doloop_body] () { - Vec ref_args; - ref_args.reserve(al, x->n_args); - for( size_t iarg = 0; iarg < x->n_args; iarg++ ) { - ASR::expr_t* ref = operands[iarg]; - if( array_mask[iarg] ) { - ref = PassUtils::create_array_ref(operands[iarg], idx_vars_value, al, current_scope); + inline void fill_array_indices_in_vars_expr( + ASR::expr_t* expr, bool is_expr_array, + Vec& vars_expr, + size_t& offset_for_array_indices) { + if( is_expr_array ) { + ASR::array_index_t* m_args = nullptr; size_t n_args = 0; + ASRUtils::extract_indices(expr, m_args, n_args); + for( size_t i = 0; i < n_args; i++ ) { + if( m_args[i].m_left == nullptr && + m_args[i].m_right != nullptr && + m_args[i].m_step == nullptr ) { + if( ASRUtils::is_array(ASRUtils::expr_type( + m_args[i].m_right)) ) { + vars_expr.push_back(al, m_args[i].m_right); + } } - ref_args.push_back(al, ref); } - Vec empty_dim; - empty_dim.reserve(al, 1); - ASR::ttype_t* dim_less_type = ASRUtils::duplicate_type(al, x->m_type, &empty_dim); - x->m_args = ref_args.p; - x->n_args = ref_args.size(); - x->m_type = dim_less_type; - ASR::expr_t* op_el_wise = ASRUtils::EXPR((ASR::asr_t *)x); - ASR::expr_t* res = PassUtils::create_array_ref(result_var, idx_vars, al, current_scope); - ASR::stmt_t* assign = ASRUtils::STMT(ASR::make_Assignment_t(al, loc, res, op_el_wise, nullptr)); - doloop_body.push_back(al, assign); - }); - if( !result_var_created ) { - use_custom_loop_params = false; + offset_for_array_indices++; } - result_var = nullptr; - } - - void replace_IntrinsicElementalFunction(ASR::IntrinsicElementalFunction_t* x) { - replace_intrinsic_function(x); } - void replace_IntrinsicArrayFunction(ASR::IntrinsicArrayFunction_t* x) { - if(!ASRUtils::IntrinsicArrayFunctionRegistry::is_elemental(x->m_arr_intrinsic_id)) { - // ASR::BaseExprReplacer::replace_IntrinsicArrayFunction(x); - if( op_expr == &(x->base) ) { - op_dims = nullptr; - op_n_dims = ASRUtils::extract_dimensions_from_ttype( - ASRUtils::expr_type(*current_expr), op_dims); + inline void create_array_item_array_indexed_expr( + ASR::expr_t* expr, ASR::expr_t** expr_address, + bool is_expr_array, int var2indices_key, + size_t var_rank, const Location& loc, + std::unordered_map>& var2indices, + size_t& j, ASR::ttype_t* int32_type) { + if( is_expr_array ) { + ASR::array_index_t* m_args = nullptr; size_t n_args = 0; + Vec array_item_args; + array_item_args.reserve(al, n_args); + ASRUtils::extract_indices(expr, m_args, n_args); + ASRUtils::ExprStmtDuplicator expr_duplicator(al); + Vec new_indices; new_indices.reserve(al, n_args); + int k = 0; + for( size_t i = 0; i < (n_args == 0 ? var_rank : n_args); i++ ) { + if( m_args && m_args[i].m_left == nullptr && + m_args[i].m_right != nullptr && + m_args[i].m_step == nullptr ) { + if( ASRUtils::is_array(ASRUtils::expr_type( + m_args[i].m_right)) ) { + ASR::array_index_t array_index; + array_index.loc = loc; + array_index.m_left = nullptr; + Vec indices1; indices1.reserve(al, 1); + ASR::array_index_t index1; index1.loc = loc; index1.m_left = nullptr; + index1.m_right = var2indices[j][0]; index1.m_step = nullptr; + new_indices.push_back(al, index1.m_right); + indices1.push_back(al, index1); + array_index.m_right = ASRUtils::EXPR(ASRUtils::make_ArrayItem_t_util(al, loc, + m_args[i].m_right, indices1.p, 1, int32_type, + ASR::arraystorageType::ColMajor, nullptr)); + array_index.m_step = nullptr; + array_item_args.push_back(al, array_index); + j++; + k++; + } else { + array_item_args.push_back(al, m_args[i]); + } + } else { + ASR::array_index_t index1; index1.loc = loc; index1.m_left = nullptr; + index1.m_right = var2indices[var2indices_key][k]; index1.m_step = nullptr; + array_item_args.push_back(al, index1); + new_indices.push_back(al, var2indices[var2indices_key][k]); + k++; + } } - return ; + var2indices[var2indices_key] = new_indices; + ASR::ttype_t* expr_type = ASRUtils::extract_type( + ASRUtils::expr_type(expr)); + *expr_address = ASRUtils::EXPR(ASRUtils::make_ArrayItem_t_util( + al, loc, ASRUtils::extract_array_variable(expr), array_item_args.p, + array_item_args.size(), expr_type, ASR::arraystorageType::ColMajor, nullptr)); } - replace_intrinsic_function(x); } - void replace_ArrayPhysicalCast(ASR::ArrayPhysicalCast_t* x) { - ASR::BaseExprReplacer::replace_ArrayPhysicalCast(x); - if( (x->m_old == x->m_new && - x->m_old != ASR::array_physical_typeType::DescriptorArray) || - (x->m_old == x->m_new && x->m_old == ASR::array_physical_typeType::DescriptorArray && - (ASR::is_a(*ASRUtils::expr_type(x->m_arg)) || - ASR::is_a(*ASRUtils::expr_type(x->m_arg)))) || - x->m_old != ASRUtils::extract_physical_type(ASRUtils::expr_type(x->m_arg)) ) { - *current_expr = x->m_arg; - } else { - x->m_old = ASRUtils::extract_physical_type(ASRUtils::expr_type(x->m_arg)); + template + void generate_loop_for_array_indexed_with_array_indices(const T& x, + ASR::expr_t** target_address, ASR::expr_t** value_address, + const Location& loc) { + ASR::expr_t* target = *target_address; + ASR::expr_t* value = *value_address; + size_t var_rank = ASRUtils::extract_n_dims_from_ttype(ASRUtils::expr_type(target)); + Vec vars_expr; vars_expr.reserve(al, 2); + bool is_target_array = ASRUtils::is_array(ASRUtils::expr_type(target)); + bool is_value_array = ASRUtils::is_array(ASRUtils::expr_type(value)); + Vec array_indices_args; array_indices_args.reserve(al, 1); + Vec rhs_array_indices_args; rhs_array_indices_args.reserve(al, 1); + int n_array_indices_args = -1; + int temp_n = -1; + size_t do_loop_depth = var_rank; + if( is_target_array ) { + vars_expr.push_back(al, ASRUtils::extract_array_variable(target)); + ASRUtils::extract_array_indices(target, al, array_indices_args, n_array_indices_args); + } + if( is_value_array ) { + vars_expr.push_back(al, ASRUtils::extract_array_variable(value)); + ASRUtils::extract_array_indices(value, al, rhs_array_indices_args, temp_n); } - } - void replace_FunctionCall(ASR::FunctionCall_t* x) { - // The following checks if the name of a function actually - // points to a subroutine. If true this would mean that the - // original function returned an array and is now a subroutine. - // So the current function call will be converted to a subroutine - // call. In short, this check acts as a signal whether to convert - // a function call to a subroutine call. - if (current_scope == nullptr) { - return ; - } + size_t offset_for_array_indices = 0; - const Location& loc = x->base.base.loc; - if( PassUtils::is_elemental(x->m_name) ) { - std::vector array_mask(x->n_args, false); - bool at_least_one_array = false; - for( size_t iarg = 0; iarg < x->n_args; iarg++ ) { - array_mask[iarg] = (x->m_args[iarg].m_value != nullptr && - ASRUtils::is_array(ASRUtils::expr_type(x->m_args[iarg].m_value))); - at_least_one_array = at_least_one_array || array_mask[iarg]; - } - if (!at_least_one_array) { - return ; - } - ASR::expr_t* result_var_copy = result_var; - std::string res_prefix = "_elemental_func_call_res"; - bool is_all_rank_0 = true; - std::vector operands; - ASR::expr_t* operand = nullptr, *first_array_operand = nullptr; - int common_rank = 0; - bool are_all_rank_same = true; - for( size_t iarg = 0; iarg < x->n_args; iarg++ ) { - if (x->m_args[iarg].m_value == nullptr) { - operands.push_back(nullptr); - continue; - } - ASR::expr_t** current_expr_copy_9 = current_expr; - current_expr = &(x->m_args[iarg].m_value); - self().replace_expr(x->m_args[iarg].m_value); - operand = *current_expr; - current_expr = current_expr_copy_9; - operands.push_back(operand); - int rank_operand = PassUtils::get_rank(operand); - if( rank_operand > 0 && first_array_operand == nullptr ) { - first_array_operand = operand; - } - if( common_rank == 0 ) { - common_rank = rank_operand; - } - if( common_rank != rank_operand && - rank_operand > 0 ) { - are_all_rank_same = false; - } - array_mask[iarg] = (rank_operand > 0); - is_all_rank_0 = is_all_rank_0 && (rank_operand <= 0); - } - if( is_all_rank_0 ) { - return ; - } - if( !are_all_rank_same ) { - throw LCompilersException("Broadcasting support not yet available " - "for different shape arrays."); - } - result_var = result_var_copy; - bool result_var_created = false; - if( result_var == nullptr ) { - ASR::Function_t* func = ASR::down_cast(ASRUtils::symbol_get_past_external(x->m_name)); - if (func->m_return_var != nullptr && !ASRUtils::is_array(ASRUtils::expr_type(func->m_return_var))) { - ASR::ttype_t* sibling_type = ASRUtils::expr_type(first_array_operand); - ASR::dimension_t* m_dims = nullptr; int ndims = 0; - PassUtils::get_dim_rank(sibling_type, m_dims, ndims); - LCOMPILERS_ASSERT(m_dims != nullptr); - ASR::ttype_t* arr_type = ASRUtils::make_Array_t_util( - al, loc, ASRUtils::expr_type(func->m_return_var), m_dims, ndims); - if( ASRUtils::extract_physical_type(arr_type) == - ASR::array_physical_typeType::DescriptorArray ) { - arr_type = ASRUtils::TYPE(ASR::make_Allocatable_t(al, loc, arr_type)); - } - result_var = PassUtils::create_var(result_counter, res_prefix, - loc, arr_type, al, current_scope); - } else { - result_var = PassUtils::create_var(result_counter, res_prefix, - loc, operand, al, current_scope); - } - result_counter += 1; - result_var_created = true; - } - *current_expr = result_var; - if( op_expr == &(x->base) ) { - op_dims = nullptr; - op_n_dims = ASRUtils::extract_dimensions_from_ttype( - ASRUtils::expr_type(*current_expr), op_dims); - } - ASR::dimension_t* m_dims; - int n_dims = ASRUtils::extract_dimensions_from_ttype( - ASRUtils::expr_type(operand), m_dims); - allocate_result_var(operand, m_dims, n_dims, result_var_created, false); - *current_expr = result_var; - - Vec idx_vars, loop_vars, idx_vars_value; - std::vector loop_var_indices; - Vec doloop_body; - create_do_loop(loc, common_rank, idx_vars, idx_vars_value, - loop_vars, loop_var_indices, doloop_body, first_array_operand, - [=, &operands, &idx_vars, &idx_vars_value, &doloop_body] () { - Vec ref_args; - ref_args.reserve(al, x->n_args); - for( size_t iarg = 0; iarg < x->n_args; iarg++ ) { - ASR::expr_t* ref = operands[iarg]; - if( array_mask[iarg] ) { - ref = PassUtils::create_array_ref(operands[iarg], idx_vars_value, al, current_scope); - } - ASR::call_arg_t ref_arg; - ref_arg.loc = x->m_args[iarg].loc; - ref_arg.m_value = ref; - ref_args.push_back(al, ref_arg); - } - Vec empty_dim; - empty_dim.reserve(al, 1); - ASR::ttype_t* dim_less_type = ASRUtils::duplicate_type(al, x->m_type, &empty_dim); - ASR::expr_t* op_el_wise = nullptr; - op_el_wise = ASRUtils::EXPR(ASRUtils::make_FunctionCall_t_util(al, loc, - x->m_name, x->m_original_name, ref_args.p, ref_args.size(), dim_less_type, - nullptr, x->m_dt)); - ASR::expr_t* res = PassUtils::create_array_ref(result_var, idx_vars, al, current_scope); - ASR::stmt_t* assign = ASRUtils::STMT(ASR::make_Assignment_t(al, loc, res, op_el_wise, nullptr)); - doloop_body.push_back(al, assign); - }); - if( !result_var_created ) { - use_custom_loop_params = false; + fill_array_indices_in_vars_expr( + target, is_target_array, + vars_expr, offset_for_array_indices); + fill_array_indices_in_vars_expr( + value, is_value_array, + vars_expr, offset_for_array_indices); + + // Common code for target and value + std::unordered_map> var2indices; + std::unordered_map> index2var; + ASR::ttype_t* int32_type = ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)); + for( size_t i = 0; i < vars_expr.size(); i++ ) { + Vec indices; + indices.reserve(al, var_rank); + for( size_t j = 0; j < (i >= offset_for_array_indices ? 1 : var_rank); j++ ) { + std::string index_var_name = current_scope->get_unique_name( + "__libasr_index_" + std::to_string(j) + "_"); + ASR::symbol_t* index = ASR::down_cast(ASRUtils::make_Variable_t_util( + al, loc, current_scope, s2c(al, index_var_name), nullptr, 0, ASR::intentType::Local, + nullptr, nullptr, ASR::storage_typeType::Default, int32_type, nullptr, + ASR::abiType::Source, ASR::accessType::Public, ASR::presenceType::Required, false)); + current_scope->add_symbol(index_var_name, index); + ASR::expr_t* index_expr = ASRUtils::EXPR(ASR::make_Var_t(al, loc, index)); + if ((i == offset_for_array_indices - 1) && is_value_array && + rhs_array_indices_args[j].m_left != nullptr) { + index2var[index_expr] = std::make_pair(rhs_array_indices_args[j].m_left, IndexType::ScalarIndex); + } else { + index2var[index_expr] = std::make_pair(vars_expr[i], + i >= offset_for_array_indices ? IndexType::ArrayIndex : IndexType::ScalarIndex); } + indices.push_back(al, index_expr); } - result_var = nullptr; + var2indices[i] = indices; } - void replace_Array(ASR::Array_t* /*x*/) { - } -}; + size_t j = offset_for_array_indices; -class ArrayOpVisitor : public ASR::CallReplacerOnExpressionsVisitor -{ - private: + create_array_item_array_indexed_expr( + target, target_address, is_target_array, 0, + var_rank, loc, var2indices, j, int32_type); + create_array_item_array_indexed_expr( + value, value_address, is_value_array, 1, + var_rank, loc, var2indices, j, int32_type); - Allocator& al; - bool use_custom_loop_params; - bool remove_original_statement; - ReplaceArrayOp replacer; - Vec pass_result; - Vec result_lbound, result_ubound, result_inc; - Vec* parent_body; - std::map resultvar2value; - bool realloc_lhs; + size_t vars_expr_size = vars_expr.size(); + for( size_t i = offset_for_array_indices; i < vars_expr_size; i++ ) { + var2indices.erase(i); + } + vars_expr.n = offset_for_array_indices; - public: + size_t var_with_maxrank = 0; - ArrayOpVisitor(Allocator& al_, bool realloc_lhs_) : - al(al_), use_custom_loop_params(false), - remove_original_statement(false), - replacer(al_, pass_result, use_custom_loop_params, - result_lbound, result_ubound, result_inc, - resultvar2value, realloc_lhs_), - parent_body(nullptr), realloc_lhs(realloc_lhs_) { - pass_result.n = 0; - result_lbound.n = 0; - result_ubound.n = 0; - result_inc.n = 0; + ASR::do_loop_head_t do_loop_head; + do_loop_head.loc = loc; + do_loop_head.m_v = at(var2indices[var_with_maxrank], -1); + size_t bound_dim = do_loop_depth; + if( index2var[do_loop_head.m_v].second == IndexType::ArrayIndex ) { + bound_dim = 1; } - - void call_replacer() { - replacer.current_expr = current_expr; - replacer.current_scope = current_scope; - replacer.replace_expr(*current_expr); + if( n_array_indices_args > -1 && array_indices_args[n_array_indices_args].m_right != nullptr && + array_indices_args[n_array_indices_args].m_left != nullptr && + array_indices_args[n_array_indices_args].m_step != nullptr) { + do_loop_head.m_start = array_indices_args[n_array_indices_args].m_left; + do_loop_head.m_end = array_indices_args[n_array_indices_args].m_right; + do_loop_head.m_increment = array_indices_args[n_array_indices_args].m_step; + } else { + do_loop_head.m_start = PassUtils::get_bound( + index2var[do_loop_head.m_v].first, bound_dim, "lbound", al); + do_loop_head.m_end = PassUtils::get_bound( + index2var[do_loop_head.m_v].first, bound_dim, "ubound", al); + do_loop_head.m_increment = nullptr; } - - void transform_stmts(ASR::stmt_t **&m_body, size_t &n_body) { - bool remove_original_statement_copy = remove_original_statement; - Vec body; - body.reserve(al, n_body); - if( parent_body ) { - for (size_t j=0; j < pass_result.size(); j++) { - parent_body->push_back(al, pass_result[j]); - } + Vec parent_do_loop_body; parent_do_loop_body.reserve(al, 1); + Vec do_loop_body; do_loop_body.reserve(al, 1); + set_index_variables(var2indices, index2var, var_with_maxrank, + var_rank, -1, parent_do_loop_body, loc); + do_loop_body.push_back(al, const_cast(&(x.base))); + increment_index_variables(var2indices, var_with_maxrank, -1, + do_loop_body, loc); + ASR::stmt_t* do_loop = ASRUtils::STMT(ASR::make_DoLoop_t(al, loc, nullptr, + do_loop_head, do_loop_body.p, do_loop_body.size(), nullptr, 0)); + do_loop_depth--; + n_array_indices_args--; + parent_do_loop_body.push_back(al, do_loop); + do_loop_body.from_pointer_n_copy(al, parent_do_loop_body.p, parent_do_loop_body.size()); + parent_do_loop_body.reserve(al, 1); + + for( int64_t i = -2; i >= -static_cast(var_rank); i-- ) { + set_index_variables(var2indices, index2var, var_with_maxrank, + var_rank, i, parent_do_loop_body, loc); + increment_index_variables(var2indices, var_with_maxrank, i, + do_loop_body, loc); + ASR::do_loop_head_t do_loop_head; + do_loop_head.loc = loc; + do_loop_head.m_v = at(var2indices[var_with_maxrank], i); + bound_dim = do_loop_depth; + if( index2var[do_loop_head.m_v].second == IndexType::ArrayIndex ) { + bound_dim = 1; } - for (size_t i=0; i* parent_body_copy = parent_body; - parent_body = &body; - visit_stmt(*m_body[i]); - parent_body = parent_body_copy; - for (size_t j=0; j < pass_result.size(); j++) { - body.push_back(al, pass_result[j]); - } - if( !remove_original_statement ) { - body.push_back(al, m_body[i]); - } + if( n_array_indices_args > -1 && array_indices_args[n_array_indices_args].m_right != nullptr && + array_indices_args[n_array_indices_args].m_left != nullptr && + array_indices_args[n_array_indices_args].m_step != nullptr) { + do_loop_head.m_start = array_indices_args[n_array_indices_args].m_left; + do_loop_head.m_end = array_indices_args[n_array_indices_args].m_right; + do_loop_head.m_increment = array_indices_args[n_array_indices_args].m_step; + } else { + do_loop_head.m_start = PassUtils::get_bound( + index2var[do_loop_head.m_v].first, bound_dim, "lbound", al); + do_loop_head.m_end = PassUtils::get_bound( + index2var[do_loop_head.m_v].first, bound_dim, "ubound", al); + do_loop_head.m_increment = nullptr; } - m_body = body.p; - n_body = body.size(); - replacer.result_var = nullptr; - replacer.result_type = nullptr; - pass_result.n = 0; - remove_original_statement = remove_original_statement_copy; + ASR::stmt_t* do_loop = ASRUtils::STMT(ASR::make_DoLoop_t(al, loc, nullptr, + do_loop_head, do_loop_body.p, do_loop_body.size(), nullptr, 0)); + do_loop_depth--; + n_array_indices_args--; + parent_do_loop_body.push_back(al, do_loop); + do_loop_body.from_pointer_n_copy(al, parent_do_loop_body.p, parent_do_loop_body.size()); + parent_do_loop_body.reserve(al, 1); + } + + for( size_t i = 0; i < do_loop_body.size(); i++ ) { + pass_result.push_back(al, do_loop_body[i]); } + } - // TODO: Only Program and While is processed, we need to process all calls - // to visit_stmt(). - // TODO: Only TranslationUnit's and Program's symbol table is processed - // for transforming function->subroutine if they return arrays - void visit_TranslationUnit(const ASR::TranslationUnit_t &x) { - SymbolTable* current_scope_copy = current_scope; - current_scope = x.m_symtab; - - std::vector build_order - = ASRUtils::determine_module_dependencies(x); - for (auto &item : build_order) { - LCOMPILERS_ASSERT(x.m_symtab->get_symbol(item)); - ASR::symbol_t *mod = x.m_symtab->get_symbol(item); - visit_symbol(*mod); + template + void generate_loop(const T& x, Vec& vars, + Vec& fix_types_args, + const Location& loc) { + Vec var_ranks; + Vec vars_expr; + var_ranks.reserve(al, vars.size()); vars_expr.reserve(al, vars.size()); + for( size_t i = 0; i < vars.size(); i++ ) { + ASR::expr_t* expr = *vars[i]; + ASR::ttype_t* type = ASRUtils::expr_type(expr); + var_ranks.push_back(al, ASRUtils::extract_n_dims_from_ttype(type)); + vars_expr.push_back(al, expr); + } + + std::unordered_map> var2indices; + ASR::ttype_t* int32_type = ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)); + for( size_t i = 0; i < vars.size(); i++ ) { + Vec indices; + indices.reserve(al, var_ranks[i]); + for( size_t j = 0; j < var_ranks[i]; j++ ) { + std::string index_var_name = current_scope->get_unique_name( + "__libasr_index_" + std::to_string(j) + "_"); + ASR::symbol_t* index = ASR::down_cast(ASRUtils::make_Variable_t_util( + al, loc, current_scope, s2c(al, index_var_name), nullptr, 0, ASR::intentType::Local, + nullptr, nullptr, ASR::storage_typeType::Default, int32_type, nullptr, + ASR::abiType::Source, ASR::accessType::Public, ASR::presenceType::Required, false)); + current_scope->add_symbol(index_var_name, index); + ASR::expr_t* index_expr = ASRUtils::EXPR(ASR::make_Var_t(al, loc, index)); + indices.push_back(al, index_expr); } + var2indices[i] = indices; + } - // Now visit everything else - for (auto &item : x.m_symtab->get_scope()) { - if (!ASR::is_a(*item.second)) { - this->visit_symbol(*item.second); - } + for( size_t i = 0; i < vars.size(); i++ ) { + Vec indices; + indices.reserve(al, var_ranks[i]); + for( size_t j = 0; j < var_ranks[i]; j++ ) { + ASR::array_index_t array_index; + array_index.loc = loc; + array_index.m_left = nullptr; + array_index.m_right = var2indices[i][j]; + array_index.m_step = nullptr; + indices.push_back(al, array_index); } - current_scope = current_scope_copy; + ASR::ttype_t* var_i_type = ASRUtils::extract_type( + ASRUtils::expr_type(*vars[i])); + *vars[i] = ASRUtils::EXPR(ASRUtils::make_ArrayItem_t_util(al, loc, *vars[i], indices.p, + indices.size(), var_i_type, ASR::arraystorageType::ColMajor, nullptr)); } - void visit_Module(const ASR::Module_t &x) { - // FIXME: this is a hack, we need to pass in a non-const `x`, - // which requires to generate a TransformVisitor. - SymbolTable* current_scope_copy = current_scope; - current_scope = x.m_symtab; + ASRUtils::RemoveArrayProcessingNodeVisitor array_broadcast_visitor(al); + for( size_t i = 0; i < fix_types_args.size(); i++ ) { + array_broadcast_visitor.current_expr = fix_types_args[i]; + array_broadcast_visitor.call_replacer(); + } - // Now visit everything else - for (auto &item : x.m_symtab->get_scope()) { - this->visit_symbol(*item.second); - } - current_scope = current_scope_copy; + FixTypeVisitor fix_types(al); + fix_types.current_scope = current_scope; + for( size_t i = 0; i < fix_types_args.size(); i++ ) { + fix_types.visit_expr(*(*fix_types_args[i])); } - void visit_Program(const ASR::Program_t &x) { - // FIXME: this is a hack, we need to pass in a non-const `x`, - // which requires to generate a TransformVisitor. - ASR::Program_t& xx = const_cast(x); - SymbolTable* current_scope_copy = current_scope; - current_scope = xx.m_symtab; - - for (auto &item : x.m_symtab->get_scope()) { - if (is_a(*item.second)) { - ASR::AssociateBlock_t *s = ASR::down_cast(item.second); - visit_AssociateBlock(*s); - } - if (is_a(*item.second)) { - visit_Function(*ASR::down_cast( - item.second)); - } + size_t var_with_maxrank = 0; + for( size_t i = 0; i < var_ranks.size(); i++ ) { + if( var_ranks[i] > var_ranks[var_with_maxrank] ) { + var_with_maxrank = i; } + } - transform_stmts(xx.m_body, xx.n_body); - current_scope = current_scope_copy; + ASR::do_loop_head_t do_loop_head; + do_loop_head.loc = loc; + do_loop_head.m_v = at(var2indices[var_with_maxrank], -1); + do_loop_head.m_start = PassUtils::get_bound(vars_expr[var_with_maxrank], + var_ranks[var_with_maxrank], "lbound", al); + do_loop_head.m_end = PassUtils::get_bound(vars_expr[var_with_maxrank], + var_ranks[var_with_maxrank], "ubound", al); + do_loop_head.m_increment = nullptr; + Vec parent_do_loop_body; parent_do_loop_body.reserve(al, 1); + Vec do_loop_body; do_loop_body.reserve(al, 1); + set_index_variables(var2indices, vars_expr, var_with_maxrank, + var_ranks[var_with_maxrank], -1, parent_do_loop_body, loc); + do_loop_body.push_back(al, const_cast(&(x.base))); + increment_index_variables(var2indices, var_with_maxrank, -1, + do_loop_body, loc); + ASR::stmt_t* do_loop = ASRUtils::STMT(ASR::make_DoLoop_t(al, loc, nullptr, + do_loop_head, do_loop_body.p, do_loop_body.size(), nullptr, 0)); + parent_do_loop_body.push_back(al, do_loop); + do_loop_body.from_pointer_n_copy(al, parent_do_loop_body.p, parent_do_loop_body.size()); + parent_do_loop_body.reserve(al, 1); + + for( int64_t i = -2; i >= -static_cast(var_ranks[var_with_maxrank]); i-- ) { + set_index_variables(var2indices, vars_expr, var_with_maxrank, + var_ranks[var_with_maxrank], i, parent_do_loop_body, loc); + increment_index_variables(var2indices, var_with_maxrank, i, + do_loop_body, loc); + ASR::do_loop_head_t do_loop_head; + do_loop_head.loc = loc; + do_loop_head.m_v = at(var2indices[var_with_maxrank], i); + do_loop_head.m_start = PassUtils::get_bound(vars_expr[var_with_maxrank], + var_ranks[var_with_maxrank] + i + 1, "lbound", al); + do_loop_head.m_end = PassUtils::get_bound(vars_expr[var_with_maxrank], + var_ranks[var_with_maxrank] + i + 1, "ubound", al); + do_loop_head.m_increment = nullptr; + ASR::stmt_t* do_loop = ASRUtils::STMT(ASR::make_DoLoop_t(al, loc, nullptr, + do_loop_head, do_loop_body.p, do_loop_body.size(), nullptr, 0)); + parent_do_loop_body.push_back(al, do_loop); + do_loop_body.from_pointer_n_copy(al, parent_do_loop_body.p, parent_do_loop_body.size()); + parent_do_loop_body.reserve(al, 1); } - inline void visit_AssignmentUtil(const ASR::Assignment_t& x) { - ASR::expr_t** current_expr_copy_9 = current_expr; - ASR::expr_t* original_value = x.m_value; - if( ASR::is_a(*x.m_value) ) { - resultvar2value[replacer.result_var] = - ASR::down_cast(original_value)->m_array; - } else { - resultvar2value[replacer.result_var] = original_value; - } - current_expr = const_cast(&(x.m_value)); - this->call_replacer(); - current_expr = current_expr_copy_9; - if( x.m_value == original_value ) { - ASR::expr_t* result_var_copy = replacer.result_var; - replacer.result_var = nullptr; - this->visit_expr(*x.m_value); - replacer.result_var = result_var_copy; - remove_original_statement = false; - } else if( x.m_value ) { - if( ASR::is_a(*x.m_value) ) { - remove_original_statement = false; - return ; - } - this->visit_expr(*x.m_value); - } - if (x.m_overloaded) { - this->visit_stmt(*x.m_overloaded); - } + for( size_t i = 0; i < do_loop_body.size(); i++ ) { + pass_result.push_back(al, do_loop_body[i]); } + } - void visit_Assignment(const ASR::Assignment_t &x) { - const Location& loc = x.base.base.loc; - if (ASRUtils::is_simd_array(x.m_target)) { - size_t n_dims = 1; - if (ASR::is_a(*x.m_value)) { - n_dims = ASRUtils::extract_n_dims_from_ttype( - ASRUtils::expr_type(down_cast( - x.m_value)->m_v)); - } - if (n_dims == 1) { - if (!ASR::is_a(*x.m_value)) { - this->visit_expr(*x.m_value); - } - return; - } + void insert_realloc_for_target(ASR::expr_t* target, ASR::expr_t* value, Vec& vars) { + ASR::ttype_t* target_type = ASRUtils::expr_type(target); + if( (realloc_lhs == false || !ASRUtils::is_allocatable(target_type) || vars.size() == 1) && + !(ASR::is_a(*value) && ASR::is_a(*target) && + ASRUtils::is_allocatable(target_type)) ) { + return ; + } + + // First element in vars is target itself + ASR::expr_t* realloc_var = nullptr; + size_t target_rank = ASRUtils::extract_n_dims_from_ttype(target_type); + for( size_t i = 1; i < vars.size(); i++ ) { + size_t var_rank = ASRUtils::extract_n_dims_from_ttype( + ASRUtils::expr_type(*vars[i])); + if( target_rank == var_rank ) { + realloc_var = *vars[i]; + break ; } - if( (ASR::is_a(*ASRUtils::expr_type(x.m_target)) && - ASR::is_a(*x.m_value)) || - (ASR::is_a(*x.m_value) || - ASR::is_a(*x.m_value)) ) { - if( realloc_lhs && ASRUtils::is_allocatable(x.m_target)) { // Add realloc-lhs later - Vec vec_alloc; - vec_alloc.reserve(al, 1); - ASR::alloc_arg_t alloc_arg; - alloc_arg.m_len_expr = nullptr; - alloc_arg.m_type = nullptr; - alloc_arg.loc = x.m_target->base.loc; - alloc_arg.m_a = x.m_target; - - - ASR::dimension_t* m_dims = nullptr; - size_t n_dims = ASRUtils::extract_dimensions_from_ttype( - ASRUtils::expr_type(x.m_value), m_dims); - Vec vec_dims; - vec_dims.reserve(al, n_dims); - ASR::ttype_t* int32_type = ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)); - for( size_t i = 0; i < n_dims; i++ ) { - ASR::dimension_t dim; - dim.loc = x.m_value->base.loc; - dim.m_start = PassUtils::get_bound(x.m_value, i + 1, "lbound", al); - dim.m_length = ASRUtils::get_size(x.m_value, i + 1, al); - dim.m_start = CastingUtil::perform_casting(dim.m_start, int32_type, al, loc); - dim.m_length = CastingUtil::perform_casting(dim.m_length, int32_type, al, loc); - vec_dims.push_back(al, dim); - } + } + Location loc; loc.first = 1, loc.last = 1; + ASRUtils::ASRBuilder builder(al, loc); + Vec realloc_dims; + realloc_dims.reserve(al, target_rank); + for( size_t i = 0; i < target_rank; i++ ) { + ASR::dimension_t realloc_dim; + realloc_dim.loc = loc; + realloc_dim.m_start = builder.i32(1); + realloc_dim.m_length = ASRUtils::EXPR(ASR::make_ArraySize_t( + al, loc, realloc_var, builder.i32(i + 1), int32, nullptr)); + realloc_dims.push_back(al, realloc_dim); + } - alloc_arg.m_dims = vec_dims.p; - alloc_arg.n_dims = vec_dims.n; - vec_alloc.push_back(al, alloc_arg); - Vec to_be_deallocated; - to_be_deallocated.reserve(al, vec_alloc.size()); - for( size_t i = 0; i < vec_alloc.size(); i++ ) { - to_be_deallocated.push_back(al, vec_alloc.p[i].m_a); - } - pass_result.push_back(al, ASRUtils::STMT(ASR::make_ExplicitDeallocate_t( - al, x.base.base.loc, to_be_deallocated.p, to_be_deallocated.size()))); - pass_result.push_back(al, ASRUtils::STMT(ASR::make_Allocate_t( - al, x.base.base.loc, vec_alloc.p, 1, nullptr, nullptr, nullptr))); - remove_original_statement = false; - } - return ; - } + Vec alloc_args; alloc_args.reserve(al, 1); + ASR::alloc_arg_t alloc_arg; + alloc_arg.loc = loc; + alloc_arg.m_a = target; + alloc_arg.m_dims = realloc_dims.p; + alloc_arg.n_dims = realloc_dims.size(); + alloc_arg.m_len_expr = nullptr; + alloc_arg.m_type = nullptr; + alloc_args.push_back(al, alloc_arg); + + pass_result.push_back(al, ASRUtils::STMT(ASR::make_ReAlloc_t( + al, loc, alloc_args.p, alloc_args.size()))); + } - if( ASR::is_a(*x.m_value) ) { - visit_AssignmentUtil(x); + void visit_Assignment(const ASR::Assignment_t& x) { + if (ASRUtils::is_simd_array(x.m_target)) { + if( !(ASRUtils::is_allocatable(x.m_value) || + ASRUtils::is_pointer(ASRUtils::expr_type(x.m_value))) ) { return ; } - - if( PassUtils::is_array(x.m_target) ) { - replacer.result_var = x.m_target; - replacer.result_type = ASRUtils::expr_type(x.m_target); - } else if( ASR::is_a(*x.m_target) ) { - ASR::ArraySection_t* array_ref = ASR::down_cast(x.m_target); - replacer.result_var = array_ref->m_v; - result_lbound.reserve(al, array_ref->n_args); - result_ubound.reserve(al, array_ref->n_args); - result_inc.reserve(al, array_ref->n_args); - ASR::expr_t *m_start, *m_end, *m_increment; - m_start = m_end = m_increment = nullptr; - for( int i = 0; i < (int) array_ref->n_args; i++ ) { - if( array_ref->m_args[i].m_step != nullptr ) { - if( array_ref->m_args[i].m_left == nullptr ) { - m_start = PassUtils::get_bound(replacer.result_var, i + 1, "lbound", al); - } else { - m_start = array_ref->m_args[i].m_left; - } - if( array_ref->m_args[i].m_right == nullptr ) { - m_end = PassUtils::get_bound(replacer.result_var, i + 1, "ubound", al); - } else { - m_end = array_ref->m_args[i].m_right; - } - } else { - m_start = array_ref->m_args[i].m_right; - m_end = array_ref->m_args[i].m_right; - } - m_increment = array_ref->m_args[i].m_step; - result_lbound.push_back(al, m_start); - result_ubound.push_back(al, m_end); - result_inc.push_back(al, m_increment); - } - use_custom_loop_params = true; + } + ASR::Assignment_t& xx = const_cast(x); + const std::vector& skip_exprs = { + ASR::exprType::IntrinsicArrayFunction, + ASR::exprType::ArrayReshape, + }; + if ( ASR::is_a(*xx.m_value) ) { + // We need to do this because, we may have an assignment + // in which IntrinsicArrayFunction is evaluated already and + // value is an ArrayConstant, thus we need to unroll it. + ASR::IntrinsicArrayFunction_t* iaf = ASR::down_cast(xx.m_value); + if ( iaf->m_value != nullptr ) { + xx.m_value = iaf->m_value; } - remove_original_statement = true; + } + if( !ASRUtils::is_array(ASRUtils::expr_type(xx.m_target)) || + std::find(skip_exprs.begin(), skip_exprs.end(), xx.m_value->type) != skip_exprs.end() || + (ASRUtils::is_simd_array(xx.m_target) && ASRUtils::is_simd_array(xx.m_value)) ) { + return ; + } + xx.m_value = ASRUtils::get_past_array_broadcast(xx.m_value); + const Location loc = x.base.base.loc; + + #define is_array_indexed_with_array_indices_check(expr) \ + ASR::is_a(*expr) || ( \ + ASR::is_a(*expr) && \ + ASRUtils::is_array_indexed_with_array_indices( \ + ASR::down_cast(expr))) + if( ( is_array_indexed_with_array_indices_check(xx.m_value) ) || + ( is_array_indexed_with_array_indices_check(xx.m_target) ) ) { + generate_loop_for_array_indexed_with_array_indices( + x, &(xx.m_target), &(xx.m_value), loc); + return ; + } - visit_AssignmentUtil(x); - use_custom_loop_params = false; + if( call_replace_on_expr(xx.m_value->type) ) { + replacer.result_expr = xx.m_target; + ASR::expr_t** current_expr_copy = current_expr; + current_expr = const_cast(&xx.m_value); + this->call_replacer(); + current_expr = current_expr_copy; + replacer.result_expr = nullptr; + return ; } - template - void create_do_loop(const Location& loc, ASR::expr_t* value_array, int var_rank, int result_rank, - Vec& idx_vars, Vec& loop_vars, - Vec& idx_vars_value, std::vector& loop_var_indices, - Vec& doloop_body, ASR::expr_t* op_expr, int op_expr_dim_offset, - LOOP_BODY loop_body) { - PassUtils::create_idx_vars(idx_vars_value, var_rank, loc, al, current_scope, "_v"); - if( use_custom_loop_params ) { - PassUtils::create_idx_vars(idx_vars, loop_vars, loop_var_indices, - result_ubound, result_inc, - loc, al, current_scope, "_t"); - } else { - PassUtils::create_idx_vars(idx_vars, result_rank, loc, al, current_scope, "_t"); - loop_vars.from_pointer_n_copy(al, idx_vars.p, idx_vars.size()); - } - ASR::stmt_t* doloop = nullptr; - LCOMPILERS_ASSERT(result_rank >= var_rank); - // LCOMPILERS_ASSERT(var_rank == (int) loop_vars.size()); - ASR::ttype_t* int32_type = ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)); - ASR::expr_t* const_1 = ASRUtils::EXPR(ASR::make_IntegerConstant_t(al, loc, 1, int32_type)); - if (var_rank == (int) loop_vars.size()) { - for( int i = var_rank - 1; i >= 0; i-- ) { - // TODO: Add an If debug node to check if the lower and upper bounds of both the arrays are same. - ASR::do_loop_head_t head; - head.m_v = loop_vars[i]; - if( use_custom_loop_params ) { - int j = loop_var_indices[i]; - head.m_start = result_lbound[j]; - head.m_end = result_ubound[j]; - head.m_increment = result_inc[j]; - } else { - head.m_start = PassUtils::get_bound(value_array, i + 1, "lbound", al); - head.m_end = PassUtils::get_bound(value_array, i + 1, "ubound", al); - head.m_increment = nullptr; - } - head.loc = head.m_v->base.loc; - doloop_body.reserve(al, 1); - if( doloop == nullptr ) { - loop_body(); - } else { - if( var_rank > 0 ) { - ASR::expr_t* idx_lb = PassUtils::get_bound(op_expr, i + op_expr_dim_offset, "lbound", al); - ASR::stmt_t* set_to_one = ASRUtils::STMT(ASR::make_Assignment_t( - al, loc, idx_vars_value[i+1], idx_lb, nullptr)); - doloop_body.push_back(al, set_to_one); - } - doloop_body.push_back(al, doloop); - } - if( var_rank > 0 ) { - ASR::expr_t* inc_expr = ASRUtils::EXPR(ASR::make_IntegerBinOp_t( - al, loc, idx_vars_value[i], ASR::binopType::Add, const_1, int32_type, nullptr)); - ASR::stmt_t* assign_stmt = ASRUtils::STMT(ASR::make_Assignment_t( - al, loc, idx_vars_value[i], inc_expr, nullptr)); - doloop_body.push_back(al, assign_stmt); - } - doloop = ASRUtils::STMT(ASR::make_DoLoop_t(al, loc, nullptr, head, doloop_body.p, doloop_body.size(), nullptr, 0)); - } - if( var_rank > 0 ) { - ASR::expr_t* idx_lb = PassUtils::get_bound(op_expr, 1, "lbound", al); - ASR::stmt_t* set_to_one = ASRUtils::STMT(ASR::make_Assignment_t(al, loc, idx_vars_value[0], idx_lb, nullptr)); - pass_result.push_back(al, set_to_one); - } - pass_result.push_back(al, doloop); - } else if (var_rank == 0) { - for( int i = loop_vars.size() - 1; i >= 0; i-- ) { - // TODO: Add an If debug node to check if the lower and upper bounds of both the arrays are same. - ASR::do_loop_head_t head; - head.m_v = loop_vars[i]; - if( use_custom_loop_params ) { - int j = loop_var_indices[i]; - head.m_start = result_lbound[j]; - head.m_end = result_ubound[j]; - head.m_increment = result_inc[j]; - } else { - head.m_start = PassUtils::get_bound(value_array, i + 1, "lbound", al); - head.m_end = PassUtils::get_bound(value_array, i + 1, "ubound", al); - head.m_increment = nullptr; - } - head.loc = head.m_v->base.loc; - doloop_body.reserve(al, 1); - if( doloop == nullptr ) { - loop_body(); - } else { - doloop_body.push_back(al, doloop); - } - doloop = ASRUtils::STMT(ASR::make_DoLoop_t(al, loc, nullptr, head, doloop_body.p, doloop_body.size(), nullptr, 0)); - } - pass_result.push_back(al, doloop); - } + Vec vars; + vars.reserve(al, 1); + ArrayVarAddressCollector var_collector_target(al, vars); + var_collector_target.current_expr = const_cast(&(xx.m_target)); + var_collector_target.call_replacer(); + ArrayVarAddressCollector var_collector_value(al, vars); + var_collector_value.current_expr = const_cast(&(xx.m_value)); + var_collector_value.call_replacer(); + + if (vars.size() == 1 && + ASRUtils::is_array(ASRUtils::expr_type(ASRUtils::get_past_array_broadcast(xx.m_value))) + ) { + return ; } - void visit_SubroutineCall(const ASR::SubroutineCall_t& x) { - ASR::symbol_t* sym = x.m_original_name; - if (sym && ASR::is_a(*sym)) { - ASR::ExternalSymbol_t* ext_sym = ASR::down_cast(sym); - std::string name = ext_sym->m_name; - std::string module_name = ext_sym->m_module_name; - if (module_name == "lfortran_intrinsic_math" && name == "random_number") { - // iterate over args and check if any of them is an array - ASR::expr_t* arg = nullptr; - for (size_t i=0; i idx_vars, loop_vars, idx_vars_value; - std::vector loop_var_indices; - Vec doloop_body; - create_do_loop(arg->base.loc, arg, var_rank, result_rank, idx_vars, - loop_vars, idx_vars_value, loop_var_indices, doloop_body, - arg, 2, - [=, &idx_vars_value, &idx_vars, &doloop_body]() { - Vec array_index; array_index.reserve(al, idx_vars.size()); - for( size_t i = 0; i < idx_vars.size(); i++ ) { - ASR::array_index_t idx; - idx.m_left = nullptr; - idx.m_right = idx_vars_value[i]; - idx.m_step = nullptr; - idx.loc = idx_vars_value[i]->base.loc; - array_index.push_back(al, idx); - } - ASR::expr_t* array_item = ASRUtils::EXPR(ASR::make_ArrayItem_t(al, x.base.base.loc, - arg, array_index.p, array_index.size(), - ASRUtils::type_get_past_array(ASRUtils::type_get_past_pointer( - ASRUtils::type_get_past_allocatable(ASRUtils::expr_type(arg)))), - ASR::arraystorageType::ColMajor, nullptr)); - Vec ref_args; ref_args.reserve(al, 1); - ASR::call_arg_t ref_arg; ref_arg.loc = array_item->base.loc; ref_arg.m_value = array_item; - ref_args.push_back(al, ref_arg); - ASR::stmt_t* subroutine_call = ASRUtils::STMT(ASRUtils::make_SubroutineCall_t_util(al, x.base.base.loc, - x.m_name, x.m_original_name, ref_args.p, ref_args.n, nullptr, nullptr, false, ASRUtils::get_class_proc_nopass_val(x.m_name))); - doloop_body.push_back(al, subroutine_call); - }); - remove_original_statement = true; - } - } - } - for (size_t i=0; i fix_type_args; + fix_type_args.reserve(al, 2); + fix_type_args.push_back(al, const_cast(&(xx.m_target))); + fix_type_args.push_back(al, const_cast(&(xx.m_value))); + + generate_loop(x, vars, fix_type_args, loc); + } + + void visit_SubroutineCall(const ASR::SubroutineCall_t& x) { + if( !PassUtils::is_elemental(x.m_name) ) { + return ; + } + const Location loc = x.base.base.loc; + + Vec vars; + vars.reserve(al, 1); + for( size_t i = 0; i < x.n_args; i++ ) { + if( x.m_args[i].m_value != nullptr && + ASRUtils::is_array(ASRUtils::expr_type(x.m_args[i].m_value)) ) { + vars.push_back(al, &(x.m_args[i].m_value)); } - if (x.m_dt) - visit_expr(*x.m_dt); } - void visit_Associate(const ASR::Associate_t& /*x*/) { + if( vars.size() == 0 ) { + return ; } - void visit_Array(const ASR::Array_t& /*x*/) { + Vec fix_type_args; + fix_type_args.reserve(al, 1); + + generate_loop(x, vars, fix_type_args, loc); + } + void visit_If(const ASR::If_t& x) { + if( !ASRUtils::is_array(ASRUtils::expr_type(x.m_test)) ) { + ASR::CallReplacerOnExpressionsVisitor::visit_If(x); + return ; } - void visit_ArrayBroadcast(const ASR::ArrayBroadcast_t& x) { - ASR::expr_t** current_expr_copy_269 = current_expr; - current_expr = const_cast(&(x.m_array)); - call_replacer(); - current_expr = current_expr_copy_269; - if( x.m_array ) { - visit_expr(*x.m_array); - } + const Location loc = x.base.base.loc; + + Vec vars; + vars.reserve(al, 1); + ArrayVarAddressCollector array_var_adress_collector_target(al, vars); + array_var_adress_collector_target.visit_If(x); + + if( vars.size() == 0 ) { + return ; } + Vec fix_type_args; + fix_type_args.reserve(al, 1); + + generate_loop(x, vars, fix_type_args, loc); + + ASRUtils::RemoveArrayProcessingNodeVisitor remove_array_processing_node_visitor(al); + remove_array_processing_node_visitor.visit_If(x); + + FixTypeVisitor fix_type_visitor(al); + fix_type_visitor.current_scope = current_scope; + fix_type_visitor.visit_If(x); + } + + void visit_CPtrToPointer(const ASR::CPtrToPointer_t& /*x*/) { + } + }; void pass_replace_array_op(Allocator &al, ASR::TranslationUnit_t &unit, const LCompilers::PassOptions& pass_options) { ArrayOpVisitor v(al, pass_options.realloc_lhs); + v.call_replacer_on_value = false; v.visit_TranslationUnit(unit); PassUtils::UpdateDependenciesVisitor u(al); u.visit_TranslationUnit(unit); diff --git a/src/libasr/pass/array_passed_in_function_call.cpp b/src/libasr/pass/array_passed_in_function_call.cpp new file mode 100644 index 0000000000..86c1daab6a --- /dev/null +++ b/src/libasr/pass/array_passed_in_function_call.cpp @@ -0,0 +1,894 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace LCompilers { + +using ASR::down_cast; +using ASR::is_a; + +/* +This pass collector that the BinOp only Var nodes and nothing else. +*/ +class ArrayVarCollector: public ASR::BaseWalkVisitor { + private: + + Allocator& al; + Vec& vars; + + public: + + ArrayVarCollector(Allocator& al_, Vec& vars_): al(al_), vars(vars_) {} + + void visit_Var(const ASR::Var_t& x) { + if( ASRUtils::is_array(ASRUtils::symbol_type(x.m_v)) ) { + vars.push_back(al, const_cast(&(x.base))); + } + } + + void visit_StructInstanceMember(const ASR::StructInstanceMember_t& x) { + if( ASRUtils::is_array(ASRUtils::symbol_type(x.m_m)) ) { + vars.push_back(al, const_cast(&(x.base))); + } + } + + void visit_ArrayBroadcast(const ASR::ArrayBroadcast_t& /*x*/) { + + } + + void visit_ArraySize(const ASR::ArraySize_t& /*x*/) { + + } + +}; + +void transform_stmts_impl(Allocator& al, ASR::stmt_t**& m_body, size_t& n_body, + Vec*& current_body, Vec*& body_after_curr_stmt, + std::function visit_stmt) { + Vec* current_body_copy = current_body; + Vec current_body_vec; current_body_vec.reserve(al, 1); + current_body_vec.reserve(al, n_body); + current_body = ¤t_body_vec; + for (size_t i = 0; i < n_body; i++) { + Vec* body_after_curr_stmt_copy = body_after_curr_stmt; + Vec body_after_curr_stmt_vec; body_after_curr_stmt_vec.reserve(al, 1); + body_after_curr_stmt = &body_after_curr_stmt_vec; + visit_stmt(*m_body[i]); + current_body->push_back(al, m_body[i]); + for (size_t j = 0; j < body_after_curr_stmt_vec.size(); j++) { + current_body->push_back(al, body_after_curr_stmt_vec[j]); + } + body_after_curr_stmt = body_after_curr_stmt_copy; + } + m_body = current_body_vec.p; n_body = current_body_vec.size(); + current_body = current_body_copy; +} + +/* + This pass is responsible to convert non-contiguous ( DescriptorArray, arrays with stride != 1 ) + arrays passed to functions by casting to contiguous ( PointerToDataArray ) arrays. + + For example: + + subroutine matprod(y) + real(8), intent(inout) :: y(:, :) + call istril(y) + end subroutine + + gets converted to: + + subroutine matprod(y) + real(8), intent(inout) :: y(:, :) + real(8), pointer :: y_tmp(:, :) + if (.not. is_contiguous(y)) + allocate(y_tmp(size(y, 1), size(y, 2))) + y_tmp = y + else + y_tmp => y + end if + call istril(y_tmp) + if (.not. is_contiguous(y)) ! only if intent is inout, out + y = y_tmp + deallocate(y_tmp) + end if + end subroutine +*/ +class CallVisitor : public ASR::CallReplacerOnExpressionsVisitor +{ +public: + + Allocator &al; + Vec* current_body; + Vec* body_after_curr_stmt; + + CallVisitor(Allocator &al_) : al(al_) {} + + + bool is_descriptor_array_casted_to_pointer_to_data( ASR::expr_t* expr ) { + if ( ASRUtils::is_array(ASRUtils::expr_type(expr) ) && + ASR::is_a(*expr) ) { + ASR::ArrayPhysicalCast_t* cast = ASR::down_cast(expr); + return cast->m_new == ASR::array_physical_typeType::PointerToDataArray && + cast->m_old == ASR::array_physical_typeType::DescriptorArray; + } + return false; + } + + void transform_stmts(ASR::stmt_t**& m_body, size_t& n_body) { + transform_stmts_impl(al, m_body, n_body, current_body, body_after_curr_stmt, + [this](const ASR::stmt_t& stmt) { visit_stmt(stmt); }); + } + + template + ASR::expr_t* get_first_array_function_args(T* func) { + int64_t first_array_arg_idx = -1; + ASR::expr_t* first_array_arg = nullptr; + for (int64_t i = 0; i < (int64_t)func->n_args; i++) { + ASR::ttype_t* func_arg_type; + if constexpr (std::is_same_v) { + func_arg_type = ASRUtils::expr_type(func->m_args[i].m_value); + } else { + func_arg_type = ASRUtils::expr_type(func->m_args[i]); + } + if (ASRUtils::is_array(func_arg_type)) { + first_array_arg_idx = i; + break; + } + } + LCOMPILERS_ASSERT(first_array_arg_idx != -1) + if constexpr (std::is_same_v) { + first_array_arg = func->m_args[first_array_arg_idx].m_value; + } else { + first_array_arg = func->m_args[first_array_arg_idx]; + } + return first_array_arg; + } + + + /* + sets allocation size of an elemental function, which can be + either an intrinsic elemental function or a user-defined + */ + template + void set_allocation_size_elemental_function( + Allocator& al, const Location& loc, + T* elemental_function, + Vec& allocate_dims + ) { + ASR::expr_t* int32_one = ASRUtils::EXPR(ASR::make_IntegerConstant_t( + al, loc, 1, ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)))); + size_t n_dims = ASRUtils::extract_n_dims_from_ttype(elemental_function->m_type); + allocate_dims.reserve(al, n_dims); + ASR::expr_t* first_array_arg = get_first_array_function_args(elemental_function); + for( size_t i = 0; i < n_dims; i++ ) { + ASR::dimension_t allocate_dim; + allocate_dim.loc = loc; + allocate_dim.m_start = int32_one; + ASR::expr_t* size_i_1 = ASRUtils::EXPR(ASR::make_ArraySize_t( + al, loc, ASRUtils::get_past_array_physical_cast(first_array_arg), + ASRUtils::EXPR(ASR::make_IntegerConstant_t( + al, loc, i + 1, ASRUtils::expr_type(int32_one))), + ASRUtils::expr_type(int32_one), nullptr)); + allocate_dim.m_length = size_i_1; + allocate_dims.push_back(al, allocate_dim); + } + } + + ASR::expr_t* create_temporary_variable_for_array(Allocator& al, + ASR::expr_t* value, SymbolTable* scope, std::string name_hint, + bool is_pointer_required=false) { + ASR::ttype_t* value_type = ASRUtils::expr_type(value); + LCOMPILERS_ASSERT(ASRUtils::is_array(value_type)); + + /* Figure out the type of the temporary array variable */ + ASR::dimension_t* value_m_dims = nullptr; + size_t value_n_dims = ASRUtils::extract_dimensions_from_ttype(value_type, value_m_dims); + + if (ASR::is_a(*value)) { + ASR::IntegerCompare_t* integer_compare = ASR::down_cast(value); + ASR::ttype_t* logical_type = ASRUtils::TYPE(ASR::make_Logical_t(al, value->base.loc, 4)); + + ASR::ttype_t* left_type = ASRUtils::expr_type(integer_compare->m_left); + ASR::ttype_t* right_type = ASRUtils::expr_type(integer_compare->m_right); + + if (ASR::is_a(*left_type)) { + ASR::Array_t* left_array_type = ASR::down_cast(left_type); + ASR::dimension_t* left_m_dims = nullptr; + size_t left_n_dims = ASRUtils::extract_dimensions_from_ttype(left_type, left_m_dims); + value_m_dims = left_m_dims; + value_n_dims = left_n_dims; + + if (left_array_type->m_physical_type == ASR::array_physical_typeType::FixedSizeArray) { + ASR::ttype_t* logical_array_type = ASRUtils::TYPE(ASR::make_Array_t(al, value->base.loc, logical_type, left_m_dims, left_n_dims, ASR::array_physical_typeType::FixedSizeArray)); + value_type = logical_array_type; + } else { + ASR::ttype_t* logical_array_type = ASRUtils::TYPE(ASR::make_Array_t(al, value->base.loc, logical_type, left_m_dims, left_n_dims, ASR::array_physical_typeType::PointerToDataArray)); + value_type = logical_array_type; + } + } else if (ASR::is_a(*right_type)) { + ASR::Array_t* right_array_type = ASR::down_cast(right_type); + ASR::dimension_t* right_m_dims = nullptr; + size_t right_n_dims = ASRUtils::extract_dimensions_from_ttype(right_type, right_m_dims); + value_m_dims = right_m_dims; + value_n_dims = right_n_dims; + + if (right_array_type->m_physical_type == ASR::array_physical_typeType::FixedSizeArray) { + ASR::ttype_t* logical_array_type = ASRUtils::TYPE(ASR::make_Array_t(al, value->base.loc, logical_type, right_m_dims, right_n_dims, ASR::array_physical_typeType::FixedSizeArray)); + value_type = logical_array_type; + } else { + ASR::ttype_t* logical_array_type = ASRUtils::TYPE(ASR::make_Array_t(al, value->base.loc, logical_type, right_m_dims, right_n_dims, ASR::array_physical_typeType::PointerToDataArray)); + value_type = logical_array_type; + } + } + } + // dimensions can be different for an ArrayConstructor e.g. [1, a], where `a` is an + // ArrayConstructor like [5, 2, 1] + if (ASR::is_a(*value) && + !PassUtils::is_args_contains_allocatable(value)) { + ASR::ArrayConstructor_t* arr_constructor = ASR::down_cast(value); + value_m_dims->m_length = ASRUtils::get_ArrayConstructor_size(al, arr_constructor); + } + bool is_fixed_sized_array = ASRUtils::is_fixed_size_array(value_type); + bool is_size_only_dependent_on_arguments = ASRUtils::is_dimension_dependent_only_on_arguments( + value_m_dims, value_n_dims); + bool is_allocatable = ASRUtils::is_allocatable(value_type); + ASR::ttype_t* var_type = nullptr; + if( (is_fixed_sized_array || is_size_only_dependent_on_arguments || is_allocatable) && + !is_pointer_required ) { + var_type = value_type; + } else { + var_type = ASRUtils::create_array_type_with_empty_dims(al, value_n_dims, value_type); + var_type = ASRUtils::TYPE(ASR::make_Pointer_t(al, var_type->base.loc, var_type)); + } + + std::string var_name = scope->get_unique_name("__libasr_created_" + name_hint); + ASR::symbol_t* temporary_variable = ASR::down_cast(ASRUtils::make_Variable_t_util( + al, value->base.loc, scope, s2c(al, var_name), nullptr, 0, ASR::intentType::Local, + nullptr, nullptr, ASR::storage_typeType::Default, var_type, nullptr, ASR::abiType::Source, + ASR::accessType::Public, ASR::presenceType::Required, false)); + scope->add_symbol(var_name, temporary_variable); + + return ASRUtils::EXPR(ASR::make_Var_t(al, temporary_variable->base.loc, temporary_variable)); + } + + bool set_allocation_size( + Allocator& al, ASR::expr_t* value, + Vec& allocate_dims, + size_t target_n_dims + ) { + if ( !ASRUtils::is_array(ASRUtils::expr_type(value)) ) { + return false; + } + const Location& loc = value->base.loc; + ASR::expr_t* int32_one = ASRUtils::EXPR(ASR::make_IntegerConstant_t( + al, loc, 1, ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)))); + if( ASRUtils::is_fixed_size_array(ASRUtils::expr_type(value)) ) { + ASR::dimension_t* m_dims = nullptr; + size_t n_dims = ASRUtils::extract_dimensions_from_ttype( + ASRUtils::expr_type(value), m_dims); + allocate_dims.reserve(al, n_dims); + for( size_t i = 0; i < n_dims; i++ ) { + ASR::dimension_t allocate_dim; + allocate_dim.loc = value->base.loc; + allocate_dim.m_start = int32_one; + allocate_dim.m_length = m_dims[i].m_length; + allocate_dims.push_back(al, allocate_dim); + } + return true; + } + switch( value->type ) { + case ASR::exprType::FunctionCall: { + ASR::FunctionCall_t* function_call = ASR::down_cast(value); + ASR::ttype_t* type = function_call->m_type; + if( ASRUtils::is_allocatable(type) ) { + return false; + } + if (PassUtils::is_elemental(function_call->m_name)) { + set_allocation_size_elemental_function(al, loc, function_call, allocate_dims); + break; + } + ASRUtils::ExprStmtDuplicator duplicator(al); + ASR::dimension_t* dims = nullptr; + size_t n_dims = ASRUtils::extract_dimensions_from_ttype(type, dims); + allocate_dims.reserve(al, n_dims); + for( size_t i = 0; i < n_dims; i++ ) { + ASR::dimension_t dim = dims[i]; + ASR::dimension_t dim_copy; + dim_copy.loc = dim.loc; + dim_copy.m_start = !dim.m_start ? nullptr : duplicator.duplicate_expr(dim.m_start); + dim_copy.m_length = !dim.m_length ? nullptr : duplicator.duplicate_expr(dim.m_length); + LCOMPILERS_ASSERT(dim_copy.m_start); + LCOMPILERS_ASSERT(dim_copy.m_length); + allocate_dims.push_back(al, dim_copy); + } + break ; + } + case ASR::exprType::IntegerBinOp: + case ASR::exprType::RealBinOp: + case ASR::exprType::ComplexBinOp: + case ASR::exprType::LogicalBinOp: + case ASR::exprType::UnsignedIntegerBinOp: + case ASR::exprType::IntegerCompare: + case ASR::exprType::RealCompare: + case ASR::exprType::ComplexCompare: + case ASR::exprType::LogicalCompare: + case ASR::exprType::UnsignedIntegerCompare: + case ASR::exprType::StringCompare: + case ASR::exprType::IntegerUnaryMinus: + case ASR::exprType::RealUnaryMinus: + case ASR::exprType::ComplexUnaryMinus: { + /* + Collect all the variables from these expressions, + then take the size of one of the arrays having + maximum dimensions for now. For now LFortran will + assume that broadcasting is doable for arrays with lesser + dimensions and the array having maximum dimensions + has compatible size of each dimension with other arrays. + */ + + Vec array_vars; array_vars.reserve(al, 1); + ArrayVarCollector array_var_collector(al, array_vars); + array_var_collector.visit_expr(*value); + Vec arrays_with_maximum_rank; + arrays_with_maximum_rank.reserve(al, 1); + LCOMPILERS_ASSERT(target_n_dims > 0); + for( size_t i = 0; i < array_vars.size(); i++ ) { + if( (size_t) ASRUtils::extract_n_dims_from_ttype( + ASRUtils::expr_type(array_vars[i])) == target_n_dims ) { + arrays_with_maximum_rank.push_back(al, array_vars[i]); + } + } + + LCOMPILERS_ASSERT(arrays_with_maximum_rank.size() > 0); + ASR::expr_t* selected_array = arrays_with_maximum_rank[0]; + allocate_dims.reserve(al, target_n_dims); + for( size_t i = 0; i < target_n_dims; i++ ) { + ASR::dimension_t allocate_dim; + Location loc; loc.first = 1, loc.last = 1; + allocate_dim.loc = loc; + // Assume 1 for Fortran. + allocate_dim.m_start = ASRUtils::EXPR(ASR::make_IntegerConstant_t( + al, loc, 1, ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)))); + ASR::expr_t* dim = ASRUtils::EXPR(ASR::make_IntegerConstant_t( + al, loc, i + 1, ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)))); + allocate_dim.m_length = ASRUtils::EXPR(ASR::make_ArraySize_t( + al, loc, ASRUtils::get_past_array_physical_cast(selected_array), + dim, ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)), nullptr)); + allocate_dims.push_back(al, allocate_dim); + } + break; + } + case ASR::exprType::LogicalNot: { + ASR::LogicalNot_t* logical_not = ASR::down_cast(value); + if ( ASRUtils::is_array(ASRUtils::expr_type(logical_not->m_arg)) ) { + size_t rank = ASRUtils::extract_n_dims_from_ttype( + ASRUtils::expr_type(logical_not->m_arg)); + ASR::expr_t* selected_array = logical_not->m_arg; + allocate_dims.reserve(al, rank); + for( size_t i = 0; i < rank; i++ ) { + ASR::dimension_t allocate_dim; + allocate_dim.loc = loc; + // Assume 1 for Fortran. + allocate_dim.m_start = ASRUtils::EXPR(ASR::make_IntegerConstant_t( + al, loc, 1, ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)))); + ASR::expr_t* dim = ASRUtils::EXPR(ASR::make_IntegerConstant_t( + al, loc, i + 1, ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)))); + allocate_dim.m_length = ASRUtils::EXPR(ASR::make_ArraySize_t( + al, loc, ASRUtils::get_past_array_physical_cast(selected_array), + dim, ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)), nullptr)); + allocate_dims.push_back(al, allocate_dim); + } + } + break; + } + case ASR::exprType::Cast: { + ASR::Cast_t* cast = ASR::down_cast(value); + if ( ASRUtils::is_array(ASRUtils::expr_type(cast->m_arg)) ) { + size_t rank = ASRUtils::extract_n_dims_from_ttype( + ASRUtils::expr_type(cast->m_arg)); + ASR::expr_t* selected_array = cast->m_arg; + allocate_dims.reserve(al, rank); + for( size_t i = 0; i < rank; i++ ) { + ASR::dimension_t allocate_dim; + allocate_dim.loc = loc; + // Assume 1 for Fortran. + allocate_dim.m_start = ASRUtils::EXPR(ASR::make_IntegerConstant_t( + al, loc, 1, ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)))); + ASR::expr_t* dim = ASRUtils::EXPR(ASR::make_IntegerConstant_t( + al, loc, i + 1, ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)))); + allocate_dim.m_length = ASRUtils::EXPR(ASR::make_ArraySize_t( + al, loc, ASRUtils::get_past_array_physical_cast(selected_array), + dim, ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)), nullptr)); + allocate_dims.push_back(al, allocate_dim); + } + } + break; + } + case ASR::exprType::ArraySection: { + ASR::ArraySection_t* array_section_t = ASR::down_cast(value); + allocate_dims.reserve(al, array_section_t->n_args); + for( size_t i = 0; i < array_section_t->n_args; i++ ) { + ASR::expr_t* start = array_section_t->m_args[i].m_left; + ASR::expr_t* end = array_section_t->m_args[i].m_right; + ASR::expr_t* step = array_section_t->m_args[i].m_step; + ASR::dimension_t allocate_dim; + allocate_dim.loc = loc; + allocate_dim.m_start = int32_one; + if( start == nullptr && step == nullptr && end != nullptr ) { + if( ASRUtils::is_array(ASRUtils::expr_type(end)) ) { + allocate_dim.m_length = ASRUtils::EXPR(ASRUtils::make_ArraySize_t_util( + al, loc, end, nullptr, ASRUtils::expr_type(int32_one), nullptr, false)); + allocate_dims.push_back(al, allocate_dim); + } + } else { + bool is_any_kind_8 = false; + ASR::expr_t * int_one = int32_one; + if( ASRUtils::extract_kind_from_ttype_t(ASRUtils::expr_type(end)) == 8 || + ASRUtils::extract_kind_from_ttype_t(ASRUtils::expr_type(start)) == 8 || + ASRUtils::extract_kind_from_ttype_t(ASRUtils::expr_type(step)) == 8 ) { + is_any_kind_8 = true; + } + if( is_any_kind_8 ) { + int_one = ASRUtils::EXPR(ASR::make_IntegerConstant_t( + al, loc, 1, ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 8)))); + } + ASR::expr_t* end_minus_start = ASRUtils::EXPR(ASR::make_IntegerBinOp_t(al, loc, + end, ASR::binopType::Sub, start, ASRUtils::expr_type(end), nullptr)); + ASR::expr_t* by_step = ASRUtils::EXPR(ASR::make_IntegerBinOp_t(al, loc, + end_minus_start, ASR::binopType::Div, step, ASRUtils::expr_type(end_minus_start), + nullptr)); + ASR::expr_t* length = ASRUtils::EXPR(ASR::make_IntegerBinOp_t(al, loc, + by_step, ASR::binopType::Add, int_one, ASRUtils::expr_type(by_step), nullptr)); + allocate_dim.m_length = length; + allocate_dims.push_back(al, allocate_dim); + } + } + break; + } + case ASR::exprType::ArrayItem: { + ASR::ArrayItem_t* array_item_t = ASR::down_cast(value); + allocate_dims.reserve(al, array_item_t->n_args); + for( size_t i = 0; i < array_item_t->n_args; i++ ) { + ASR::expr_t* start = array_item_t->m_args[i].m_left; + ASR::expr_t* end = array_item_t->m_args[i].m_right; + ASR::expr_t* step = array_item_t->m_args[i].m_step; + if( !(start == nullptr && step == nullptr && end != nullptr) ) { + continue ; + } + if( !ASRUtils::is_array(ASRUtils::expr_type(end)) ) { + continue ; + } + ASR::dimension_t allocate_dim; + allocate_dim.loc = loc; + allocate_dim.m_start = int32_one; + allocate_dim.m_length = ASRUtils::EXPR(ASRUtils::make_ArraySize_t_util( + al, loc, end, nullptr, ASRUtils::expr_type(int32_one), nullptr, false)); + allocate_dims.push_back(al, allocate_dim); + } + break; + } + case ASR::exprType::IntrinsicElementalFunction: { + ASR::IntrinsicElementalFunction_t* intrinsic_elemental_function = + ASR::down_cast(value); + set_allocation_size_elemental_function(al, loc, intrinsic_elemental_function, + allocate_dims); + break; + } + case ASR::exprType::IntrinsicArrayFunction: { + ASR::IntrinsicArrayFunction_t* intrinsic_array_function = + ASR::down_cast(value); + switch (intrinsic_array_function->m_arr_intrinsic_id) { + case static_cast(ASRUtils::IntrinsicArrayFunctions::All): + case static_cast(ASRUtils::IntrinsicArrayFunctions::Any): + case static_cast(ASRUtils::IntrinsicArrayFunctions::Count): + case static_cast(ASRUtils::IntrinsicArrayFunctions::Parity): + case static_cast(ASRUtils::IntrinsicArrayFunctions::Sum): + case static_cast(ASRUtils::IntrinsicArrayFunctions::MaxVal): + case static_cast(ASRUtils::IntrinsicArrayFunctions::MinVal): { + size_t n_dims = ASRUtils::extract_n_dims_from_ttype( + intrinsic_array_function->m_type); + allocate_dims.reserve(al, n_dims); + for( size_t i = 0; i < n_dims; i++ ) { + ASR::dimension_t allocate_dim; + allocate_dim.loc = loc; + allocate_dim.m_start = int32_one; + ASR::expr_t* size_i_1 = ASRUtils::EXPR(ASR::make_ArraySize_t( + al, loc, ASRUtils::get_past_array_physical_cast(intrinsic_array_function->m_args[0]), + ASRUtils::EXPR(ASR::make_IntegerConstant_t( + al, loc, i + 1, ASRUtils::expr_type(int32_one))), + ASRUtils::expr_type(int32_one), nullptr)); + ASR::expr_t* size_i_2 = ASRUtils::EXPR(ASR::make_ArraySize_t( + al, loc, ASRUtils::get_past_array_physical_cast(intrinsic_array_function->m_args[0]), + ASRUtils::EXPR(ASR::make_IntegerConstant_t( + al, loc, i + 2, ASRUtils::expr_type(int32_one))), + ASRUtils::expr_type(int32_one), nullptr)); + Vec merge_i_args; merge_i_args.reserve(al, 3); + merge_i_args.push_back(al, size_i_1); merge_i_args.push_back(al, size_i_2); + merge_i_args.push_back(al, ASRUtils::EXPR(ASR::make_IntegerCompare_t(al, loc, + ASRUtils::EXPR(ASR::make_IntegerConstant_t( + al, loc, i + 1, ASRUtils::expr_type(int32_one))), ASR::cmpopType::Lt, + intrinsic_array_function->m_args[1], + ASRUtils::TYPE(ASR::make_Logical_t(al, loc, 4)), nullptr))); + ASR::expr_t* merge_i = ASRUtils::EXPR(ASRUtils::make_IntrinsicElementalFunction_t_util( + al, loc, static_cast(ASRUtils::IntrinsicElementalFunctions::Merge), + merge_i_args.p, merge_i_args.size(), 0, ASRUtils::expr_type(int32_one), nullptr)); + allocate_dim.m_length = merge_i; + allocate_dims.push_back(al, allocate_dim); + } + break; + } + case static_cast(ASRUtils::IntrinsicArrayFunctions::Pack): { + size_t n_dims = ASRUtils::extract_n_dims_from_ttype( + intrinsic_array_function->m_type); + allocate_dims.reserve(al, n_dims); + for ( size_t i = 0; i < n_dims; i++ ) { + ASR::dimension_t allocate_dim; + allocate_dim.loc = loc; + allocate_dim.m_start = int32_one; + ASR::expr_t* size_i_1 = nullptr; + if (intrinsic_array_function->n_args == 3) { + size_i_1 = ASRUtils::EXPR(ASR::make_ArraySize_t( + al, loc, ASRUtils::get_past_array_physical_cast(intrinsic_array_function->m_args[2]), + ASRUtils::EXPR(ASR::make_IntegerConstant_t( + al, loc, i + 1, ASRUtils::expr_type(int32_one))), + ASRUtils::expr_type(int32_one), nullptr)); + } else { + Vec count_i_args; count_i_args.reserve(al, 1); + count_i_args.push_back(al, intrinsic_array_function->m_args[1]); + size_i_1 = ASRUtils::EXPR(ASRUtils::make_IntrinsicArrayFunction_t_util( + al, loc, static_cast(ASRUtils::IntrinsicArrayFunctions::Count), + count_i_args.p, count_i_args.size(), 0, ASRUtils::expr_type(int32_one), nullptr)); + } + allocate_dim.m_length = size_i_1; + allocate_dims.push_back(al, allocate_dim); + } + break; + } + case static_cast(ASRUtils::IntrinsicArrayFunctions::Shape): { + size_t n_dims = ASRUtils::extract_n_dims_from_ttype( + intrinsic_array_function->m_type); + allocate_dims.reserve(al, n_dims); + for( size_t i = 0; i < n_dims; i++ ) { + ASR::dimension_t allocate_dim; + allocate_dim.loc = loc; + allocate_dim.m_start = int32_one; + allocate_dim.m_length = int32_one; + allocate_dims.push_back(al, allocate_dim); + } + break; + } + case static_cast(ASRUtils::IntrinsicArrayFunctions::Transpose): { + size_t n_dims = ASRUtils::extract_n_dims_from_ttype(intrinsic_array_function->m_type); + LCOMPILERS_ASSERT(n_dims == 2); + allocate_dims.reserve(al, n_dims); + // Transpose swaps the dimensions + for (size_t i = 0; i < n_dims; i++) { + ASR::dimension_t allocate_dim; + allocate_dim.loc = loc; + allocate_dim.m_start = int32_one; + ASR::expr_t* size_i = ASRUtils::EXPR(ASR::make_ArraySize_t( + al, loc, intrinsic_array_function->m_args[0], + ASRUtils::EXPR(ASR::make_IntegerConstant_t( + al, loc, n_dims - i, ASRUtils::expr_type(int32_one))), + ASRUtils::expr_type(int32_one), nullptr)); + + allocate_dim.m_length = size_i; + allocate_dims.push_back(al, allocate_dim); + } + break; + } + case static_cast(ASRUtils::IntrinsicArrayFunctions::Cshift): { + size_t n_dims = ASRUtils::extract_n_dims_from_ttype(intrinsic_array_function->m_type); + allocate_dims.reserve(al, n_dims); + for (size_t i = 0; i < n_dims; i++) { + ASR::dimension_t allocate_dim; + allocate_dim.loc = loc; + allocate_dim.m_start = int32_one; + + ASR::expr_t* size_i = ASRUtils::EXPR(ASR::make_ArraySize_t( + al, loc, intrinsic_array_function->m_args[0], + ASRUtils::EXPR(ASR::make_IntegerConstant_t( + al, loc, i + 1, ASRUtils::expr_type(int32_one))), + ASRUtils::expr_type(int32_one), nullptr)); + + allocate_dim.m_length = size_i; + allocate_dims.push_back(al, allocate_dim); + } + break; + } + case static_cast(ASRUtils::IntrinsicArrayFunctions::Spread): { + size_t n_dims = ASRUtils::extract_n_dims_from_ttype(intrinsic_array_function->m_type); + ASR::expr_t* dim_arg = intrinsic_array_function->m_args[1]; + allocate_dims.reserve(al, n_dims); + if (dim_arg && (ASRUtils::expr_value(dim_arg) != nullptr)) { + // Compile time value of `dim` + ASRUtils::ASRBuilder b(al, intrinsic_array_function->base.base.loc); + ASR::IntegerConstant_t* dim_val = ASR::down_cast(dim_arg); + size_t dim_index = dim_val->m_n; + ASR::expr_t* ncopies = intrinsic_array_function->m_args[2]; + int ncopies_inserted = 0; + for (size_t i = 0; i < n_dims; i++) { + ASR::dimension_t allocate_dim; + allocate_dim.loc = loc; + allocate_dim.m_start = int32_one; + if ( i == dim_index - 1 ) { + allocate_dim.m_length = ncopies; + ncopies_inserted = 1; + } else { + allocate_dim.m_length = b.ArraySize(intrinsic_array_function->m_args[0], + b.i32(i + 1 - ncopies_inserted), ASRUtils::expr_type(int32_one)); + } + allocate_dims.push_back(al, allocate_dim); + } + } else { + // Here `dim` is runtime so can't decide where to insert ncopies + // Just copy original dimensions + ASR::dimension_t* dims; + ASRUtils::extract_dimensions_from_ttype(intrinsic_array_function->m_type, dims); + for (size_t i = 0; i < n_dims; i++) { + allocate_dims.push_back(al, dims[i]); + } + } + break; + } + + default: { + LCOMPILERS_ASSERT_MSG(false, "ASR::IntrinsicArrayFunctions::" + + ASRUtils::get_array_intrinsic_name(intrinsic_array_function->m_arr_intrinsic_id) + + " not handled yet in set_allocation_size"); + } + } + break; + } + case ASR::exprType::StructInstanceMember: { + ASR::StructInstanceMember_t* struct_instance_member_t = + ASR::down_cast(value); + size_t n_dims = ASRUtils::extract_n_dims_from_ttype(struct_instance_member_t->m_type); + allocate_dims.reserve(al, n_dims); + if( ASRUtils::is_array(ASRUtils::expr_type(struct_instance_member_t->m_v)) ) { + value = struct_instance_member_t->m_v; + } + ASRUtils::ExprStmtDuplicator expr_duplicator(al); + for( size_t i = 0; i < n_dims; i++ ) { + ASR::dimension_t allocate_dim; + allocate_dim.loc = loc; + allocate_dim.m_start = int32_one; + allocate_dim.m_length = ASRUtils::EXPR(ASR::make_ArraySize_t( + al, loc, expr_duplicator.duplicate_expr( + ASRUtils::get_past_array_physical_cast(value)), + ASRUtils::EXPR(ASR::make_IntegerConstant_t( + al, loc, i + 1, ASRUtils::expr_type(int32_one))), + ASRUtils::expr_type(int32_one), nullptr)); + allocate_dims.push_back(al, allocate_dim); + } + break; + } + case ASR::exprType::ArrayReshape: { + ASR::ArrayReshape_t* array_reshape_t = ASR::down_cast(value); + size_t n_dims = ASRUtils::get_fixed_size_of_array( + ASRUtils::expr_type(array_reshape_t->m_shape)); + allocate_dims.reserve(al, n_dims); + ASRUtils::ASRBuilder b(al, array_reshape_t->base.base.loc); + for( size_t i = 0; i < n_dims; i++ ) { + ASR::dimension_t allocate_dim; + allocate_dim.loc = loc; + allocate_dim.m_start = int32_one; + allocate_dim.m_length = b.ArrayItem_01(array_reshape_t->m_shape, {b.i32(i + 1)}); + allocate_dims.push_back(al, allocate_dim); + } + break; + } + case ASR::exprType::ArrayConstructor: { + allocate_dims.reserve(al, 1); + ASR::dimension_t allocate_dim; + allocate_dim.loc = loc; + allocate_dim.m_start = int32_one; + allocate_dim.m_length = ASRUtils::get_ArrayConstructor_size(al, + ASR::down_cast(value)); + allocate_dims.push_back(al, allocate_dim); + break; + } + case ASR::exprType::ArrayConstant: { + allocate_dims.reserve(al, 1); + ASR::dimension_t allocate_dim; + allocate_dim.loc = loc; + allocate_dim.m_start = int32_one; + allocate_dim.m_length = ASRUtils::get_ArrayConstant_size(al, + ASR::down_cast(value)); + allocate_dims.push_back(al, allocate_dim); + break; + } + case ASR::exprType::Var: { + ASRUtils::ASRBuilder b(al, value->base.loc); + if ( ASRUtils::is_array(ASRUtils::expr_type(value))) { + ASR::dimension_t* m_dims; + size_t n_dims = ASRUtils::extract_dimensions_from_ttype( + ASRUtils::expr_type(value), m_dims); + allocate_dims.reserve(al, n_dims); + for( size_t i = 0; i < n_dims; i++ ) { + ASR::dimension_t allocate_dim; + allocate_dim.loc = loc; + allocate_dim.m_start = int32_one; + allocate_dim.m_length = b.ArrayUBound(value, i+1); + allocate_dims.push_back(al, allocate_dim); + } + } else { + return false; + } + break; + } + default: { + LCOMPILERS_ASSERT_MSG(false, "ASR::exprType::" + std::to_string(value->type) + + " not handled yet in set_allocation_size"); + } + } + return true; + } + + + ASR::stmt_t* create_do_loop(Allocator &al, const Location &loc, std::vector do_loop_variables, ASR::expr_t* left_arr, ASR::expr_t* right_arr, int curr_idx) { + ASRUtils::ASRBuilder b(al, loc); + + if (curr_idx == 1) { + std::vector vars; + for (size_t i = 0; i < do_loop_variables.size(); i++) { + vars.push_back(do_loop_variables[i]); + } + return b.DoLoop(do_loop_variables[curr_idx - 1], LBound(left_arr, curr_idx), UBound(left_arr, curr_idx), { + b.Assignment(b.ArrayItem_01(left_arr, vars), b.ArrayItem_01(right_arr, vars)) + }, nullptr); + } + return b.DoLoop(do_loop_variables[curr_idx - 1], LBound(left_arr, curr_idx), UBound(left_arr, curr_idx), { + create_do_loop(al, loc, do_loop_variables, left_arr, right_arr, curr_idx - 1) + }, nullptr); + } + + void traverse_call_args(Vec& x_m_args_vec, ASR::call_arg_t* x_m_args, + size_t x_n_args, const std::string& name_hint, std::vector is_arg_intent_out = {}, bool is_func_bind_c = false) { + /* For other frontends, we might need to traverse the arguments + in reverse order. */ + for( size_t i = 0; i < x_n_args; i++ ) { + ASR::expr_t* arg_expr = x_m_args[i].m_value; + if ( x_m_args[i].m_value && is_descriptor_array_casted_to_pointer_to_data(x_m_args[i].m_value) && + !is_func_bind_c && !ASRUtils::is_pointer(ASRUtils::expr_type(x_m_args[i].m_value)) && + !ASR::is_a(*ASRUtils::get_past_array_physical_cast(x_m_args[i].m_value)) ) { + ASR::ArrayPhysicalCast_t* array_physical_cast = ASR::down_cast(arg_expr); + ASR::expr_t* arg_expr_past_cast = ASRUtils::get_past_array_physical_cast(arg_expr); + const Location& loc = arg_expr->base.loc; + ASR::expr_t* array_var_temporary = create_temporary_variable_for_array( + al, arg_expr_past_cast, current_scope, name_hint, true); + ASR::call_arg_t array_var_temporary_arg; + array_var_temporary_arg.loc = loc; + if( ASRUtils::is_pointer(ASRUtils::expr_type(array_var_temporary)) ) { + ASR::expr_t* casted_array_var_temporary_arg = ASRUtils::EXPR(ASR::make_ArrayPhysicalCast_t(al, loc, + array_var_temporary, ASR::array_physical_typeType::DescriptorArray, ASR::array_physical_typeType::PointerToDataArray, + array_physical_cast->m_type, nullptr)); + array_var_temporary_arg.m_value = casted_array_var_temporary_arg; + x_m_args_vec.push_back(al, array_var_temporary_arg); + // This should be always true as we pass `true` to `create_temporary_variable_for_array` + ASRUtils::ASRBuilder b(al, arg_expr_past_cast->base.loc); + Vec allocate_dims; allocate_dims.reserve(al, 1); + size_t target_n_dims = ASRUtils::extract_n_dims_from_ttype(ASRUtils::expr_type(array_var_temporary)); + if( !set_allocation_size(al, arg_expr_past_cast, allocate_dims, target_n_dims) ) { + current_body->push_back(al, ASRUtils::STMT(ASR::make_Associate_t( + al, loc, array_var_temporary, arg_expr_past_cast))); + return; + } + LCOMPILERS_ASSERT(target_n_dims == allocate_dims.size()); + Vec alloc_args; alloc_args.reserve(al, 1); + ASR::alloc_arg_t alloc_arg; + alloc_arg.loc = arg_expr_past_cast->base.loc; + alloc_arg.m_a = array_var_temporary; + alloc_arg.m_dims = allocate_dims.p; + alloc_arg.n_dims = allocate_dims.size(); + alloc_arg.m_len_expr = nullptr; + alloc_arg.m_type = nullptr; + alloc_args.push_back(al, alloc_arg); + + Vec dealloc_args; dealloc_args.reserve(al, 1); + dealloc_args.push_back(al, array_var_temporary); + ASR::expr_t* is_contiguous = ASRUtils::EXPR(ASR::make_ArrayIsContiguous_t(al, loc, + arg_expr_past_cast, ASRUtils::expr_type(array_var_temporary), nullptr)); + ASR::expr_t* not_is_contiguous = ASRUtils::EXPR(ASR::make_LogicalNot_t(al, loc, is_contiguous, + ASRUtils::expr_type(is_contiguous), nullptr)); + ASR::dimension_t* array_dims = nullptr; + int array_rank = ASRUtils::extract_dimensions_from_ttype(ASRUtils::expr_type(array_var_temporary), array_dims); + std::vector do_loop_variables; + #define declare(var_name, type, intent) \ + b.Variable(fn_symtab, var_name, type, ASR::intentType::intent) + for (int i = 0; i < array_rank; i++) { + std::string var_name = current_scope->get_unique_name("__lcompilers_i_" + std::to_string(i)); + do_loop_variables.push_back(b.Variable(current_scope, var_name, ASRUtils::expr_type(b.i32(0)), ASR::intentType::Local)); + } + current_body->push_back(al, + b.If(not_is_contiguous, { + ASRUtils::STMT(ASR::make_ExplicitDeallocate_t(al, + array_var_temporary->base.loc, dealloc_args.p, dealloc_args.size())), + ASRUtils::STMT(ASR::make_Allocate_t(al, + array_var_temporary->base.loc, alloc_args.p, alloc_args.size(), + nullptr, nullptr, nullptr)), + create_do_loop(al, loc, do_loop_variables, array_var_temporary, arg_expr_past_cast, array_rank) + }, { + ASRUtils::STMT(ASR::make_Associate_t( + al, loc, array_var_temporary, arg_expr_past_cast)) + }) + ); + if ( is_arg_intent_out.size() > 0 && is_arg_intent_out[i] ) { + body_after_curr_stmt->push_back(al, b.If(not_is_contiguous, { + create_do_loop(al, loc, do_loop_variables, arg_expr_past_cast, array_var_temporary, array_rank) + }, {})); + } + } else { + x_m_args_vec.push_back(al, x_m_args[i]); + } + } else { + x_m_args_vec.push_back(al, x_m_args[i]); + } + } + } + + template + void visit_Call(const T& x, const std::string& name_hint) { + LCOMPILERS_ASSERT(!x.m_dt || !ASRUtils::is_array(ASRUtils::expr_type(x.m_dt))); + Vec x_m_args; x_m_args.reserve(al, x.n_args); + std::vector is_arg_intent_out; + if ( ASR::is_a(*ASRUtils::symbol_get_past_external(x.m_name)) ) { + ASR::Function_t* func = ASR::down_cast(ASRUtils::symbol_get_past_external(x.m_name)); + ASR::FunctionType_t* func_type = ASR::down_cast(func->m_function_signature); + bool is_func_bind_c = func_type->m_abi == ASR::abiType::BindC || func_type->m_deftype == ASR::deftypeType::Interface; + for (size_t i = 0; i < func->n_args; i++ ) { + if ( ASR::is_a(*func->m_args[i]) ) { + ASR::Var_t* var_ = ASR::down_cast(func->m_args[i]); + if ( ASR::is_a(*var_->m_v) ) { + ASR::Variable_t* var = ASR::down_cast(var_->m_v); + is_arg_intent_out.push_back(var->m_intent == ASR::intentType::Out || + var->m_intent == ASR::intentType::InOut); + } else { + is_arg_intent_out.push_back(false); + } + } else { + is_arg_intent_out.push_back(false); + } + } + traverse_call_args(x_m_args, x.m_args, x.n_args, + name_hint + ASRUtils::symbol_name(x.m_name), is_arg_intent_out, is_func_bind_c); + } else { + traverse_call_args(x_m_args, x.m_args, x.n_args, + name_hint + ASRUtils::symbol_name(x.m_name)); + } + + T& xx = const_cast(x); + xx.m_args = x_m_args.p; + xx.n_args = x_m_args.size(); + } + + void visit_SubroutineCall(const ASR::SubroutineCall_t& x) { + visit_Call(x, "_subroutine_call_"); + ASR::CallReplacerOnExpressionsVisitor::visit_SubroutineCall(x); + } + + void visit_FunctionCall(const ASR::FunctionCall_t& x) { + visit_Call(x, "_function_call_"); + ASR::CallReplacerOnExpressionsVisitor::visit_FunctionCall(x); + } + +}; + +void pass_replace_array_passed_in_function_call(Allocator &al, ASR::TranslationUnit_t &unit, + const LCompilers::PassOptions& /*pass_options*/) { + CallVisitor v(al); + v.visit_TranslationUnit(unit); + PassUtils::UpdateDependenciesVisitor x(al); + x.visit_TranslationUnit(unit); +} + + +} // namespace LCompilers diff --git a/src/libasr/pass/array_struct_temporary.cpp b/src/libasr/pass/array_struct_temporary.cpp new file mode 100644 index 0000000000..541e87520d --- /dev/null +++ b/src/libasr/pass/array_struct_temporary.cpp @@ -0,0 +1,2651 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace LCompilers { + +bool is_vectorise_able(ASR::expr_t* x) { + switch( x->type ) { + case ASR::exprType::FunctionCall: { + return ASRUtils::is_elemental(ASR::down_cast(x)->m_name); + } + case ASR::exprType::IntrinsicElementalFunction: { + return true; + } + case ASR::exprType::IntegerBinOp: + case ASR::exprType::RealBinOp: + case ASR::exprType::ComplexBinOp: + case ASR::exprType::LogicalBinOp: + case ASR::exprType::UnsignedIntegerBinOp: + case ASR::exprType::IntegerCompare: + case ASR::exprType::RealCompare: + case ASR::exprType::ComplexCompare: + case ASR::exprType::LogicalCompare: + case ASR::exprType::UnsignedIntegerCompare: + case ASR::exprType::StringCompare: + case ASR::exprType::IntegerUnaryMinus: + case ASR::exprType::RealUnaryMinus: + case ASR::exprType::ComplexUnaryMinus: + case ASR::exprType::Var: { + return true; + } + default: { + return false; + } + } +} + +enum targetType { + GeneratedTarget, + OriginalTarget, + GeneratedTargetPointerForArraySection +}; + +typedef std::map> ExprsWithTargetType; + +const std::vector& exprs_with_no_type = { +}; + +static inline ASR::asr_t* make_Assignment_t_util( + Allocator &al, const Location &a_loc, ASR::expr_t* a_target, + ASR::expr_t* a_value, ASR::stmt_t* a_overloaded, + ExprsWithTargetType& exprs_with_target) { + ASRUtils::ExprStmtDuplicator expr_duplicator(al); + a_target = expr_duplicator.duplicate_expr(a_target); + a_value = expr_duplicator.duplicate_expr(a_value); + + exprs_with_target[a_value] = std::make_pair(a_target, targetType::GeneratedTarget); + return ASR::make_Assignment_t(al, a_loc, a_target, a_value, a_overloaded); +} + +/* +This pass collector that the BinOp only Var nodes and nothing else. +*/ +class ArrayVarCollector: public ASR::BaseWalkVisitor { + private: + + Allocator& al; + Vec& vars; + + public: + + ArrayVarCollector(Allocator& al_, Vec& vars_): al(al_), vars(vars_) {} + + void visit_Var(const ASR::Var_t& x) { + if( ASRUtils::is_array(ASRUtils::symbol_type(x.m_v)) ) { + vars.push_back(al, const_cast(&(x.base))); + } + } + + void visit_StructInstanceMember(const ASR::StructInstanceMember_t& x) { + if( ASRUtils::is_array(ASRUtils::symbol_type(x.m_m)) ) { + vars.push_back(al, const_cast(&(x.base))); + } + } + + void visit_ArrayBroadcast(const ASR::ArrayBroadcast_t& /*x*/) { + + } + + void visit_ArraySize(const ASR::ArraySize_t& /*x*/) { + + } + +}; + +ASR::expr_t* create_temporary_variable_for_scalar(Allocator& al, + ASR::expr_t* value, SymbolTable* scope, std::string name_hint) { + ASR::ttype_t* value_type = ASRUtils::expr_type(value); + LCOMPILERS_ASSERT(!ASRUtils::is_array(value_type)); + + ASR::ttype_t* var_type = ASRUtils::duplicate_type(al, ASRUtils::extract_type(value_type)); + std::string var_name = scope->get_unique_name("__libasr_created_" + name_hint); + ASR::symbol_t* temporary_variable = ASR::down_cast(ASRUtils::make_Variable_t_util( + al, value->base.loc, scope, s2c(al, var_name), nullptr, 0, ASR::intentType::Local, + nullptr, nullptr, ASR::storage_typeType::Default, var_type, nullptr, ASR::abiType::Source, + ASR::accessType::Public, ASR::presenceType::Required, false)); + scope->add_symbol(var_name, temporary_variable); + + return ASRUtils::EXPR(ASR::make_Var_t(al, temporary_variable->base.loc, temporary_variable)); +} + +ASR::expr_t* create_temporary_variable_for_array(Allocator& al, + ASR::expr_t* value, SymbolTable* scope, std::string name_hint, + bool is_pointer_required=false) { + ASR::ttype_t* value_type = ASRUtils::expr_type(value); + LCOMPILERS_ASSERT(ASRUtils::is_array(value_type)); + + /* Figure out the type of the temporary array variable */ + ASR::dimension_t* value_m_dims = nullptr; + size_t value_n_dims = ASRUtils::extract_dimensions_from_ttype(value_type, value_m_dims); + + if (ASR::is_a(*value)) { + ASR::IntegerCompare_t* integer_compare = ASR::down_cast(value); + ASR::ttype_t* logical_type = ASRUtils::TYPE(ASR::make_Logical_t(al, value->base.loc, 4)); + + ASR::ttype_t* left_type = ASRUtils::expr_type(integer_compare->m_left); + ASR::ttype_t* right_type = ASRUtils::expr_type(integer_compare->m_right); + + if (ASR::is_a(*left_type)) { + ASR::Array_t* left_array_type = ASR::down_cast(left_type); + ASR::dimension_t* left_m_dims = nullptr; + size_t left_n_dims = ASRUtils::extract_dimensions_from_ttype(left_type, left_m_dims); + value_m_dims = left_m_dims; + value_n_dims = left_n_dims; + + if (left_array_type->m_physical_type == ASR::array_physical_typeType::FixedSizeArray) { + ASR::ttype_t* logical_array_type = ASRUtils::TYPE(ASR::make_Array_t(al, value->base.loc, logical_type, left_m_dims, left_n_dims, ASR::array_physical_typeType::FixedSizeArray)); + value_type = logical_array_type; + } else { + ASR::ttype_t* logical_array_type = ASRUtils::TYPE(ASR::make_Array_t(al, value->base.loc, logical_type, left_m_dims, left_n_dims, ASR::array_physical_typeType::PointerToDataArray)); + value_type = logical_array_type; + } + } else if (ASR::is_a(*right_type)) { + ASR::Array_t* right_array_type = ASR::down_cast(right_type); + ASR::dimension_t* right_m_dims = nullptr; + size_t right_n_dims = ASRUtils::extract_dimensions_from_ttype(right_type, right_m_dims); + value_m_dims = right_m_dims; + value_n_dims = right_n_dims; + + if (right_array_type->m_physical_type == ASR::array_physical_typeType::FixedSizeArray) { + ASR::ttype_t* logical_array_type = ASRUtils::TYPE(ASR::make_Array_t(al, value->base.loc, logical_type, right_m_dims, right_n_dims, ASR::array_physical_typeType::FixedSizeArray)); + value_type = logical_array_type; + } else { + ASR::ttype_t* logical_array_type = ASRUtils::TYPE(ASR::make_Array_t(al, value->base.loc, logical_type, right_m_dims, right_n_dims, ASR::array_physical_typeType::PointerToDataArray)); + value_type = logical_array_type; + } + } + } + // dimensions can be different for an ArrayConstructor e.g. [1, a], where `a` is an + // ArrayConstructor like [5, 2, 1] + if (ASR::is_a(*value) && + !PassUtils::is_args_contains_allocatable(value)) { + ASR::ArrayConstructor_t* arr_constructor = ASR::down_cast(value); + value_m_dims->m_length = ASRUtils::get_ArrayConstructor_size(al, arr_constructor); + } + bool is_fixed_sized_array = ASRUtils::is_fixed_size_array(value_type); + bool is_size_only_dependent_on_arguments = ASRUtils::is_dimension_dependent_only_on_arguments( + value_m_dims, value_n_dims); + bool is_allocatable = ASRUtils::is_allocatable(value_type); + ASR::ttype_t* var_type = nullptr; + if( (is_fixed_sized_array || is_size_only_dependent_on_arguments || is_allocatable) && + !is_pointer_required ) { + var_type = value_type; + } else { + var_type = ASRUtils::create_array_type_with_empty_dims(al, value_n_dims, value_type); + if( ASR::is_a(*value) && is_pointer_required && + !ASRUtils::is_array_indexed_with_array_indices(ASR::down_cast(value))) { + if( ASRUtils::is_simd_array(value) ) { + var_type = ASRUtils::expr_type(value); + } else { + var_type = ASRUtils::TYPE(ASR::make_Pointer_t(al, var_type->base.loc, var_type)); + } + } else { + var_type = ASRUtils::TYPE(ASRUtils::make_Allocatable_t_util(al, var_type->base.loc, var_type)); + } + } + + std::string var_name = scope->get_unique_name("__libasr_created_" + name_hint); + ASR::symbol_t* temporary_variable = ASR::down_cast(ASRUtils::make_Variable_t_util( + al, value->base.loc, scope, s2c(al, var_name), nullptr, 0, ASR::intentType::Local, + nullptr, nullptr, ASR::storage_typeType::Default, var_type, nullptr, ASR::abiType::Source, + ASR::accessType::Public, ASR::presenceType::Required, false)); + scope->add_symbol(var_name, temporary_variable); + + return ASRUtils::EXPR(ASR::make_Var_t(al, temporary_variable->base.loc, temporary_variable)); +} + +ASR::expr_t* create_temporary_variable_for_array(Allocator& al, const Location& loc, + SymbolTable* scope, std::string name_hint, ASR::ttype_t* value_type) { + + std::string var_name = scope->get_unique_name("__libasr_created_" + name_hint); + ASR::symbol_t* temporary_variable = ASR::down_cast(ASRUtils::make_Variable_t_util( + al, loc, scope, s2c(al, var_name), nullptr, 0, ASR::intentType::Local, + nullptr, nullptr, ASR::storage_typeType::Default, value_type, nullptr, ASR::abiType::Source, + ASR::accessType::Public, ASR::presenceType::Required, false)); + scope->add_symbol(var_name, temporary_variable); + + return ASRUtils::EXPR(ASR::make_Var_t(al, temporary_variable->base.loc, temporary_variable)); +} + +ASR::expr_t* create_temporary_variable_for_struct(Allocator& al, + ASR::expr_t* value, SymbolTable* scope, std::string name_hint) { + ASR::ttype_t* value_type = ASRUtils::expr_type(value); + LCOMPILERS_ASSERT(ASRUtils::is_struct(*value_type)); + + std::string var_name = scope->get_unique_name("__libasr_created_" + name_hint); + ASR::symbol_t* temporary_variable = ASR::down_cast(ASRUtils::make_Variable_t_util( + al, value->base.loc, scope, s2c(al, var_name), nullptr, 0, ASR::intentType::Local, + nullptr, nullptr, ASR::storage_typeType::Default, value_type, nullptr, ASR::abiType::Source, + ASR::accessType::Public, ASR::presenceType::Required, false)); + scope->add_symbol(var_name, temporary_variable); + + return ASRUtils::EXPR(ASR::make_Var_t(al, temporary_variable->base.loc, temporary_variable)); +} + +template +ASR::expr_t* get_first_array_function_args(T* func) { + int64_t first_array_arg_idx = -1; + ASR::expr_t* first_array_arg = nullptr; + for (int64_t i = 0; i < (int64_t)func->n_args; i++) { + ASR::ttype_t* func_arg_type; + if constexpr (std::is_same_v) { + func_arg_type = ASRUtils::expr_type(func->m_args[i].m_value); + } else { + func_arg_type = ASRUtils::expr_type(func->m_args[i]); + } + if (ASRUtils::is_array(func_arg_type)) { + first_array_arg_idx = i; + break; + } + } + LCOMPILERS_ASSERT(first_array_arg_idx != -1) + if constexpr (std::is_same_v) { + first_array_arg = func->m_args[first_array_arg_idx].m_value; + } else { + first_array_arg = func->m_args[first_array_arg_idx]; + } + return first_array_arg; +} + +/* + sets allocation size of an elemental function, which can be + either an intrinsic elemental function or a user-defined +*/ +template +void set_allocation_size_elemental_function( + Allocator& al, const Location& loc, + T* elemental_function, + Vec& allocate_dims +) { + ASR::expr_t* int32_one = ASRUtils::EXPR(ASR::make_IntegerConstant_t( + al, loc, 1, ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)))); + size_t n_dims = ASRUtils::extract_n_dims_from_ttype(elemental_function->m_type); + allocate_dims.reserve(al, n_dims); + ASR::expr_t* first_array_arg = get_first_array_function_args(elemental_function); + for( size_t i = 0; i < n_dims; i++ ) { + ASR::dimension_t allocate_dim; + allocate_dim.loc = loc; + allocate_dim.m_start = int32_one; + ASR::expr_t* size_i_1 = ASRUtils::EXPR(ASR::make_ArraySize_t( + al, loc, ASRUtils::get_past_array_physical_cast(first_array_arg), + ASRUtils::EXPR(ASR::make_IntegerConstant_t( + al, loc, i + 1, ASRUtils::expr_type(int32_one))), + ASRUtils::expr_type(int32_one), nullptr)); + allocate_dim.m_length = size_i_1; + allocate_dims.push_back(al, allocate_dim); + } +} + +bool set_allocation_size( + Allocator& al, ASR::expr_t* value, + Vec& allocate_dims, + size_t target_n_dims +) { + if ( !ASRUtils::is_array(ASRUtils::expr_type(value)) ) { + return false; + } + const Location& loc = value->base.loc; + ASR::expr_t* int32_one = ASRUtils::EXPR(ASR::make_IntegerConstant_t( + al, loc, 1, ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)))); + if( ASRUtils::is_fixed_size_array(ASRUtils::expr_type(value)) ) { + ASR::dimension_t* m_dims = nullptr; + size_t n_dims = ASRUtils::extract_dimensions_from_ttype( + ASRUtils::expr_type(value), m_dims); + allocate_dims.reserve(al, n_dims); + for( size_t i = 0; i < n_dims; i++ ) { + ASR::dimension_t allocate_dim; + allocate_dim.loc = value->base.loc; + allocate_dim.m_start = int32_one; + allocate_dim.m_length = m_dims[i].m_length; + allocate_dims.push_back(al, allocate_dim); + } + return true; + } + switch( value->type ) { + case ASR::exprType::FunctionCall: { + ASR::FunctionCall_t* function_call = ASR::down_cast(value); + ASR::ttype_t* type = function_call->m_type; + if( ASRUtils::is_allocatable(type) ) { + return false; + } + if (PassUtils::is_elemental(function_call->m_name)) { + set_allocation_size_elemental_function(al, loc, function_call, allocate_dims); + break; + } + ASRUtils::ExprStmtDuplicator duplicator(al); + ASR::dimension_t* dims = nullptr; + size_t n_dims = ASRUtils::extract_dimensions_from_ttype(type, dims); + allocate_dims.reserve(al, n_dims); + for( size_t i = 0; i < n_dims; i++ ) { + ASR::dimension_t dim = dims[i]; + ASR::dimension_t dim_copy; + dim_copy.loc = dim.loc; + dim_copy.m_start = !dim.m_start ? nullptr : duplicator.duplicate_expr(dim.m_start); + dim_copy.m_length = !dim.m_length ? nullptr : duplicator.duplicate_expr(dim.m_length); + LCOMPILERS_ASSERT(dim_copy.m_start); + LCOMPILERS_ASSERT(dim_copy.m_length); + allocate_dims.push_back(al, dim_copy); + } + break ; + } + case ASR::exprType::IntegerBinOp: + case ASR::exprType::RealBinOp: + case ASR::exprType::ComplexBinOp: + case ASR::exprType::LogicalBinOp: + case ASR::exprType::UnsignedIntegerBinOp: + case ASR::exprType::IntegerCompare: + case ASR::exprType::RealCompare: + case ASR::exprType::ComplexCompare: + case ASR::exprType::LogicalCompare: + case ASR::exprType::UnsignedIntegerCompare: + case ASR::exprType::StringCompare: + case ASR::exprType::IntegerUnaryMinus: + case ASR::exprType::RealUnaryMinus: + case ASR::exprType::ComplexUnaryMinus: { + /* + Collect all the variables from these expressions, + then take the size of one of the arrays having + maximum dimensions for now. For now LFortran will + assume that broadcasting is doable for arrays with lesser + dimensions and the array having maximum dimensions + has compatible size of each dimension with other arrays. + */ + + Vec array_vars; array_vars.reserve(al, 1); + ArrayVarCollector array_var_collector(al, array_vars); + array_var_collector.visit_expr(*value); + Vec arrays_with_maximum_rank; + arrays_with_maximum_rank.reserve(al, 1); + LCOMPILERS_ASSERT(target_n_dims > 0); + for( size_t i = 0; i < array_vars.size(); i++ ) { + if( (size_t) ASRUtils::extract_n_dims_from_ttype( + ASRUtils::expr_type(array_vars[i])) == target_n_dims ) { + arrays_with_maximum_rank.push_back(al, array_vars[i]); + } + } + + LCOMPILERS_ASSERT(arrays_with_maximum_rank.size() > 0); + ASR::expr_t* selected_array = arrays_with_maximum_rank[0]; + allocate_dims.reserve(al, target_n_dims); + for( size_t i = 0; i < target_n_dims; i++ ) { + ASR::dimension_t allocate_dim; + Location loc; loc.first = 1, loc.last = 1; + allocate_dim.loc = loc; + // Assume 1 for Fortran. + allocate_dim.m_start = ASRUtils::EXPR(ASR::make_IntegerConstant_t( + al, loc, 1, ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)))); + ASR::expr_t* dim = ASRUtils::EXPR(ASR::make_IntegerConstant_t( + al, loc, i + 1, ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)))); + allocate_dim.m_length = ASRUtils::EXPR(ASR::make_ArraySize_t( + al, loc, ASRUtils::get_past_array_physical_cast(selected_array), + dim, ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)), nullptr)); + allocate_dims.push_back(al, allocate_dim); + } + break; + } + case ASR::exprType::LogicalNot: { + ASR::LogicalNot_t* logical_not = ASR::down_cast(value); + if ( ASRUtils::is_array(ASRUtils::expr_type(logical_not->m_arg)) ) { + size_t rank = ASRUtils::extract_n_dims_from_ttype( + ASRUtils::expr_type(logical_not->m_arg)); + ASR::expr_t* selected_array = logical_not->m_arg; + allocate_dims.reserve(al, rank); + for( size_t i = 0; i < rank; i++ ) { + ASR::dimension_t allocate_dim; + allocate_dim.loc = loc; + // Assume 1 for Fortran. + allocate_dim.m_start = ASRUtils::EXPR(ASR::make_IntegerConstant_t( + al, loc, 1, ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)))); + ASR::expr_t* dim = ASRUtils::EXPR(ASR::make_IntegerConstant_t( + al, loc, i + 1, ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)))); + allocate_dim.m_length = ASRUtils::EXPR(ASR::make_ArraySize_t( + al, loc, ASRUtils::get_past_array_physical_cast(selected_array), + dim, ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)), nullptr)); + allocate_dims.push_back(al, allocate_dim); + } + } + break; + } + case ASR::exprType::Cast: { + ASR::Cast_t* cast = ASR::down_cast(value); + if ( ASRUtils::is_array(ASRUtils::expr_type(cast->m_arg)) ) { + size_t rank = ASRUtils::extract_n_dims_from_ttype( + ASRUtils::expr_type(cast->m_arg)); + ASR::expr_t* selected_array = cast->m_arg; + allocate_dims.reserve(al, rank); + for( size_t i = 0; i < rank; i++ ) { + ASR::dimension_t allocate_dim; + allocate_dim.loc = loc; + // Assume 1 for Fortran. + allocate_dim.m_start = ASRUtils::EXPR(ASR::make_IntegerConstant_t( + al, loc, 1, ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)))); + ASR::expr_t* dim = ASRUtils::EXPR(ASR::make_IntegerConstant_t( + al, loc, i + 1, ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)))); + allocate_dim.m_length = ASRUtils::EXPR(ASR::make_ArraySize_t( + al, loc, ASRUtils::get_past_array_physical_cast(selected_array), + dim, ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)), nullptr)); + allocate_dims.push_back(al, allocate_dim); + } + } + break; + } + case ASR::exprType::ArraySection: { + ASR::ArraySection_t* array_section_t = ASR::down_cast(value); + allocate_dims.reserve(al, array_section_t->n_args); + for( size_t i = 0; i < array_section_t->n_args; i++ ) { + ASR::expr_t* start = array_section_t->m_args[i].m_left; + ASR::expr_t* end = array_section_t->m_args[i].m_right; + ASR::expr_t* step = array_section_t->m_args[i].m_step; + ASR::dimension_t allocate_dim; + allocate_dim.loc = loc; + allocate_dim.m_start = int32_one; + if( start == nullptr && step == nullptr && end != nullptr ) { + if( ASRUtils::is_array(ASRUtils::expr_type(end)) ) { + allocate_dim.m_length = ASRUtils::EXPR(ASRUtils::make_ArraySize_t_util( + al, loc, end, nullptr, ASRUtils::expr_type(int32_one), nullptr, false)); + allocate_dims.push_back(al, allocate_dim); + } + } else { + ASR::expr_t* end_minus_start = ASRUtils::EXPR(ASR::make_IntegerBinOp_t(al, loc, + end, ASR::binopType::Sub, start, ASRUtils::expr_type(end), nullptr)); + ASR::expr_t* by_step = ASRUtils::EXPR(ASR::make_IntegerBinOp_t(al, loc, + end_minus_start, ASR::binopType::Div, step, ASRUtils::expr_type(end_minus_start), + nullptr)); + ASR::expr_t* length = ASRUtils::EXPR(ASR::make_IntegerBinOp_t(al, loc, + by_step, ASR::binopType::Add, int32_one, ASRUtils::expr_type(by_step), nullptr)); + allocate_dim.m_length = length; + allocate_dims.push_back(al, allocate_dim); + } + } + break; + } + case ASR::exprType::ArrayItem: { + ASR::ArrayItem_t* array_item_t = ASR::down_cast(value); + allocate_dims.reserve(al, array_item_t->n_args); + for( size_t i = 0; i < array_item_t->n_args; i++ ) { + ASR::expr_t* start = array_item_t->m_args[i].m_left; + ASR::expr_t* end = array_item_t->m_args[i].m_right; + ASR::expr_t* step = array_item_t->m_args[i].m_step; + if( !(start == nullptr && step == nullptr && end != nullptr) ) { + continue ; + } + if( !ASRUtils::is_array(ASRUtils::expr_type(end)) ) { + continue ; + } + ASR::dimension_t allocate_dim; + allocate_dim.loc = loc; + allocate_dim.m_start = int32_one; + allocate_dim.m_length = ASRUtils::EXPR(ASRUtils::make_ArraySize_t_util( + al, loc, end, nullptr, ASRUtils::expr_type(int32_one), nullptr, false)); + allocate_dims.push_back(al, allocate_dim); + } + break; + } + case ASR::exprType::IntrinsicElementalFunction: { + ASR::IntrinsicElementalFunction_t* intrinsic_elemental_function = + ASR::down_cast(value); + set_allocation_size_elemental_function(al, loc, intrinsic_elemental_function, + allocate_dims); + break; + } + case ASR::exprType::IntrinsicArrayFunction: { + ASR::IntrinsicArrayFunction_t* intrinsic_array_function = + ASR::down_cast(value); + switch (intrinsic_array_function->m_arr_intrinsic_id) { + case static_cast(ASRUtils::IntrinsicArrayFunctions::All): + case static_cast(ASRUtils::IntrinsicArrayFunctions::Any): + case static_cast(ASRUtils::IntrinsicArrayFunctions::Count): + case static_cast(ASRUtils::IntrinsicArrayFunctions::Parity): + case static_cast(ASRUtils::IntrinsicArrayFunctions::Sum): + case static_cast(ASRUtils::IntrinsicArrayFunctions::MaxVal): + case static_cast(ASRUtils::IntrinsicArrayFunctions::MinVal): { + size_t n_dims = ASRUtils::extract_n_dims_from_ttype( + intrinsic_array_function->m_type); + allocate_dims.reserve(al, n_dims); + for( size_t i = 0; i < n_dims; i++ ) { + ASR::dimension_t allocate_dim; + allocate_dim.loc = loc; + allocate_dim.m_start = int32_one; + ASR::expr_t* size_i_1 = ASRUtils::EXPR(ASR::make_ArraySize_t( + al, loc, ASRUtils::get_past_array_physical_cast(intrinsic_array_function->m_args[0]), + ASRUtils::EXPR(ASR::make_IntegerConstant_t( + al, loc, i + 1, ASRUtils::expr_type(int32_one))), + ASRUtils::expr_type(int32_one), nullptr)); + ASR::expr_t* size_i_2 = ASRUtils::EXPR(ASR::make_ArraySize_t( + al, loc, ASRUtils::get_past_array_physical_cast(intrinsic_array_function->m_args[0]), + ASRUtils::EXPR(ASR::make_IntegerConstant_t( + al, loc, i + 2, ASRUtils::expr_type(int32_one))), + ASRUtils::expr_type(int32_one), nullptr)); + Vec merge_i_args; merge_i_args.reserve(al, 3); + merge_i_args.push_back(al, size_i_1); merge_i_args.push_back(al, size_i_2); + merge_i_args.push_back(al, ASRUtils::EXPR(ASR::make_IntegerCompare_t(al, loc, + ASRUtils::EXPR(ASR::make_IntegerConstant_t( + al, loc, i + 1, ASRUtils::expr_type(int32_one))), ASR::cmpopType::Lt, + intrinsic_array_function->m_args[1], + ASRUtils::TYPE(ASR::make_Logical_t(al, loc, 4)), nullptr))); + ASR::expr_t* merge_i = ASRUtils::EXPR(ASRUtils::make_IntrinsicElementalFunction_t_util( + al, loc, static_cast(ASRUtils::IntrinsicElementalFunctions::Merge), + merge_i_args.p, merge_i_args.size(), 0, ASRUtils::expr_type(int32_one), nullptr)); + allocate_dim.m_length = merge_i; + allocate_dims.push_back(al, allocate_dim); + } + break; + } + case static_cast(ASRUtils::IntrinsicArrayFunctions::Pack): { + size_t n_dims = ASRUtils::extract_n_dims_from_ttype( + intrinsic_array_function->m_type); + allocate_dims.reserve(al, n_dims); + for ( size_t i = 0; i < n_dims; i++ ) { + ASR::dimension_t allocate_dim; + allocate_dim.loc = loc; + allocate_dim.m_start = int32_one; + ASR::expr_t* size_i_1 = nullptr; + if (intrinsic_array_function->n_args == 3) { + size_i_1 = ASRUtils::EXPR(ASR::make_ArraySize_t( + al, loc, ASRUtils::get_past_array_physical_cast(intrinsic_array_function->m_args[2]), + ASRUtils::EXPR(ASR::make_IntegerConstant_t( + al, loc, i + 1, ASRUtils::expr_type(int32_one))), + ASRUtils::expr_type(int32_one), nullptr)); + } else { + Vec count_i_args; count_i_args.reserve(al, 1); + count_i_args.push_back(al, intrinsic_array_function->m_args[1]); + size_i_1 = ASRUtils::EXPR(ASRUtils::make_IntrinsicArrayFunction_t_util( + al, loc, static_cast(ASRUtils::IntrinsicArrayFunctions::Count), + count_i_args.p, count_i_args.size(), 0, ASRUtils::expr_type(int32_one), nullptr)); + } + allocate_dim.m_length = size_i_1; + allocate_dims.push_back(al, allocate_dim); + } + break; + } + case static_cast(ASRUtils::IntrinsicArrayFunctions::Shape): { + size_t n_dims = ASRUtils::extract_n_dims_from_ttype( + intrinsic_array_function->m_type); + allocate_dims.reserve(al, n_dims); + for( size_t i = 0; i < n_dims; i++ ) { + ASR::dimension_t allocate_dim; + allocate_dim.loc = loc; + allocate_dim.m_start = int32_one; + allocate_dim.m_length = int32_one; + allocate_dims.push_back(al, allocate_dim); + } + break; + } + case static_cast(ASRUtils::IntrinsicArrayFunctions::Transpose): { + size_t n_dims = ASRUtils::extract_n_dims_from_ttype(intrinsic_array_function->m_type); + LCOMPILERS_ASSERT(n_dims == 2); + allocate_dims.reserve(al, n_dims); + // Transpose swaps the dimensions + for (size_t i = 0; i < n_dims; i++) { + ASR::dimension_t allocate_dim; + allocate_dim.loc = loc; + allocate_dim.m_start = int32_one; + ASR::expr_t* size_i = ASRUtils::EXPR(ASR::make_ArraySize_t( + al, loc, intrinsic_array_function->m_args[0], + ASRUtils::EXPR(ASR::make_IntegerConstant_t( + al, loc, n_dims - i, ASRUtils::expr_type(int32_one))), + ASRUtils::expr_type(int32_one), nullptr)); + + allocate_dim.m_length = size_i; + allocate_dims.push_back(al, allocate_dim); + } + break; + } + case static_cast(ASRUtils::IntrinsicArrayFunctions::Cshift): { + size_t n_dims = ASRUtils::extract_n_dims_from_ttype(intrinsic_array_function->m_type); + allocate_dims.reserve(al, n_dims); + for (size_t i = 0; i < n_dims; i++) { + ASR::dimension_t allocate_dim; + allocate_dim.loc = loc; + allocate_dim.m_start = int32_one; + + ASR::expr_t* size_i = ASRUtils::EXPR(ASR::make_ArraySize_t( + al, loc, intrinsic_array_function->m_args[0], + ASRUtils::EXPR(ASR::make_IntegerConstant_t( + al, loc, i + 1, ASRUtils::expr_type(int32_one))), + ASRUtils::expr_type(int32_one), nullptr)); + + allocate_dim.m_length = size_i; + allocate_dims.push_back(al, allocate_dim); + } + break; + } + case static_cast(ASRUtils::IntrinsicArrayFunctions::Spread): { + size_t n_dims = ASRUtils::extract_n_dims_from_ttype(intrinsic_array_function->m_type); + ASR::expr_t* dim_arg = intrinsic_array_function->m_args[1]; + allocate_dims.reserve(al, n_dims); + if (dim_arg && (ASRUtils::expr_value(dim_arg) != nullptr)) { + // Compile time value of `dim` + ASRUtils::ASRBuilder b(al, intrinsic_array_function->base.base.loc); + ASR::IntegerConstant_t* dim_val = ASR::down_cast(dim_arg); + size_t dim_index = dim_val->m_n; + ASR::expr_t* ncopies = intrinsic_array_function->m_args[2]; + int ncopies_inserted = 0; + for (size_t i = 0; i < n_dims; i++) { + ASR::dimension_t allocate_dim; + allocate_dim.loc = loc; + allocate_dim.m_start = int32_one; + if ( i == dim_index - 1 ) { + allocate_dim.m_length = ncopies; + ncopies_inserted = 1; + } else { + allocate_dim.m_length = b.ArraySize(intrinsic_array_function->m_args[0], + b.i32(i + 1 - ncopies_inserted), ASRUtils::expr_type(int32_one)); + } + allocate_dims.push_back(al, allocate_dim); + } + } else { + // Here `dim` is runtime so can't decide where to insert ncopies + // Just copy original dimensions + ASR::dimension_t* dims; + ASRUtils::extract_dimensions_from_ttype(intrinsic_array_function->m_type, dims); + for (size_t i = 0; i < n_dims; i++) { + allocate_dims.push_back(al, dims[i]); + } + } + break; + } + + default: { + LCOMPILERS_ASSERT_MSG(false, "ASR::IntrinsicArrayFunctions::" + + ASRUtils::get_array_intrinsic_name(intrinsic_array_function->m_arr_intrinsic_id) + + " not handled yet in set_allocation_size"); + } + } + break; + } + case ASR::exprType::StructInstanceMember: { + ASR::StructInstanceMember_t* struct_instance_member_t = + ASR::down_cast(value); + size_t n_dims = ASRUtils::extract_n_dims_from_ttype(struct_instance_member_t->m_type); + allocate_dims.reserve(al, n_dims); + if( ASRUtils::is_array(ASRUtils::expr_type(struct_instance_member_t->m_v)) ) { + value = struct_instance_member_t->m_v; + } + ASRUtils::ExprStmtDuplicator expr_duplicator(al); + for( size_t i = 0; i < n_dims; i++ ) { + ASR::dimension_t allocate_dim; + allocate_dim.loc = loc; + allocate_dim.m_start = int32_one; + allocate_dim.m_length = ASRUtils::EXPR(ASR::make_ArraySize_t( + al, loc, expr_duplicator.duplicate_expr( + ASRUtils::get_past_array_physical_cast(value)), + ASRUtils::EXPR(ASR::make_IntegerConstant_t( + al, loc, i + 1, ASRUtils::expr_type(int32_one))), + ASRUtils::expr_type(int32_one), nullptr)); + allocate_dims.push_back(al, allocate_dim); + } + break; + } + case ASR::exprType::ArrayReshape: { + ASR::ArrayReshape_t* array_reshape_t = ASR::down_cast(value); + size_t n_dims = ASRUtils::get_fixed_size_of_array( + ASRUtils::expr_type(array_reshape_t->m_shape)); + allocate_dims.reserve(al, n_dims); + ASRUtils::ASRBuilder b(al, array_reshape_t->base.base.loc); + for( size_t i = 0; i < n_dims; i++ ) { + ASR::dimension_t allocate_dim; + allocate_dim.loc = loc; + allocate_dim.m_start = int32_one; + allocate_dim.m_length = b.ArrayItem_01(array_reshape_t->m_shape, {b.i32(i + 1)}); + allocate_dims.push_back(al, allocate_dim); + } + break; + } + case ASR::exprType::ArrayConstructor: { + allocate_dims.reserve(al, 1); + ASR::dimension_t allocate_dim; + allocate_dim.loc = loc; + allocate_dim.m_start = int32_one; + allocate_dim.m_length = ASRUtils::get_ArrayConstructor_size(al, + ASR::down_cast(value)); + allocate_dims.push_back(al, allocate_dim); + break; + } + case ASR::exprType::ArrayConstant: { + allocate_dims.reserve(al, 1); + ASR::dimension_t allocate_dim; + allocate_dim.loc = loc; + allocate_dim.m_start = int32_one; + allocate_dim.m_length = ASRUtils::get_ArrayConstant_size(al, + ASR::down_cast(value)); + allocate_dims.push_back(al, allocate_dim); + break; + } + default: { + LCOMPILERS_ASSERT_MSG(false, "ASR::exprType::" + std::to_string(value->type) + + " not handled yet in set_allocation_size"); + } + } + return true; +} + +void insert_allocate_stmt_for_array(Allocator& al, ASR::expr_t* temporary_var, + ASR::expr_t* value, Vec* current_body) { + if( !ASRUtils::is_allocatable(temporary_var) ) { + return ; + } + Vec allocate_dims; + size_t target_n_dims = ASRUtils::extract_n_dims_from_ttype(ASRUtils::expr_type(temporary_var)); + if( !set_allocation_size(al, value, allocate_dims, target_n_dims) ) { + return ; + } + LCOMPILERS_ASSERT(target_n_dims == allocate_dims.size()); + Vec alloc_args; alloc_args.reserve(al, 1); + ASR::alloc_arg_t alloc_arg; + alloc_arg.loc = value->base.loc; + alloc_arg.m_a = temporary_var; + alloc_arg.m_dims = allocate_dims.p; + alloc_arg.n_dims = allocate_dims.size(); + alloc_arg.m_len_expr = nullptr; + alloc_arg.m_type = nullptr; + alloc_args.push_back(al, alloc_arg); + + Vec dealloc_args; dealloc_args.reserve(al, 1); + dealloc_args.push_back(al, temporary_var); + current_body->push_back(al, ASRUtils::STMT(ASR::make_ExplicitDeallocate_t(al, + temporary_var->base.loc, dealloc_args.p, dealloc_args.size()))); + current_body->push_back(al, ASRUtils::STMT(ASR::make_Allocate_t(al, + temporary_var->base.loc, alloc_args.p, alloc_args.size(), + nullptr, nullptr, nullptr))); +} + +void insert_allocate_stmt_for_struct(Allocator& al, ASR::expr_t* temporary_var, + ASR::expr_t* value, Vec* current_body) { + if( !ASRUtils::is_allocatable(temporary_var) ) { + return ; + } + + Vec alloc_args; alloc_args.reserve(al, 1); + ASR::alloc_arg_t alloc_arg; + alloc_arg.loc = value->base.loc; + alloc_arg.m_a = temporary_var; + alloc_arg.m_dims = nullptr; + alloc_arg.n_dims = 0; + alloc_arg.m_len_expr = nullptr; + alloc_arg.m_type = nullptr; + alloc_args.push_back(al, alloc_arg); + + Vec dealloc_args; dealloc_args.reserve(al, 1); + dealloc_args.push_back(al, temporary_var); + current_body->push_back(al, ASRUtils::STMT(ASR::make_ExplicitDeallocate_t(al, + temporary_var->base.loc, dealloc_args.p, dealloc_args.size()))); + current_body->push_back(al, ASRUtils::STMT(ASR::make_Allocate_t(al, + temporary_var->base.loc, alloc_args.p, alloc_args.size(), + nullptr, nullptr, nullptr))); +} + +void transform_stmts_impl(Allocator& al, ASR::stmt_t**& m_body, size_t& n_body, + Vec*& current_body, bool inside_where, + std::function visit_stmt) { + if( inside_where ) { + for (size_t i = 0; i < n_body; i++) { + visit_stmt(*m_body[i]); + } + } else { + Vec* current_body_copy = current_body; + Vec current_body_vec; current_body_vec.reserve(al, 1); + current_body_vec.reserve(al, n_body); + current_body = ¤t_body_vec; + for (size_t i = 0; i < n_body; i++) { + visit_stmt(*m_body[i]); + current_body->push_back(al, m_body[i]); + } + m_body = current_body_vec.p; n_body = current_body_vec.size(); + current_body = current_body_copy; + } +} + +ASR::expr_t* create_and_declare_temporary_variable_for_scalar( + ASR::expr_t* scalar_expr, const std::string& name_hint, Allocator& al, + Vec*& current_body, SymbolTable* current_scope, + ExprsWithTargetType& exprs_with_target) { + const Location& loc = scalar_expr->base.loc; + ASR::expr_t* scalar_var_temporary = create_temporary_variable_for_scalar( + al, scalar_expr, current_scope, name_hint); + current_body->push_back(al, ASRUtils::STMT(make_Assignment_t_util( + al, loc, scalar_var_temporary, scalar_expr, nullptr, exprs_with_target))); + return scalar_var_temporary; +} + +ASR::expr_t* create_and_allocate_temporary_variable_for_array( + ASR::expr_t* array_expr, const std::string& name_hint, Allocator& al, + Vec*& current_body, SymbolTable* current_scope, + ExprsWithTargetType& exprs_with_target, bool is_pointer_required=false, + ASR::expr_t* allocate_size_reference=nullptr) { + const Location& loc = array_expr->base.loc; + if( allocate_size_reference == nullptr ) { + allocate_size_reference = array_expr; + } + ASR::expr_t* array_var_temporary = create_temporary_variable_for_array( + al, allocate_size_reference, current_scope, name_hint, is_pointer_required); + if( ASRUtils::is_pointer(ASRUtils::expr_type(array_var_temporary)) ) { + exprs_with_target[array_expr] = std::make_pair(array_var_temporary, targetType::GeneratedTargetPointerForArraySection); + current_body->push_back(al, ASRUtils::STMT(ASR::make_Associate_t( + al, loc, array_var_temporary, array_expr))); + } else { + insert_allocate_stmt_for_array(al, array_var_temporary, allocate_size_reference, current_body); + array_expr = ASRUtils::get_past_array_physical_cast(array_expr); + if( !is_pointer_required && + !ASRUtils::is_simd_array(array_expr) && + ( (ASR::is_a(*array_expr) && + !ASRUtils::is_array_indexed_with_array_indices(ASR::down_cast(array_expr))) || + (ASR::is_a(*array_expr) && + !ASRUtils::is_array_indexed_with_array_indices(ASR::down_cast(array_expr))) ) ) { + size_t value_n_dims = ASRUtils::extract_n_dims_from_ttype( + ASRUtils::expr_type(array_expr)); + ASR::ttype_t* tmp_type = ASRUtils::create_array_type_with_empty_dims( + al, value_n_dims, ASRUtils::expr_type(array_expr)); + tmp_type = ASRUtils::TYPE(ASR::make_Pointer_t(al, loc, tmp_type)); + ASR::expr_t* array_expr_ptr = create_temporary_variable_for_array( + al, array_expr->base.loc, current_scope, + "_array_section_pointer_", tmp_type); + current_body->push_back(al, ASRUtils::STMT(ASR::make_Associate_t( + al, loc, array_expr_ptr, array_expr))); + exprs_with_target[array_expr] = std::make_pair(array_expr_ptr, targetType::GeneratedTarget); + array_expr = array_expr_ptr; + } + current_body->push_back(al, ASRUtils::STMT(make_Assignment_t_util( + al, loc, array_var_temporary, array_expr, nullptr, exprs_with_target))); + } + return array_var_temporary; +} + +ASR::expr_t* create_and_allocate_temporary_variable_for_struct( + ASR::expr_t* struct_expr, const std::string& name_hint, Allocator& al, + Vec*& current_body, SymbolTable* current_scope, + ExprsWithTargetType& exprs_with_target) { + const Location& loc = struct_expr->base.loc; + ASR::expr_t* struct_var_temporary = create_temporary_variable_for_struct( + al, struct_expr, current_scope, name_hint); + if( ASRUtils::is_pointer(ASRUtils::expr_type(struct_var_temporary)) ) { + exprs_with_target[struct_expr] = std::make_pair(struct_var_temporary, targetType::GeneratedTarget); + current_body->push_back(al, ASRUtils::STMT(ASR::make_Associate_t( + al, loc, struct_var_temporary, struct_expr))); + } else { + insert_allocate_stmt_for_struct(al, struct_var_temporary, struct_expr, current_body); + struct_expr = ASRUtils::get_past_array_physical_cast(struct_expr); + current_body->push_back(al, ASRUtils::STMT(make_Assignment_t_util( + al, loc, struct_var_temporary, struct_expr, nullptr, exprs_with_target))); + } + return struct_var_temporary; +} + +bool is_elemental_expr(ASR::expr_t* value) { + value = ASRUtils::get_past_array_physical_cast(value); + switch( value->type ) { + case ASR::exprType::Var: + case ASR::exprType::StructInstanceMember: { + return true; + } + default: { + return false; + } + } +} + +bool is_temporary_needed(ASR::expr_t* value) { + if( ASRUtils::is_pointer(ASRUtils::expr_type(value)) ) { + return false; + } + bool is_expr_with_no_type = value && (std::find(exprs_with_no_type.begin(), exprs_with_no_type.end(), + value->type) == exprs_with_no_type.end()) && ASRUtils::is_array(ASRUtils::expr_type(value)); + bool is_non_empty_fixed_size_array = value && (!ASRUtils::is_fixed_size_array(ASRUtils::expr_type(value)) || + (ASRUtils::is_fixed_size_array(ASRUtils::expr_type(value)) && + ASRUtils::get_fixed_size_of_array(ASRUtils::expr_type(value)) > 0)); + return value && is_expr_with_no_type && + !is_elemental_expr(value) && is_non_empty_fixed_size_array; +} + +ASR::symbol_t* extract_symbol(ASR::expr_t* expr) { + switch( expr->type ) { + case ASR::exprType::Var: { + return ASR::down_cast(expr)->m_v; + } + case ASR::exprType::StructInstanceMember: { + return ASRUtils::symbol_get_past_external( + ASR::down_cast(expr)->m_m); + } + default: { + return nullptr; + } + } +} + +bool is_common_symbol_present_in_lhs_and_rhs(Allocator &al, ASR::expr_t* lhs, ASR::expr_t* rhs) { + if (lhs == nullptr) { + return false; + } + Vec lhs_vars, rhs_vars; + lhs_vars.reserve(al, 1); rhs_vars.reserve(al, 1); + ArrayVarCollector lhs_collector(al, lhs_vars); + ArrayVarCollector rhs_collector(al, rhs_vars); + lhs_collector.visit_expr(*lhs); + rhs_collector.visit_expr(*rhs); + + for( size_t i = 0; i < lhs_vars.size(); i++ ) { + ASR::symbol_t* lhs_sym = extract_symbol(lhs_vars[i]); + for( size_t j = 0; j < rhs_vars.size(); j++ ) { + if( extract_symbol(rhs_vars[j]) == lhs_sym ) { + return true; + } + } + } + + return false; +} + +class ArgSimplifier: public ASR::CallReplacerOnExpressionsVisitor +{ + + private: + + Allocator& al; + Vec* current_body; + Vec* parent_body_for_where; + ExprsWithTargetType& exprs_with_target; + ASR::expr_t* lhs_var; + bool realloc_lhs; + bool inside_where; + + public: + + ArgSimplifier(Allocator& al_, ExprsWithTargetType& exprs_with_target_, bool realloc_lhs_) : + al(al_), current_body(nullptr), parent_body_for_where(nullptr), + exprs_with_target(exprs_with_target_), lhs_var(nullptr), realloc_lhs(realloc_lhs_), + inside_where(false) {(void)realloc_lhs; /*Silence-Warning*/} + + + void transform_stmts(ASR::stmt_t**& m_body, size_t& n_body) { + transform_stmts_impl(al, m_body, n_body, current_body, inside_where, + [this](const ASR::stmt_t& stmt) { visit_stmt(stmt); }); + } + + bool var_check(ASR::expr_t* expr) { + return !ASR::is_a(*expr) && ASRUtils::is_array(ASRUtils::expr_type(expr)); + } + + ASR::expr_t* call_create_and_allocate_temporary_variable(ASR::expr_t*& expr, Allocator &al, Vec*& current_body, + const std::string& name_hint, SymbolTable* current_scope, ExprsWithTargetType& exprs_with_target) { + ASR::expr_t* x_m_args_i = ASRUtils::get_past_array_physical_cast(expr); + ASR::expr_t* array_var_temporary = nullptr; + bool is_pointer_required = ASR::is_a(*x_m_args_i) && + !is_common_symbol_present_in_lhs_and_rhs(al, lhs_var, expr) && + !ASRUtils::is_array_indexed_with_array_indices(ASR::down_cast(x_m_args_i)); + array_var_temporary = create_and_allocate_temporary_variable_for_array( + x_m_args_i, name_hint, al, current_body, current_scope, exprs_with_target, + is_pointer_required); + return array_var_temporary; + } + + void visit_IO(ASR::expr_t**& x_values, size_t& n_values, const std::string& name_hint) { + Vec x_m_values; x_m_values.reserve(al, n_values); + /* For frontends like LC, we will need to traverse the print statement arguments + in reverse order. */ + for( size_t i = 0; i < n_values; i++ ) { + if( is_temporary_needed(x_values[i]) ) { + visit_expr(*x_values[i]); + ASR::expr_t* array_var_temporary = call_create_and_allocate_temporary_variable(x_values[i], al, current_body, name_hint, current_scope, exprs_with_target); + x_m_values.push_back(al, array_var_temporary); + } else if( ASRUtils::is_struct(*ASRUtils::expr_type(x_values[i])) && + !ASR::is_a( + *ASRUtils::get_past_array_physical_cast(x_values[i])) ) { + visit_expr(*x_values[i]); + ASR::expr_t* struct_var_temporary = create_and_allocate_temporary_variable_for_struct( + ASRUtils::get_past_array_physical_cast(x_values[i]), name_hint, al, current_body, + current_scope, exprs_with_target); + if( ASR::is_a(*x_values[i]) ) { + ASR::ArrayPhysicalCast_t* x_m_values_i = ASR::down_cast(x_values[i]); + struct_var_temporary = ASRUtils::EXPR(ASRUtils::make_ArrayPhysicalCast_t_util( + al, struct_var_temporary->base.loc, struct_var_temporary, + ASRUtils::extract_physical_type(ASRUtils::expr_type(struct_var_temporary)), + x_m_values_i->m_new, x_m_values_i->m_type, nullptr)); + } + x_m_values.push_back(al, struct_var_temporary); + } else if( ASR::is_a(*x_values[i]) ) { + ASR::ImpliedDoLoop_t* implied_do_loop = ASR::down_cast(x_values[i]); + const Location& loc = x_values[i]->base.loc; + Vec array_con_args; array_con_args.reserve(al, 1); + array_con_args.push_back(al, x_values[i]); + Vec m_dims; m_dims.reserve(al, 1); + ASRUtils::ASRBuilder builder(al, loc); + ASR::dimension_t m_dim; m_dim.loc = loc; + m_dim.m_start = builder.i32(1); + m_dim.m_length = ASRUtils::get_ImpliedDoLoop_size(al, implied_do_loop); + m_dims.push_back(al, m_dim); + ASR::ttype_t* type = ASRUtils::make_Array_t_util(al, loc, + implied_do_loop->m_type, m_dims.p, m_dims.size()); + x_m_values.push_back(al, ASRUtils::EXPR(ASRUtils::make_ArrayConstructor_t_util(al, loc, + array_con_args.p, array_con_args.size(), type, ASR::arraystorageType::ColMajor))); + } else { + visit_expr(*x_values[i]); + x_m_values.push_back(al, x_values[i]); + } + } + + x_values = x_m_values.p; + n_values = x_m_values.size(); + } + + void traverse_args(Vec& x_m_args_vec, ASR::expr_t** x_m_args, + size_t x_n_args, const std::string& name_hint) { + /* For other frontends, we might need to traverse the arguments + in reverse order. */ + for( size_t i = 0; i < x_n_args; i++ ) { + visit_expr(*x_m_args[i]); + if( is_temporary_needed(x_m_args[i]) ) { + ASR::expr_t* array_var_temporary = call_create_and_allocate_temporary_variable(x_m_args[i], al, current_body, name_hint, current_scope, exprs_with_target); + if( ASR::is_a(*x_m_args[i]) ) { + ASR::ArrayPhysicalCast_t* x_m_args_i = ASR::down_cast(x_m_args[i]); + array_var_temporary = ASRUtils::EXPR(ASRUtils::make_ArrayPhysicalCast_t_util( + al, array_var_temporary->base.loc, array_var_temporary, + ASRUtils::extract_physical_type(ASRUtils::expr_type(array_var_temporary)), + x_m_args_i->m_new, x_m_args_i->m_type, nullptr)); + } + x_m_args_vec.push_back(al, array_var_temporary); + } else if( ASRUtils::is_struct(*ASRUtils::expr_type(x_m_args[i])) && + !ASR::is_a( + *ASRUtils::get_past_array_physical_cast(x_m_args[i])) ) { + ASR::expr_t* struct_var_temporary = create_and_allocate_temporary_variable_for_struct( + ASRUtils::get_past_array_physical_cast(x_m_args[i]), name_hint, al, current_body, + current_scope, exprs_with_target); + if( ASR::is_a(*x_m_args[i]) ) { + ASR::ArrayPhysicalCast_t* x_m_args_i = ASR::down_cast(x_m_args[i]); + struct_var_temporary = ASRUtils::EXPR(ASRUtils::make_ArrayPhysicalCast_t_util( + al, struct_var_temporary->base.loc, struct_var_temporary, + ASRUtils::extract_physical_type(ASRUtils::expr_type(struct_var_temporary)), + x_m_args_i->m_new, x_m_args_i->m_type, nullptr)); + } + x_m_args_vec.push_back(al, struct_var_temporary); + } else { + x_m_args_vec.push_back(al, x_m_args[i]); + } + } + } + + void traverse_call_args(Vec& x_m_args_vec, ASR::call_arg_t* x_m_args, + size_t x_n_args, const std::string& name_hint) { + /* For other frontends, we might need to traverse the arguments + in reverse order. */ + for( size_t i = 0; i < x_n_args; i++ ) { + if( is_temporary_needed(x_m_args[i].m_value) ) { + visit_call_arg(x_m_args[i]); + ASR::expr_t* array_var_temporary = call_create_and_allocate_temporary_variable(x_m_args[i].m_value, al, current_body, name_hint, current_scope, exprs_with_target); + if( ASR::is_a(*x_m_args[i].m_value) ) { + ASR::ArrayPhysicalCast_t* x_m_args_i = ASR::down_cast(x_m_args[i].m_value); + array_var_temporary = ASRUtils::EXPR(ASRUtils::make_ArrayPhysicalCast_t_util( + al, array_var_temporary->base.loc, array_var_temporary, + ASRUtils::extract_physical_type(ASRUtils::expr_type(array_var_temporary)), + x_m_args_i->m_new, x_m_args_i->m_type, nullptr)); + } + ASR::call_arg_t call_arg; + call_arg.loc = array_var_temporary->base.loc; + call_arg.m_value = array_var_temporary; + x_m_args_vec.push_back(al, call_arg); + } else if( x_m_args[i].m_value && + ASRUtils::is_struct(*ASRUtils::expr_type(x_m_args[i].m_value)) && + !ASR::is_a( + *ASRUtils::get_past_array_physical_cast(x_m_args[i].m_value)) ) { + ASR::expr_t* struct_var_temporary = create_and_allocate_temporary_variable_for_struct( + ASRUtils::get_past_array_physical_cast(x_m_args[i].m_value), name_hint, al, current_body, + current_scope, exprs_with_target); + if( ASR::is_a(*x_m_args[i].m_value) ) { + ASR::ArrayPhysicalCast_t* x_m_args_i = ASR::down_cast(x_m_args[i].m_value); + struct_var_temporary = ASRUtils::EXPR(ASRUtils::make_ArrayPhysicalCast_t_util( + al, struct_var_temporary->base.loc, struct_var_temporary, + ASRUtils::extract_physical_type(ASRUtils::expr_type(struct_var_temporary)), + x_m_args_i->m_new, x_m_args_i->m_type, nullptr)); + } + ASR::call_arg_t struct_var_temporary_arg; + struct_var_temporary_arg.loc = struct_var_temporary->base.loc; + struct_var_temporary_arg.m_value = struct_var_temporary; + x_m_args_vec.push_back(al, struct_var_temporary_arg); + } else { + x_m_args_vec.push_back(al, x_m_args[i]); + } + } + } + + void visit_Variable(const ASR::Variable_t& /*x*/) { + // Do nothing + } + + void visit_FunctionType(const ASR::FunctionType_t& /*x*/) { + // Do nothing + } + + void visit_Assignment(const ASR::Assignment_t& x) { + ASR::Assignment_t& xx = const_cast(x); + // e.g.; a = [b, a], where 'a' is an allocatable + if (realloc_lhs && ASR::is_a(*xx.m_value) && + ASRUtils::is_allocatable(xx.m_target) + ) { + // TODO: dealing with StructType would need thinking similar to the + // way `traverse_args` handles it, the only reason to not + // add it is because there is currently no integration test + // for it + if (!ASRUtils::is_struct(*ASRUtils::expr_type(xx.m_value))) { + ASR::Var_t* v1 = ASR::down_cast(xx.m_target); + bool create_temp_var_for_rhs = false; + Vec array_vars; array_vars.reserve(al, 1); + ArrayVarCollector array_var_collector(al, array_vars); + array_var_collector.visit_expr(*xx.m_value); + // after collecting variables from RHS, we check whether + // there is any common variable + for (size_t i=0; i < array_vars.size(); i++) { + ASR::Var_t* v = ASR::down_cast(array_vars[i]); + if (v->m_v == v1->m_v) { + create_temp_var_for_rhs = true; + } + } + + if (create_temp_var_for_rhs) { + std::string name_hint = "_assignment_"; + ASR::expr_t* array_var_temporary = call_create_and_allocate_temporary_variable(xx.m_value, al, current_body, name_hint, current_scope, exprs_with_target); + xx.m_value = array_var_temporary; + } + } + } + ASR::expr_t* lhs_array_var = nullptr; + if( ASRUtils::is_array(ASRUtils::expr_type(x.m_target)) ) { + lhs_array_var = ASRUtils::extract_array_variable(x.m_target); + } + lhs_var = lhs_array_var; + ASR::CallReplacerOnExpressionsVisitor::visit_Assignment(x); + lhs_var = nullptr; + } + + void visit_Where(const ASR::Where_t &x) { + bool inside_where_copy = inside_where; + if( !inside_where ) { + inside_where = true; + parent_body_for_where = current_body; + } + Vec* current_body_copy_ = current_body; + current_body = parent_body_for_where; + ASR::expr_t** current_expr_copy_86 = current_expr; + current_expr = const_cast(&(x.m_test)); + call_replacer(); + current_expr = current_expr_copy_86; + if( x.m_test && visit_expr_after_replacement ) + visit_expr(*x.m_test); + current_body = current_body_copy_; + + ASR::Where_t& xx = const_cast(x); + transform_stmts(xx.m_body, xx.n_body); + transform_stmts(xx.m_orelse, xx.n_orelse); + + if( !inside_where_copy ) { + inside_where = false; + parent_body_for_where = nullptr; + } + } + + void visit_Print(const ASR::Print_t& x) { + ASR::Print_t& xx = const_cast(x); + std::string name_hint = "print"; + if( is_temporary_needed(xx.m_text) ) { + visit_expr(*xx.m_text); + ASR::expr_t* array_var_temporary = call_create_and_allocate_temporary_variable(xx.m_text, al, current_body, name_hint, current_scope, exprs_with_target); + xx.m_text = array_var_temporary; + } else if( ASRUtils::is_struct(*ASRUtils::expr_type(xx.m_text)) && + !ASR::is_a( + *ASRUtils::get_past_array_physical_cast(xx.m_text)) ) { + visit_expr(*xx.m_text); + ASR::expr_t* struct_var_temporary = create_and_allocate_temporary_variable_for_struct( + ASRUtils::get_past_array_physical_cast(xx.m_text), name_hint, al, current_body, + current_scope, exprs_with_target); + if( ASR::is_a(*xx.m_text) ) { + ASR::ArrayPhysicalCast_t* x_m_values_i = ASR::down_cast(xx.m_text); + struct_var_temporary = ASRUtils::EXPR(ASRUtils::make_ArrayPhysicalCast_t_util( + al, struct_var_temporary->base.loc, struct_var_temporary, + ASRUtils::extract_physical_type(ASRUtils::expr_type(struct_var_temporary)), + x_m_values_i->m_new, x_m_values_i->m_type, nullptr)); + } + xx.m_text = struct_var_temporary; + } else if( ASR::is_a(*xx.m_text) ) { + ASR::ImpliedDoLoop_t* implied_do_loop = ASR::down_cast(xx.m_text); + const Location& loc = xx.m_text->base.loc; + Vec array_con_args; array_con_args.reserve(al, 1); + array_con_args.push_back(al, xx.m_text); + Vec m_dims; m_dims.reserve(al, 1); + ASRUtils::ASRBuilder builder(al, loc); + ASR::dimension_t m_dim; m_dim.loc = loc; + m_dim.m_start = builder.i32(1); + m_dim.m_length = ASRUtils::get_ImpliedDoLoop_size(al, implied_do_loop); + m_dims.push_back(al, m_dim); + ASR::ttype_t* type = ASRUtils::make_Array_t_util(al, loc, + implied_do_loop->m_type, m_dims.p, m_dims.size()); + xx.m_text = ASRUtils::EXPR(ASRUtils::make_ArrayConstructor_t_util(al, loc, + array_con_args.p, array_con_args.size(), type, ASR::arraystorageType::ColMajor)); + } else { + visit_expr(*xx.m_text); + } + CallReplacerOnExpressionsVisitor::visit_Print(x); + } + + void visit_FileWrite(const ASR::FileWrite_t& x) { + ASR::FileWrite_t& xx = const_cast(x); + visit_IO(xx.m_values, xx.n_values, "file_write"); + CallReplacerOnExpressionsVisitor::visit_FileWrite(x); + } + + void visit_FileRead(const ASR::FileRead_t& x) { + ASR::FileRead_t& xx = const_cast(x); + visit_IO(xx.m_values, xx.n_values, "file_read"); + CallReplacerOnExpressionsVisitor::visit_FileRead(x); + } + + void visit_StringFormat(const ASR::StringFormat_t& x) { + ASR::StringFormat_t& xx = const_cast(x); + visit_IO(xx.m_args, xx.n_args, "string_format"); + CallReplacerOnExpressionsVisitor::visit_StringFormat(x); + } + + ASR::expr_t* visit_BinOp_expr(ASR::expr_t* expr, const std::string& name_hint, ASR::exprType allowed_expr) { + if (ASRUtils::is_array(ASRUtils::expr_type(expr)) && + !ASR::is_a(*expr) && + !is_vectorise_able(expr) && + (expr->type != allowed_expr) + ) { + visit_expr(*expr); + ASR::expr_t* array_var_temporary = call_create_and_allocate_temporary_variable(expr, al, current_body, name_hint, current_scope, exprs_with_target); + return array_var_temporary; + } else if( ASRUtils::is_struct(*ASRUtils::expr_type(expr)) && + !ASR::is_a( + *ASRUtils::get_past_array_physical_cast(expr)) ) { + visit_expr(*expr); + ASR::expr_t* struct_var_temporary = create_and_allocate_temporary_variable_for_struct( + ASRUtils::get_past_array_physical_cast(expr), name_hint, al, current_body, + current_scope, exprs_with_target); + if( ASR::is_a(*expr) ) { + ASR::ArrayPhysicalCast_t* x_m_values_i = ASR::down_cast(expr); + struct_var_temporary = ASRUtils::EXPR(ASRUtils::make_ArrayPhysicalCast_t_util( + al, struct_var_temporary->base.loc, struct_var_temporary, + ASRUtils::extract_physical_type(ASRUtils::expr_type(struct_var_temporary)), + x_m_values_i->m_new, x_m_values_i->m_type, nullptr)); + } + return struct_var_temporary; + } else { + return expr; + } + } + + template + bool visit_BinOpUtil(T* binop, const std::string& name_hint, + std::pair& left_right, ASR::exprType allowed_expr) { + if( ASRUtils::is_simd_array(binop->m_type) ) { + return false; + } + ASR::expr_t* left = visit_BinOp_expr(binop->m_left, name_hint + "_left_", allowed_expr); + ASR::expr_t* right = visit_BinOp_expr(binop->m_right, name_hint + "_right_", allowed_expr); + left_right = std::make_pair(left, right); + return true; + } + + void visit_IntegerBinOp(const ASR::IntegerBinOp_t& x) { + ASR::IntegerBinOp_t& xx = const_cast(x); + std::pair binop; + if( !visit_BinOpUtil(&xx, "integer_binop", binop, ASR::exprType::IntegerBinOp) ) { + return ; + } + xx.m_left = binop.first; + xx.m_right = binop.second; + CallReplacerOnExpressionsVisitor::visit_IntegerBinOp(x); + } + + void visit_RealBinOp(const ASR::RealBinOp_t& x) { + ASR::RealBinOp_t& xx = const_cast(x); + std::pair binop; + if( !visit_BinOpUtil(&xx, "real_binop", binop, ASR::exprType::RealBinOp) ) { + return ; + } + xx.m_left = binop.first; + xx.m_right = binop.second; + CallReplacerOnExpressionsVisitor::visit_RealBinOp(x); + } + + void visit_ComplexBinOp(const ASR::ComplexBinOp_t& x) { + ASR::ComplexBinOp_t& xx = const_cast(x); + std::pair binop; + if( !visit_BinOpUtil(&xx, "complex_binop", binop, ASR::exprType::ComplexBinOp) ) { + return ; + } + xx.m_left = binop.first; + xx.m_right = binop.second; + CallReplacerOnExpressionsVisitor::visit_ComplexBinOp(x); + } + + void visit_LogicalBinOp(const ASR::LogicalBinOp_t& x) { + ASR::LogicalBinOp_t& xx = const_cast(x); + std::pair binop; + if( !visit_BinOpUtil(&xx, "logical_binop", binop, ASR::exprType::LogicalBinOp) ) { + return ; + } + xx.m_left = binop.first; + xx.m_right = binop.second; + CallReplacerOnExpressionsVisitor::visit_LogicalBinOp(x); + } + + void visit_LogicalNot(const ASR::LogicalNot_t& x) { + ASR::LogicalNot_t& xx = const_cast(x); + xx.m_arg = visit_BinOp_expr(x.m_arg, "logical_not_", ASR::exprType::LogicalNot); + CallReplacerOnExpressionsVisitor::visit_LogicalNot(x); + } + + void visit_RealUnaryMinus(const ASR::RealUnaryMinus_t& x) { + ASR::RealUnaryMinus_t& xx = const_cast(x); + // Replace only when the x.m_arg i.e., the operand of RealUnaryMinus + // must need evaluation. For example -some_function_call, here some_function_call + // needs temporary if it is non-elemental and returns an array. -(a + b) doesn't + // need a temporary because it can be vectorised as -(a(i) + b(i)) + if( !is_vectorise_able(xx.m_arg) ) { + xx.m_arg = visit_BinOp_expr(x.m_arg, "real_unary_minus_", ASR::exprType::RealUnaryMinus); + } + CallReplacerOnExpressionsVisitor::visit_RealUnaryMinus(x); + } + + void visit_RealCompare(const ASR::RealCompare_t& x) { + ASR::RealCompare_t& xx = const_cast(x); + std::pair binop; + if( !visit_BinOpUtil(&xx, "real_compare", binop, ASR::exprType::RealCompare) ) { + return ; + } + xx.m_left = binop.first; + xx.m_right = binop.second; + CallReplacerOnExpressionsVisitor::visit_RealCompare(x); + } + + void visit_IntegerCompare(const ASR::IntegerCompare_t& x) { + ASR::IntegerCompare_t& xx = const_cast(x); + std::pair binop; + if( !visit_BinOpUtil(&xx, "integer_compare", binop, ASR::exprType::IntegerCompare) ) { + return ; + } + xx.m_left = binop.first; + xx.m_right = binop.second; + CallReplacerOnExpressionsVisitor::visit_IntegerCompare(x); + } + + template + void visit_TypeConstructor(const T& x, const std::string& name_hint) { + Vec x_m_args; x_m_args.reserve(al, x.n_args); + traverse_args(x_m_args, x.m_args, x.n_args, name_hint); + T& xx = const_cast(x); + xx.m_args = x_m_args.p; + xx.n_args = x_m_args.size(); + } + + void visit_EnumConstructor(const ASR::EnumConstructor_t& x) { + visit_TypeConstructor(x, std::string("_enum_type_constructor_") + + ASRUtils::symbol_name(x.m_dt_sym)); + } + + void visit_UnionConstructor(const ASR::UnionConstructor_t& x) { + visit_TypeConstructor(x, std::string("_union_type_constructor_") + + ASRUtils::symbol_name(x.m_dt_sym)); + } + + void visit_TypeInquiry(const ASR::TypeInquiry_t& x) { + Vec x_m_args_; x_m_args_.reserve(al, 1); + x_m_args_.push_back(al, x.m_arg); + Vec x_m_args; x_m_args.reserve(al, 1); + traverse_args(x_m_args, x_m_args_.p, x_m_args_.size(), std::string("_type_inquiry_")); + ASR::TypeInquiry_t& xx = const_cast(x); + xx.m_arg = x_m_args[0]; + } + + void visit_ArrayConstructor(const ASR::ArrayConstructor_t& x) { + Vec x_m_args; x_m_args.reserve(al, x.n_args); + traverse_args(x_m_args, x.m_args, x.n_args, std::string("_array_constructor_")); + ASR::ArrayConstructor_t& xx = const_cast(x); + xx.m_args = x_m_args.p; + xx.n_args = x_m_args.size(); + } + + template + void visit_IntrinsicCall(const T& x, const std::string& name_hint) { + Vec x_m_args; x_m_args.reserve(al, x.n_args); + traverse_args(x_m_args, x.m_args, x.n_args, name_hint); + T& xx = const_cast(x); + xx.m_args = x_m_args.p; + xx.n_args = x_m_args.size(); + } + + void visit_IntrinsicImpureSubroutine(const ASR::IntrinsicImpureSubroutine_t& x) { + visit_IntrinsicCall(x, "_intrinsic_impure_subroutine_" + + ASRUtils::get_intrinsic_subroutine_name(x.m_sub_intrinsic_id)); + } + + void visit_IntrinsicElementalFunction(const ASR::IntrinsicElementalFunction_t& x) { + visit_IntrinsicCall(x, "_intrinsic_elemental_function_" + + ASRUtils::get_intrinsic_name(x.m_intrinsic_id)); + ASR::CallReplacerOnExpressionsVisitor::visit_IntrinsicElementalFunction(x); + } + + void visit_IntrinsicArrayFunction(const ASR::IntrinsicArrayFunction_t& x) { + visit_IntrinsicCall(x, "_intrinsic_array_function_" + + ASRUtils::get_array_intrinsic_name(x.m_arr_intrinsic_id)); + ASR::IntrinsicArrayFunction_t& xx = const_cast(x); + if( ASRUtils::IntrinsicArrayFunctionRegistry::get_dim_index( + static_cast(x.m_arr_intrinsic_id)) == 1 && + x.n_args > 1 && ASRUtils::is_array(x.m_type) ) { + Vec dims; + diag::Diagnostics diags; + ASRUtils::ArrIntrinsic::fill_dimensions_for_ArrIntrinsic( + al, ASRUtils::extract_n_dims_from_ttype(x.m_type), x.m_args[0], + x.m_args[1], diags, !ASRUtils::is_value_constant(x.m_args[1]), dims); + xx.m_type = ASRUtils::duplicate_type(al, x.m_type, &dims, + ASR::array_physical_typeType::DescriptorArray, true); + } + } + + template + void visit_Call(const T& x, const std::string& name_hint) { + LCOMPILERS_ASSERT(!x.m_dt || !ASRUtils::is_array(ASRUtils::expr_type(x.m_dt))); + Vec x_m_args; x_m_args.reserve(al, x.n_args); + traverse_call_args(x_m_args, x.m_args, x.n_args, + name_hint + ASRUtils::symbol_name(x.m_name)); + T& xx = const_cast(x); + xx.m_args = x_m_args.p; + xx.n_args = x_m_args.size(); + } + + void visit_StructConstructor(const ASR::StructConstructor_t& x) { + Vec x_m_args; x_m_args.reserve(al, x.n_args); + traverse_call_args(x_m_args, x.m_args, x.n_args, + std::string("_struct_type_constructor_") + ASRUtils::symbol_name(x.m_dt_sym)); + ASR::StructConstructor_t& xx = const_cast(x); + xx.m_args = x_m_args.p; + xx.n_args = x_m_args.size(); + } + + void visit_SubroutineCall(const ASR::SubroutineCall_t& x) { + visit_Call(x, "_subroutine_call_"); + ASR::CallReplacerOnExpressionsVisitor::visit_SubroutineCall(x); + } + + void visit_FunctionCall(const ASR::FunctionCall_t& x) { + visit_Call(x, "_function_call_"); + ASR::CallReplacerOnExpressionsVisitor::visit_FunctionCall(x); + } + + void replace_expr_with_temporary_variable(ASR::expr_t* &xx_member, ASR::expr_t* x_member, const std::string& name_hint) { + if( var_check(x_member)) { + visit_expr(*x_member); + bool is_pointer_required = ASR::is_a(*x_member) && + name_hint.find("_array_is_contiguous_array") != std::string::npos && + !ASRUtils::is_array_indexed_with_array_indices(ASR::down_cast(x_member)); + xx_member = create_and_allocate_temporary_variable_for_array(x_member, + name_hint, al, current_body, current_scope, exprs_with_target, is_pointer_required); + } + } + + void visit_ArrayReshape(const ASR::ArrayReshape_t& x) { + ASR::ArrayReshape_t& xx = const_cast(x); + replace_expr_with_temporary_variable(xx.m_array, x.m_array, "_array_reshape_array"); + } + + void visit_ArrayIsContiguous(const ASR::ArrayIsContiguous_t& x) { + ASR::ArrayIsContiguous_t& xx = const_cast(x); + replace_expr_with_temporary_variable(xx.m_array, x.m_array, "_array_is_contiguous_array"); + } + + void visit_ComplexConstructor(const ASR::ComplexConstructor_t& x) { + ASR::ComplexConstructor_t& xx = const_cast(x); + + replace_expr_with_temporary_variable(xx.m_re, x.m_re, "_complex_constructor_re"); + + replace_expr_with_temporary_variable(xx.m_im, xx.m_im, "_complex_constructor_im"); + } + + void visit_ArrayTranspose(const ASR::ArrayTranspose_t& x) { + ASR::ArrayTranspose_t& xx = const_cast(x); + + replace_expr_with_temporary_variable(xx.m_matrix, x.m_matrix, "_array_transpose_matrix_"); + } + + void visit_ArrayPack(const ASR::ArrayPack_t& x) { + ASR::ArrayPack_t& xx = const_cast(x); + + replace_expr_with_temporary_variable(xx.m_array, x.m_array, "_array_pack_array_"); + + replace_expr_with_temporary_variable(xx.m_mask, x.m_mask, "_array_pack_mask_"); + + if( x.m_vector ) { + replace_expr_with_temporary_variable(xx.m_vector, x.m_vector, "_array_pack_vector_"); + } + } + + void visit_ComplexRe(const ASR::ComplexRe_t& x) { + ASR::ComplexRe_t& xx = const_cast(x); + + replace_expr_with_temporary_variable(xx.m_arg, x.m_arg, "_complex_re_"); + } + + void visit_ComplexIm(const ASR::ComplexIm_t& x) { + ASR::ComplexIm_t& xx = const_cast(x); + + replace_expr_with_temporary_variable(xx.m_arg, x.m_arg, "_complex_im_"); + } + + void visit_RealSqrt(const ASR::RealSqrt_t& x) { + ASR::RealSqrt_t& xx = const_cast(x); + + replace_expr_with_temporary_variable(xx.m_arg, x.m_arg, "_real_sqrt_"); + } + + void visit_ArrayBound(const ASR::ArrayBound_t& x) { + ASR::ArrayBound_t& xx = const_cast(x); + + if( is_temporary_needed(xx.m_v) ) { + replace_expr_with_temporary_variable(xx.m_v, x.m_v, "_array_bound_v"); + } + } + + void visit_ArraySize(const ASR::ArraySize_t& x) { + ASR::ArraySize_t& xx = const_cast(x); + if( is_temporary_needed(xx.m_v) ) { + replace_expr_with_temporary_variable(xx.m_v, x.m_v, "_array_size_v"); + } + } +}; + +class ReplaceExprWithTemporary: public ASR::BaseExprReplacer { + + private: + + Allocator& al; + ExprsWithTargetType& exprs_with_target; + bool realloc_lhs; + + public: + + Vec* current_body; + SymbolTable* current_scope; + bool is_assignment_target_array_section_item; + bool is_simd_expression; + ASR::ttype_t* simd_type; + ASR::expr_t* parent_expr; + ASR::expr_t* lhs_var; + + ReplaceExprWithTemporary(Allocator& al_, ExprsWithTargetType& exprs_with_target_, bool realloc_lhs_) : + al(al_), exprs_with_target(exprs_with_target_), realloc_lhs(realloc_lhs_), current_scope(nullptr), + is_assignment_target_array_section_item(false), is_simd_expression(false), simd_type(nullptr), + parent_expr(nullptr), lhs_var(nullptr) {} + + bool is_current_expr_linked_to_target(ExprsWithTargetType& exprs_with_target, ASR::expr_t** ¤t_expr) { + return exprs_with_target.find(*current_expr) != exprs_with_target.end(); + } + + bool is_current_expr_linked_to_target_then_return(ASR::expr_t** ¤t_expr, ExprsWithTargetType& exprs_with_target, + Vec* ¤t_body, bool &realloc_lhs, Allocator& al) { + if( is_current_expr_linked_to_target(exprs_with_target, current_expr) ) { + std::pair& target_info = exprs_with_target[*current_expr]; + ASR::expr_t* target = target_info.first; targetType target_Type = target_info.second; + if( ASRUtils::is_allocatable(ASRUtils::expr_type(target)) && + target_Type == targetType::OriginalTarget && + realloc_lhs ) { + insert_allocate_stmt_for_array(al, target, *current_expr, current_body); + } + return true; + } + return false; + } + + void force_replace_current_expr_for_array(ASR::expr_t** ¤t_expr, const std::string& name_hint, Allocator& al, + Vec* ¤t_body, SymbolTable* ¤t_scope, ExprsWithTargetType& exprs_with_target, + bool is_assignment_target_array_section_item) { + *current_expr = create_and_allocate_temporary_variable_for_array( + *current_expr, name_hint, al, current_body, + current_scope, exprs_with_target, is_assignment_target_array_section_item); + } + + void force_replace_current_expr_for_struct(ASR::expr_t** ¤t_expr, const std::string& name_hint, Allocator& al, + Vec* ¤t_body, SymbolTable* ¤t_scope, ExprsWithTargetType& exprs_with_target) { + *current_expr = create_and_allocate_temporary_variable_for_struct( + *current_expr, name_hint, al, current_body, + current_scope, exprs_with_target); + } + + void force_replace_current_expr_for_scalar(ASR::expr_t** ¤t_expr, const std::string& name_hint, Allocator& al, + Vec* ¤t_body, SymbolTable* ¤t_scope, ExprsWithTargetType& exprs_with_target) { + *current_expr = create_and_declare_temporary_variable_for_scalar( + *current_expr, name_hint, al, current_body, + current_scope, exprs_with_target); + } + + template + void replace_current_expr(T* &x, const std::string& name_hint) { + if( is_current_expr_linked_to_target_then_return(current_expr, exprs_with_target, current_body, realloc_lhs, al) ) { + return; + } + if( ASRUtils::is_array(x->m_type) ) { + force_replace_current_expr_for_array(current_expr, name_hint, al, current_body, current_scope, exprs_with_target, is_assignment_target_array_section_item); + } else if( ASRUtils::is_struct(*x->m_type) ) { + force_replace_current_expr_for_struct(current_expr, name_hint, al, current_body, current_scope, exprs_with_target); + } + } + + void replace_ComplexConstructor(ASR::ComplexConstructor_t* x) { + replace_current_expr(x, "_complex_constructor_"); + } + + void replace_FunctionCall(ASR::FunctionCall_t* x) { + if( PassUtils::is_elemental(x->m_name) && !ASR::is_a(*x->m_type)) { + // ASR::Function_t* f = ASR::down_cast(x->m_name); + // std::cout << f << "\n"; + return ; + } + + if( is_current_expr_linked_to_target(exprs_with_target, current_expr) && ASRUtils::is_array(x->m_type) ) { + targetType target_Type = exprs_with_target[*current_expr].second; + ASR::expr_t* target = exprs_with_target[*current_expr].first; + ASR::array_index_t* m_args = nullptr; size_t n_args = 0; + ASRUtils::extract_indices(target, m_args, n_args); + if( (target_Type == targetType::OriginalTarget && (realloc_lhs || + ASRUtils::is_array_indexed_with_array_indices(m_args, n_args) || + ((ASRUtils::is_array(ASRUtils::expr_type(target)) || + ASRUtils::is_array(x->m_type)) && + is_common_symbol_present_in_lhs_and_rhs(al, target, *current_expr))) ) || + target_Type == targetType::GeneratedTargetPointerForArraySection || + (!ASRUtils::is_allocatable(target) && ASRUtils::is_allocatable(x->m_type)) ) { + force_replace_current_expr_for_array(current_expr, std::string("_function_call_") + + ASRUtils::symbol_name(x->m_name), al, current_body, current_scope, + exprs_with_target, is_assignment_target_array_section_item); + return ; + } + } + if( !ASRUtils::is_array(x->m_type) && + is_common_symbol_present_in_lhs_and_rhs(al, lhs_var, *current_expr) ) { + force_replace_current_expr_for_scalar(current_expr, std::string("_function_call_") + + ASRUtils::symbol_name(x->m_name), al, current_body, current_scope, exprs_with_target); + return ; + } + + replace_current_expr(x, std::string("_function_call_") + + ASRUtils::symbol_name(x->m_name)); + } + + void replace_IntrinsicArrayFunction(ASR::IntrinsicArrayFunction_t* x) { + std::string name_hint = std::string("_intrinsic_array_function_") + ASRUtils::get_array_intrinsic_name(x->m_arr_intrinsic_id); + if (!(is_current_expr_linked_to_target(exprs_with_target, current_expr) || ASRUtils::is_array(x->m_type))) { + force_replace_current_expr_for_scalar(current_expr, name_hint, al, current_body, current_scope, exprs_with_target); + } else if ((is_current_expr_linked_to_target(exprs_with_target, current_expr) && + static_cast(ASRUtils::IntrinsicArrayFunctions::Transpose) == x->m_arr_intrinsic_id && + exprs_with_target[*current_expr].second == targetType::OriginalTarget) || + (is_current_expr_linked_to_target(exprs_with_target, current_expr) && + exprs_with_target[*current_expr].second == + targetType::GeneratedTargetPointerForArraySection) || + (is_current_expr_linked_to_target(exprs_with_target, current_expr) && (( + ASRUtils::is_array(ASRUtils::expr_type(exprs_with_target[*current_expr].first)) || + ASRUtils::is_array(x->m_type)) && + is_common_symbol_present_in_lhs_and_rhs(al, exprs_with_target[*current_expr].first, *current_expr))) + ) { + // x = transpose(x), where 'x' is user-variable + // needs have a temporary, there might be more + // intrinsic array functions needing this + force_replace_current_expr_for_array(current_expr, name_hint, al, current_body, current_scope, + exprs_with_target, is_assignment_target_array_section_item); + } else { + replace_current_expr(x, name_hint); + } + } + + void replace_IntrinsicImpureFunction(ASR::IntrinsicImpureFunction_t* x) { + replace_current_expr(x, std::string("_intrinsic_impure_function_") + + ASRUtils::get_impure_intrinsic_name(x->m_impure_intrinsic_id)); + } + + void replace_StructConstructor(ASR::StructConstructor_t* x) { + replace_current_expr(x, "_struct_constructor_"); + } + + void replace_EnumConstructor(ASR::EnumConstructor_t* x) { + replace_current_expr(x, "_enum_constructor_"); + } + + void replace_UnionConstructor(ASR::UnionConstructor_t* x) { + replace_current_expr(x, "_union_constructor_"); + } + + void replace_ImpliedDoLoop(ASR::ImpliedDoLoop_t* x) { + replace_current_expr(x, "_implied_do_loop_"); + } + + void replace_ListConstant(ASR::ListConstant_t* x) { + replace_current_expr(x, "_list_constant_"); + } + + void replace_SetConstant(ASR::SetConstant_t* x) { + replace_current_expr(x, "_set_constant_"); + } + + void replace_TupleConstant(ASR::TupleConstant_t* x) { + replace_current_expr(x, "_tuple_constant_"); + } + + void replace_StringSection(ASR::StringSection_t* x) { + replace_current_expr(x, "_string_section_"); + } + + void replace_DictConstant(ASR::DictConstant_t* x) { + replace_current_expr(x, "_dict_constant_"); + } + + void replace_ArrayConstructor(ASR::ArrayConstructor_t* x) { + replace_current_expr(x, "_array_constructor_"); + } + + void replace_ArrayConstant(ASR::ArrayConstant_t* /*x*/) { + // assign a temporary variable only when either + // (a). there is no target, e.g. size([1, 2, 3]) + // (b). there is an OriginalTarget and realloc_lhs is true e.g. `x = [1, 2, 3, 4]` + if (exprs_with_target.find(*current_expr) == exprs_with_target.end() || + (exprs_with_target[*current_expr].second == targetType::OriginalTarget && realloc_lhs)) { + force_replace_current_expr_for_array(current_expr, "_array_constant_", al, current_body, current_scope, + exprs_with_target, is_assignment_target_array_section_item); + } + } + + ASR::expr_t* generate_associate_for_array_section(ASR::expr_t** ¤t_expr, Allocator& al, const Location &loc, + SymbolTable* ¤t_scope, Vec* ¤t_body) { + size_t value_n_dims = ASRUtils::extract_n_dims_from_ttype(ASRUtils::expr_type(*current_expr)); + ASR::ttype_t* tmp_type = ASRUtils::create_array_type_with_empty_dims( + al, value_n_dims, ASRUtils::expr_type(*current_expr)); + tmp_type = ASRUtils::TYPE(ASR::make_Pointer_t(al, loc, tmp_type)); + ASR::expr_t* array_expr_ptr = create_temporary_variable_for_array( + al, loc, current_scope, "_array_section_pointer_", tmp_type); + current_body->push_back(al, ASRUtils::STMT(ASR::make_Associate_t( + al, loc, array_expr_ptr, *current_expr))); + *current_expr = array_expr_ptr; + return array_expr_ptr; + } + + void replace_ArraySection(ASR::ArraySection_t* x) { + ASR::BaseExprReplacer::replace_ArraySection(x); + if( ASRUtils::is_array_indexed_with_array_indices(x) ) { + if( (exprs_with_target.find(*current_expr) == exprs_with_target.end() && + !is_assignment_target_array_section_item) || + is_common_symbol_present_in_lhs_and_rhs(al, lhs_var, x->m_v)) { + *current_expr = create_and_allocate_temporary_variable_for_array( + *current_expr, "_array_section_", al, current_body, + current_scope, exprs_with_target); + } + return ; + } + + const Location& loc = x->base.base.loc; + if( is_simd_expression ) { + if( is_current_expr_linked_to_target(exprs_with_target, current_expr) ) { + return ; + } + + ASR::expr_t* array_expr_ptr = generate_associate_for_array_section(current_expr, + al, loc, current_scope, current_body); + + array_expr_ptr = create_temporary_variable_for_array( + al, loc, current_scope, "_array_section_copy_", simd_type); + current_body->push_back(al, ASRUtils::STMT(ASR::make_Assignment_t( + al, loc, array_expr_ptr, *current_expr, nullptr))); + *current_expr = array_expr_ptr; + return ; + } + + if( exprs_with_target.find(*current_expr) != exprs_with_target.end() ) { + generate_associate_for_array_section(current_expr, al, loc, current_scope, current_body); + return ; + } + + replace_current_expr(x, "_array_section_"); + } + + void replace_ArrayTranspose(ASR::ArrayTranspose_t* x) { + replace_current_expr(x, "_array_transpose_"); + } + + void replace_ArrayPack(ASR::ArrayPack_t* x) { + replace_current_expr(x, "_array_pack_"); + } + + void replace_ArrayReshape(ASR::ArrayReshape_t* x) { + replace_current_expr(x, "_array_reshape_"); + } + + void replace_ArrayItem(ASR::ArrayItem_t* x) { + if( ASRUtils::is_array_indexed_with_array_indices(x) ) { + ASR::BaseExprReplacer::replace_ArrayItem(x); + if( (exprs_with_target.find(*current_expr) == exprs_with_target.end() && + !is_assignment_target_array_section_item) || + is_common_symbol_present_in_lhs_and_rhs(al, lhs_var, x->m_v)) { + *current_expr = create_and_allocate_temporary_variable_for_array( + *current_expr, "_array_item_", al, current_body, + current_scope, exprs_with_target); + } + return ; + } else if( is_common_symbol_present_in_lhs_and_rhs(al, lhs_var, x->m_v) ) { + ASR::BaseExprReplacer::replace_ArrayItem(x); + *current_expr = create_and_declare_temporary_variable_for_scalar(*current_expr, + "_array_item_", al, current_body, current_scope, exprs_with_target); + } + + if( ASR::is_a(*x->m_v) ) { + return ; + } + ASR::BaseExprReplacer::replace_ArrayItem(x); + } + + void replace_IntegerBinOp(ASR::IntegerBinOp_t* x) { + ASR::expr_t* parent_expr_copy = parent_expr; + parent_expr = *current_expr; + ASR::BaseExprReplacer::replace_IntegerBinOp(x); + parent_expr = parent_expr_copy; + if( parent_expr == nullptr ) { + replace_current_expr(x, "_integer_binop_"); + } + } + + void replace_StructStaticMember(ASR::StructStaticMember_t* x) { + replace_current_expr(x, "_struct_static_member_"); + } + + void replace_EnumStaticMember(ASR::EnumStaticMember_t* x) { + replace_current_expr(x, "_enum_static_member_"); + } + + void replace_UnionInstanceMember(ASR::UnionInstanceMember_t* x) { + replace_current_expr(x, "_union_instance_member_"); + } + + void replace_OverloadedCompare(ASR::OverloadedCompare_t* x) { + replace_current_expr(x, "_overloaded_compare_"); + } + + template + void replace_OverloadedOperator(T* x) { + LCOMPILERS_ASSERT(x->m_overloaded); + std::pair target_Info = + std::make_pair(nullptr, targetType::GeneratedTarget); + if( exprs_with_target.find(*current_expr) != exprs_with_target.end() ) { + target_Info = exprs_with_target[*current_expr]; + } + *current_expr = x->m_overloaded; + if( target_Info.first != nullptr ) { + exprs_with_target[*current_expr] = target_Info; + } + ASR::BaseExprReplacer::replace_expr(*current_expr); + } + + void replace_OverloadedBinOp(ASR::OverloadedBinOp_t* x) { + replace_OverloadedOperator(x); + } + + void replace_OverloadedUnaryMinus(ASR::OverloadedUnaryMinus_t* x) { + replace_OverloadedOperator(x); + } + + void replace_OverloadedStringConcat(ASR::OverloadedStringConcat_t* x) { + replace_OverloadedOperator(x); + } + + void replace_ComplexRe(ASR::ComplexRe_t* x) { + replace_current_expr(x, "_complex_re_"); + } + + void replace_ComplexIm(ASR::ComplexIm_t* x) { + replace_current_expr(x, "_complex_im_"); + } + + void replace_ListSection(ASR::ListSection_t* x) { + replace_current_expr(x, "_list_section_"); + } + + void replace_ListRepeat(ASR::ListRepeat_t* x) { + replace_current_expr(x, "_list_repeat_"); + } + + void replace_DictPop(ASR::DictPop_t* x) { + replace_current_expr(x, "_dict_pop_"); + } + + void replace_SetPop(ASR::SetPop_t* x) { + replace_current_expr(x, "_set_pop_"); + } + + void replace_RealSqrt(ASR::RealSqrt_t* x) { + replace_current_expr(x, "_real_sqrt_"); + } + + void replace_ArrayBound(ASR::ArrayBound_t* x) { + ASR::expr_t** current_expr_copy_149 = current_expr; + current_expr = &(x->m_v); + if( is_temporary_needed(x->m_v) ) { + force_replace_current_expr_for_array(current_expr, "_array_bound_v", al, current_body, current_scope, + exprs_with_target, is_assignment_target_array_section_item); + } + current_expr = current_expr_copy_149; + } + + void replace_ArraySize(ASR::ArraySize_t* x) { + ASR::expr_t** current_expr_copy_149 = current_expr; + current_expr = &(x->m_v); + if( is_temporary_needed(x->m_v) ) { + force_replace_current_expr_for_array(current_expr, "_array_size_v", al, current_body, current_scope, + exprs_with_target, is_assignment_target_array_section_item); + } + current_expr = current_expr_copy_149; + } +}; + +class ReplaceExprWithTemporaryVisitor: + public ASR::CallReplacerOnExpressionsVisitor { + + private: + + Allocator& al; + ExprsWithTargetType& exprs_with_target; + Vec* current_body; + ReplaceExprWithTemporary replacer; + Vec* parent_body_for_where; + bool inside_where; + + public: + + ReplaceExprWithTemporaryVisitor(Allocator& al_, ExprsWithTargetType& exprs_with_target_, bool realloc_lhs_): + al(al_), exprs_with_target(exprs_with_target_), replacer(al, exprs_with_target, realloc_lhs_), + parent_body_for_where(nullptr), inside_where(false) { + replacer.call_replacer_on_value = false; + call_replacer_on_value = false; + } + + void call_replacer() { + replacer.current_expr = current_expr; + replacer.current_body = current_body; + replacer.current_scope = current_scope; + replacer.replace_expr(*current_expr); + } + + void visit_Variable(const ASR::Variable_t& /*x*/) { + // Do nothing + } + + void visit_FunctionType(const ASR::FunctionType_t& /*x*/) { + // Do nothing + } + + void transform_stmts(ASR::stmt_t **&m_body, size_t &n_body) { + transform_stmts_impl(al, m_body, n_body, current_body, inside_where, + [this](const ASR::stmt_t& stmt) { visit_stmt(stmt); }); + } + + void visit_Where(const ASR::Where_t &x) { + bool inside_where_copy = inside_where; + if( !inside_where ) { + inside_where = true; + parent_body_for_where = current_body; + } + Vec* current_body_copy_ = current_body; + current_body = parent_body_for_where; + ASR::expr_t** current_expr_copy_86 = current_expr; + current_expr = const_cast(&(x.m_test)); + call_replacer(); + current_expr = current_expr_copy_86; + if( x.m_test && visit_expr_after_replacement ) + visit_expr(*x.m_test); + current_body = current_body_copy_; + + ASR::Where_t& xx = const_cast(x); + transform_stmts(xx.m_body, xx.n_body); + transform_stmts(xx.m_orelse, xx.n_orelse); + + if( !inside_where_copy ) { + inside_where = false; + parent_body_for_where = nullptr; + } + } + + + void visit_ArrayBroadcast(const ASR::ArrayBroadcast_t &x) { + ASR::expr_t** current_expr_copy_273 = current_expr; + current_expr = const_cast(&(x.m_array)); + call_replacer(); + current_expr = current_expr_copy_273; + if( x.m_array ) + visit_expr(*x.m_array); + visit_ttype(*x.m_type); + if (x.m_value) { + if (call_replacer_on_value) { + ASR::expr_t** current_expr_copy_275 = current_expr; + current_expr = const_cast(&(x.m_value)); + call_replacer(); + current_expr = current_expr_copy_275; + } + if( x.m_value ) { + visit_expr(*x.m_value); + } + } + } + + void visit_ArrayItem(const ASR::ArrayItem_t& x) { + if( ASR::is_a(*x.m_v) ) { + return ; + } + ASR::CallReplacerOnExpressionsVisitor::visit_ArrayItem(x); + } + + void visit_Assignment(const ASR::Assignment_t &x) { + ASR::array_index_t* m_args = nullptr; size_t n_args = 0; + ASR::expr_t* lhs_array_var = nullptr; + if( ASRUtils::is_array(ASRUtils::expr_type(x.m_target)) ) { + lhs_array_var = ASRUtils::extract_array_variable(x.m_target); + } + if( ASR::is_a(*x.m_target) || + ASR::is_a(*x.m_target) ) { + ASRUtils::extract_indices(x.m_target, m_args, n_args); + bool is_assignment_target_array_section_item = replacer.is_assignment_target_array_section_item; + replacer.is_assignment_target_array_section_item = true; + ASR::expr_t** current_expr_copy_8 = current_expr; + ASR::expr_t* original_target = x.m_target; + current_expr = const_cast(&(x.m_target)); + call_replacer(); + current_expr = current_expr_copy_8; + replacer.is_assignment_target_array_section_item = is_assignment_target_array_section_item; + if( x.m_target != original_target ) { + exprs_with_target[x.m_value] = std::make_pair(x.m_target, targetType::GeneratedTargetPointerForArraySection); + } + } + ASR::expr_t** current_expr_copy_9 = current_expr; + bool is_simd_expr_copy = replacer.is_simd_expression; + ASR::ttype_t* simd_type_copy = replacer.simd_type; + replacer.is_simd_expression = ASRUtils::is_simd_array(x.m_value); + replacer.simd_type = ASRUtils::expr_type(x.m_value); + replacer.lhs_var = lhs_array_var; + current_expr = const_cast(&(x.m_value)); + call_replacer(); + replacer.lhs_var = nullptr; + if( ASRUtils::is_array_indexed_with_array_indices(m_args, n_args) && + ASRUtils::is_array(ASRUtils::expr_type(x.m_value)) && + !is_elemental_expr(x.m_value) ) { + bool is_assignment_target_array_section_item = true; + replacer.force_replace_current_expr_for_array(current_expr, "_assignment_value_", al, current_body, current_scope, + exprs_with_target, is_assignment_target_array_section_item); + } + current_expr = current_expr_copy_9; + replacer.is_simd_expression = is_simd_expr_copy; + replacer.simd_type = simd_type_copy; + if( !ASRUtils::is_simd_array(x.m_value) ) { + visit_expr(*x.m_value); + } + if (x.m_overloaded) { + visit_stmt(*x.m_overloaded); + } + } + + void visit_Associate(const ASR::Associate_t& /*x*/) { + } + + void visit_CPtrToPointer(const ASR::CPtrToPointer_t& /*x*/) { + } + +}; + +bool check_if_ASR_owner_is_module(ASR::asr_t* &asr_owner) { + return ASR::is_a(*asr_owner) && ASR::is_a(*ASR::down_cast(asr_owner)); +} + +bool check_if_ASR_owner_is_enum(ASR::asr_t* &asr_owner) { + return ASR::is_a(*asr_owner) && ASR::is_a(*ASR::down_cast(asr_owner)); +} + +bool check_if_ASR_owner_is_struct(ASR::asr_t* &asr_owner) { + return ASR::is_a(*asr_owner) && ASR::is_a(*ASR::down_cast(asr_owner)); +} + +class ReplaceModuleVarWithValue: + public ASR::BaseExprReplacer { + + private: + + Allocator& al; + + public: + + ReplaceModuleVarWithValue(Allocator& al_): al(al_) {} + + void replace_Var(ASR::Var_t* x) { + if( !ASR::is_a( + *ASRUtils::symbol_get_past_external(x->m_v)) ) { + return ; + } + + ASR::Variable_t* y = ASR::down_cast( + ASRUtils::symbol_get_past_external(x->m_v)); + if( !((check_if_ASR_owner_is_module(y->m_parent_symtab->asr_owner)) && + y->m_storage == ASR::storage_typeType::Parameter) || + y->m_symbolic_value == nullptr ) { + return ; + } + + ASRUtils::ExprStmtDuplicator expr_duplicator(al); + ASR::expr_t* value = nullptr; + if (y->m_value) { + value = y->m_value; + } else { + value = y->m_symbolic_value; + } + *current_expr = expr_duplicator.duplicate_expr(value); + replace_expr(*current_expr); + } + +}; + +class TransformVariableInitialiser: + public ASR::CallReplacerOnExpressionsVisitor { + + private: + + Allocator& al; + ExprsWithTargetType& exprs_with_target; + std::map> symtab2decls; + ReplaceModuleVarWithValue replacer; + + public: + + TransformVariableInitialiser(Allocator& al_, ExprsWithTargetType& exprs_with_target_): al(al_), + exprs_with_target(exprs_with_target_), replacer(al_) {} + + void call_replacer() { + replacer.current_expr = current_expr; + replacer.replace_expr(*current_expr); + } + + void visit_Variable(const ASR::Variable_t &x) { + ASR::expr_t* value = x.m_value ? x.m_value : x.m_symbolic_value; + // TODO: StructType expressions aren't evaluated at compile time + // currently, see: https://github.com/lfortran/lfortran/issues/4909 + if ((check_if_ASR_owner_is_module(x.m_parent_symtab->asr_owner)) || + (check_if_ASR_owner_is_enum(x.m_parent_symtab->asr_owner)) || + (check_if_ASR_owner_is_struct(x.m_parent_symtab->asr_owner)) || + ( x.m_storage == ASR::storage_typeType::Parameter && + // this condition ensures that currently constants + // not evaluated at compile time like + // real(4), parameter :: z(1) = [x % y] + // are converted to an assignment for now + ASRUtils::is_value_constant(value) && + !ASR::is_a( + *ASRUtils::extract_type(ASRUtils::expr_type(value)) + ) + ) || ( + x.m_storage == ASR::storage_typeType::Save && + value && + ASRUtils::is_value_constant(value) + ) + ) { + return; + } + + const Location& loc = x.base.base.loc; + for( size_t i = 0; i < x.n_dependencies; i++ ) { + std::string dep_name = x.m_dependencies[i]; + visit_symbol(*(current_scope->resolve_symbol(dep_name))); + } + + ASR::Variable_t& xx = const_cast(x); + if (value) { + if( symtab2decls.find(x.m_parent_symtab) == symtab2decls.end() ) { + Vec result_vec; result_vec.reserve(al, 1); + symtab2decls[x.m_parent_symtab] = result_vec; + } + Vec& result_vec = symtab2decls[x.m_parent_symtab]; + ASR::expr_t* target = ASRUtils::EXPR(ASR::make_Var_t(al, loc, &(xx.base))); + + // if `m_value` is present, then use that for converting it into + // assignment/association below, otherwise use `m_symbolic_value` + // for the same. As `m_value` is usually more "simplified" than + // `m_symbolic_value` + ASR::expr_t* value = nullptr; + if (xx.m_value) { + value = xx.m_value; + } else { + value = xx.m_symbolic_value; + } + + exprs_with_target[value] = std::make_pair(target, targetType::OriginalTarget); + if (ASRUtils::is_pointer(x.m_type)) { + result_vec.push_back(al, ASRUtils::STMT(ASR::make_Associate_t( + al, loc, target, value))); + } else { + result_vec.push_back(al, ASRUtils::STMT(make_Assignment_t_util( + al, loc, target, value, nullptr, exprs_with_target))); + } + xx.m_symbolic_value = nullptr; + xx.m_value = nullptr; + } + } + + void transform_stmts(ASR::stmt_t **&m_body, size_t &n_body) { + Vec body; + body.reserve(al, n_body); + + if( symtab2decls.find(current_scope) != symtab2decls.end() ) { + Vec& decls = symtab2decls[current_scope]; + for (size_t j = 0; j < decls.size(); j++) { + body.push_back(al, decls[j]); + } + symtab2decls.erase(current_scope); + } + + for (size_t i = 0; i < n_body; i++) { + visit_stmt(*m_body[i]); + body.push_back(al, m_body[i]); + } + m_body = body.p; + n_body = body.size(); + } + + void visit_StructType(const ASR::StructType_t& x) { + std::string derived_type_name = ASRUtils::symbol_name(x.m_derived_type); + if( x.m_derived_type == current_scope->resolve_symbol(derived_type_name) ) { + return ; + } + + ASR::StructType_t& xx = const_cast(x); + xx.m_derived_type = current_scope->resolve_symbol(derived_type_name); + } + +}; + +class CheckNodeTypesInExpr: public ASR::BaseWalkVisitor { + private: + + Vec& nodes; + + public: + + bool is_node_incorrect; + CheckNodeTypesInExpr(Vec& nodes_): + nodes(nodes_), is_node_incorrect(false) {} + + void visit_expr(const ASR::expr_t& e) { + if( is_node_incorrect ) { + return; + } + bool is_node_correct = false; + for( size_t i = 0; i < nodes.size(); i++ ) { + if( e.type == nodes[i] ) { + if( e.type == ASR::exprType::FunctionCall ) { + ASR::FunctionCall_t* func_call = ASR::down_cast(&(e)); + if( !ASRUtils::is_array(func_call->m_type) ) { + is_node_correct = true; + } + } else if( e.type == ASR::exprType::IntrinsicElementalFunction ) { + ASR::IntrinsicElementalFunction_t* elem_func = ASR::down_cast(&(e)); + if( !ASRUtils::is_array(elem_func->m_type) ) { + is_node_correct = true; + } + } else { + is_node_correct = true; + } + break; + } + } + is_node_incorrect = is_node_incorrect || !is_node_correct; + ASR::BaseWalkVisitor::visit_expr(e); + } + +}; + +class VerifySimplifierASROutput: + public ASR::BaseWalkVisitor { + + private: + + Allocator& al; + ExprsWithTargetType& exprs_with_target; + + public: + + VerifySimplifierASROutput(Allocator& al_, ExprsWithTargetType& exprs_with_target_) : + al(al_), exprs_with_target(exprs_with_target_) { + visit_compile_time_value = false; + (void)exprs_with_target; // explicitly reference to avoid unused warning + } + + void visit_ArrayBroadcast(const ASR::ArrayBroadcast_t &x) { + visit_expr(*x.m_array); + visit_ttype(*x.m_type); + if (x.m_value && visit_compile_time_value) { + visit_expr(*x.m_value); + } + } + + void visit_Assignment(const ASR::Assignment_t& x) { + if( !ASRUtils::is_simd_array(x.m_value) ) { + LCOMPILERS_ASSERT(!ASR::is_a(*x.m_value)); + } + if( ASR::is_a(*x.m_target) ) { + visit_expr(*x.m_target); + } + visit_expr(*x.m_value); + if (x.m_overloaded) { + visit_stmt(*x.m_overloaded); + } + } + + void visit_FunctionType(const ASR::FunctionType_t& /*x*/) { + // Do nothing + } + + void visit_Associate(const ASR::Associate_t& /*x*/) { + return ; + } + + void check_for_var_if_array(ASR::expr_t* expr) { + if ( is_temporary_needed(expr) ) { + LCOMPILERS_ASSERT(ASR::is_a(*ASRUtils::get_past_array_physical_cast(expr))); + } + } + + void check_if_linked_to_target([[maybe_unused]] ASR::expr_t expr, ASR::ttype_t* type) { + if( ASRUtils::is_aggregate_type(type) && + ASRUtils::is_simd_array(type) ) { + LCOMPILERS_ASSERT(exprs_with_target.find(&expr) != exprs_with_target.end()); + } + } + + template + void visit_IO(const T& x) { + for( size_t i = 0; i < x.n_values; i++ ) { + check_for_var_if_array(x.m_values[i]); + } + } + + void visit_Print(const ASR::Print_t& x) { + check_for_var_if_array(x.m_text); + } + + void visit_FileWrite(const ASR::FileWrite_t& x) { + visit_IO(x); + } + + void traverse_call_args(ASR::call_arg_t* m_args, size_t n_args) { + for( size_t i = 0; i < n_args; i++ ) { + check_for_var_if_array(m_args[i].m_value); + } + } + + void traverse_args(ASR::expr_t** m_args, size_t n_args) { + for( size_t i = 0; i < n_args; i++ ) { + check_for_var_if_array(m_args[i]); + } + } + + template + void visit_Call(const T& x) { + traverse_call_args(x.m_args, x.n_args); + } + + void visit_SubroutineCall(const ASR::SubroutineCall_t& x) { + visit_Call(x); + } + + template + void visit_IntrinsicCall(const T& x) { + traverse_args(x.m_args, x.n_args); + } + + void visit_IntrinsicImpureSubroutine(const ASR::IntrinsicImpureSubroutine_t& x) { + visit_IntrinsicCall(x); + } + + void visit_ComplexConstructor(const ASR::ComplexConstructor_t& x) { + check_for_var_if_array(x.m_re); + check_for_var_if_array(x.m_im); + check_if_linked_to_target(x.base, x.m_type); + } + + void visit_FunctionCall(const ASR::FunctionCall_t& x) { + visit_Call(x); + if( !PassUtils::is_elemental(x.m_name) ) { + check_if_linked_to_target(x.base, x.m_type); + } + } + + void visit_IntrinsicElementalFunction(const ASR::IntrinsicElementalFunction_t& x) { + visit_IntrinsicCall(x); + } + + void visit_IntrinsicArrayFunction(const ASR::IntrinsicArrayFunction_t& x) { + visit_IntrinsicCall(x); + check_if_linked_to_target(x.base, x.m_type); + } + + void visit_StructConstructor(const ASR::StructConstructor_t& x) { + traverse_call_args(x.m_args, x.n_args); + check_if_linked_to_target(x.base, x.m_type); + } + + void visit_EnumTypeConstructor(const ASR::EnumConstructor_t& x) { + traverse_args(x.m_args, x.n_args); + check_if_linked_to_target(x.base, x.m_type); + } + + void visit_UnionConstructor(const ASR::UnionConstructor_t& x) { + traverse_args(x.m_args, x.n_args); + check_if_linked_to_target(x.base, x.m_type); + } + + void visit_ImpliedDoLoop(const ASR::ImpliedDoLoop_t& x) { + check_if_linked_to_target(x.base, x.m_type); + } + + void visit_ListConstant(const ASR::ListConstant_t& x) { + check_if_linked_to_target(x.base, x.m_type); + } + + void visit_SetConstant(const ASR::SetConstant_t& x) { + check_if_linked_to_target(x.base, x.m_type); + } + + void visit_TupleConstant(const ASR::TupleConstant_t& x) { + check_if_linked_to_target(x.base, x.m_type); + } + + void visit_StringSection(const ASR::StringSection_t& x) { + check_if_linked_to_target(x.base, x.m_type); + } + + void visit_DictConstant(const ASR::DictConstant_t& x) { + check_if_linked_to_target(x.base, x.m_type); + } + + void visit_ArrayConstant(const ASR::ArrayConstant_t& x) { + check_if_linked_to_target(x.base, x.m_type); + } + + void visit_ArraySection(const ASR::ArraySection_t& x) { + check_if_linked_to_target(x.base, x.m_type); + } + + void visit_ArrayReshape(const ASR::ArrayReshape_t& x) { + check_if_linked_to_target(x.base, x.m_type); + } + + void visit_ArrayConstructor(const ASR::ArrayConstructor_t& x) { + traverse_args(x.m_args, x.n_args); + } + + void visit_ArrayTranspose(const ASR::ArrayTranspose_t& x) { + check_for_var_if_array(x.m_matrix); + } + + void visit_ArrayPack(const ASR::ArrayPack_t& x) { + check_for_var_if_array(x.m_array); + check_for_var_if_array(x.m_mask); + check_for_var_if_array(x.m_vector); + } + + void visit_ArrayItem(const ASR::ArrayItem_t& x) { + if( ASR::is_a(*x.m_v) ) { + return ; + } + ASR::BaseWalkVisitor::visit_ArrayItem(x); + } + + void visit_StructStaticMember(const ASR::StructStaticMember_t& x) { + check_if_linked_to_target(x.base, x.m_type); + } + + void visit_EnumStaticMember(const ASR::EnumStaticMember_t& x) { + check_if_linked_to_target(x.base, x.m_type); + } + + void visit_UnionInstanceMember(const ASR::UnionInstanceMember_t& x) { + check_if_linked_to_target(x.base, x.m_type); + } + + void visit_OverloadedCompare(const ASR::OverloadedCompare_t& x) { + check_if_linked_to_target(x.base, x.m_type); + } + + void visit_OverloadedBinOp(const ASR::OverloadedBinOp_t& x) { + check_if_linked_to_target(x.base, x.m_type); + } + + void visit_OverloadedUnaryMinus(const ASR::OverloadedUnaryMinus_t& x) { + check_if_linked_to_target(x.base, x.m_type); + } + + void visit_OverloadedStringConcat(const ASR::OverloadedStringConcat_t& x) { + check_if_linked_to_target(x.base, x.m_type); + } + + void visit_ComplexRe(const ASR::ComplexRe_t& x) { + check_for_var_if_array(x.m_arg); + check_if_linked_to_target(x.base, x.m_type); + } + + void visit_ComplexIm(const ASR::ComplexIm_t& x) { + check_for_var_if_array(x.m_arg); + check_if_linked_to_target(x.base, x.m_type); + } + + void visit_ListSection(const ASR::ListSection_t& x) { + check_if_linked_to_target(x.base, x.m_type); + } + + void visit_ListRepeat(const ASR::ListRepeat_t& x) { + check_if_linked_to_target(x.base, x.m_type); + } + + void visit_DictPop(const ASR::DictPop_t& x) { + check_if_linked_to_target(x.base, x.m_type); + } + + void visit_SetPop(const ASR::SetPop_t& x) { + check_if_linked_to_target(x.base, x.m_type); + } + + void visit_RealSqrt(const ASR::RealSqrt_t& x) { + check_for_var_if_array(x.m_arg); + check_if_linked_to_target(x.base, x.m_type); + } + + void visit_ArrayBound(const ASR::ArrayBound_t& x) { + check_for_var_if_array(x.m_v); + check_for_var_if_array(x.m_dim); + + } + + void visit_Variable(const ASR::Variable_t& x) { + if( (ASRUtils::is_array(x.m_type) || + ASRUtils::is_aggregate_type(x.m_type)) && + !(check_if_ASR_owner_is_module(x.m_parent_symtab->asr_owner)) && + !(check_if_ASR_owner_is_enum(x.m_parent_symtab->asr_owner)) && + !(check_if_ASR_owner_is_struct(x.m_parent_symtab->asr_owner)) && + !(x.m_storage == ASR::storage_typeType::Save && x.m_symbolic_value && + ASRUtils::is_value_constant(x.m_symbolic_value) + ) && + x.m_storage != ASR::storage_typeType::Parameter ) { + LCOMPILERS_ASSERT(x.m_symbolic_value == nullptr); + LCOMPILERS_ASSERT(x.m_value == nullptr); + } + } + + void visit_Allocate(const ASR::Allocate_t& x) { + for( size_t i = 0; i < x.n_args; i++ ) { + for( size_t j = 0; j < x.m_args[i].n_dims; j++ ) { + ASR::dimension_t& alloc_dim = x.m_args[i].m_dims[j]; + LCOMPILERS_ASSERT(alloc_dim.m_length); + Vec vec; + vec.reserve(al, 2); + vec.push_back(al, ASR::exprType::Var); + vec.push_back(al, ASR::exprType::FunctionCall); + vec.push_back(al, ASR::exprType::IntrinsicElementalFunction); + CheckNodeTypesInExpr check(vec); + check.visit_expr(*alloc_dim.m_length); + if( alloc_dim.m_start != nullptr ) { + check.visit_expr(*alloc_dim.m_start); + } + } + } + } + +}; + +class InitialiseExprWithTarget: public ASR::BaseWalkVisitor { + private: + + ExprsWithTargetType& exprs_with_target; + + public: + + InitialiseExprWithTarget(ExprsWithTargetType& exprs_with_target_): + exprs_with_target(exprs_with_target_) {} + + void visit_Assignment(const ASR::Assignment_t& x) { + if ( ASR::is_a(*x.m_value) && !ASRUtils::is_array(ASRUtils::expr_type(x.m_value)) ) { + return; + } + exprs_with_target[x.m_value] = std::make_pair(const_cast(x.m_target), targetType::OriginalTarget); + } + +}; + +void pass_array_struct_temporary(Allocator &al, ASR::TranslationUnit_t &unit, + const PassOptions &pass_options) { + // TODO: Add a visitor in asdl_cpp.py which will replace + // current_expr with its own `m_value` (if `m_value` is not nullptr) + // Call the visitor here. + ASRUtils::RemoveArrayProcessingNodeVisitor remove_array_processing_node_visitor(al); + remove_array_processing_node_visitor.visit_TranslationUnit(unit); + ExprsWithTargetType exprs_with_target; + InitialiseExprWithTarget init_expr_with_target(exprs_with_target); + init_expr_with_target.visit_TranslationUnit(unit); + TransformVariableInitialiser a(al, exprs_with_target); + a.visit_TranslationUnit(unit); + ArgSimplifier b(al, exprs_with_target, pass_options.realloc_lhs); + b.visit_TranslationUnit(unit); + ReplaceExprWithTemporaryVisitor c(al, exprs_with_target, pass_options.realloc_lhs); + c.visit_TranslationUnit(unit); + PassUtils::UpdateDependenciesVisitor d(al); + d.visit_TranslationUnit(unit); + #if defined(WITH_LFORTRAN_ASSERT) + VerifySimplifierASROutput e(al, exprs_with_target); + e.visit_TranslationUnit(unit); + #endif +} + + +} // namespace LCompilers diff --git a/src/libasr/pass/array_struct_temporary.h b/src/libasr/pass/array_struct_temporary.h new file mode 100644 index 0000000000..b5f27b4fc2 --- /dev/null +++ b/src/libasr/pass/array_struct_temporary.h @@ -0,0 +1,14 @@ +#ifndef LIBASR_PASS_ARRAY_STRUCT_TEMPORARY_H +#define LIBASR_PASS_ARRAY_STRUCT_TEMPORARY_H + +#include +#include + +namespace LCompilers { + + void pass_array_struct_temporary(Allocator &al, ASR::TranslationUnit_t &unit, + const PassOptions &pass_options); + +} // namespace LCompilers + +#endif // LIBASR_PASS_ARRAY_STRUCT_TEMPORARY_H diff --git a/src/libasr/pass/class_constructor.cpp b/src/libasr/pass/class_constructor.cpp index d79bdd264c..51cd8d4178 100644 --- a/src/libasr/pass/class_constructor.cpp +++ b/src/libasr/pass/class_constructor.cpp @@ -6,8 +6,6 @@ #include #include -#include -#include namespace LCompilers { diff --git a/src/libasr/pass/dead_code_removal.cpp b/src/libasr/pass/dead_code_removal.cpp index 491bf967c7..b851a0fb61 100644 --- a/src/libasr/pass/dead_code_removal.cpp +++ b/src/libasr/pass/dead_code_removal.cpp @@ -6,10 +6,6 @@ #include #include -#include -#include -#include - namespace LCompilers { diff --git a/src/libasr/pass/div_to_mul.cpp b/src/libasr/pass/div_to_mul.cpp index b476d89caf..c79bfbaa68 100644 --- a/src/libasr/pass/div_to_mul.cpp +++ b/src/libasr/pass/div_to_mul.cpp @@ -6,9 +6,6 @@ #include #include -#include -#include - namespace LCompilers { diff --git a/src/libasr/pass/do_loops.cpp b/src/libasr/pass/do_loops.cpp index cdc6cb8436..63dbfa3967 100644 --- a/src/libasr/pass/do_loops.cpp +++ b/src/libasr/pass/do_loops.cpp @@ -37,15 +37,29 @@ class DoLoopVisitor : public ASR::StatementWalkVisitor { public: bool use_loop_variable_after_loop = false; - DoLoopVisitor(Allocator &al) : StatementWalkVisitor(al) { - } + PassOptions pass_options; + DoLoopVisitor(Allocator &al, PassOptions pass_options_) : + StatementWalkVisitor(al), pass_options(pass_options_) { } void visit_DoLoop(const ASR::DoLoop_t &x) { pass_result = PassUtils::replace_doloop(al, x, -1, use_loop_variable_after_loop); } void visit_DoConcurrentLoop(const ASR::DoConcurrentLoop_t &x) { - ASR::asr_t* do_loop = ASR::make_DoLoop_t(al, x.base.base.loc, s2c(al, ""), x.m_head, x.m_body, x.n_body, nullptr, 0); + if (pass_options.enable_gpu_offloading) { + // DoConcurrentLoop is handled in the MLIR backend + return; + } + Vec body;body.reserve(al,1); + for (int i = 0; i < static_cast(x.n_body); i++) { + body.push_back(al,x.m_body[i]); + } + for (int i = static_cast(x.n_head) - 1; i > 0; i--) { + ASR::asr_t* do_loop = ASR::make_DoLoop_t(al, x.base.base.loc, s2c(al, ""), x.m_head[i], body.p, body.n, nullptr, 0); + body={};body.reserve(al,1); + body.push_back(al,ASRUtils::STMT(do_loop)); + } + ASR::asr_t* do_loop = ASR::make_DoLoop_t(al, x.base.base.loc, s2c(al, ""), x.m_head[0], body.p, body.n, nullptr, 0); const ASR::DoLoop_t &do_loop_ref = (const ASR::DoLoop_t&)(*do_loop); pass_result = PassUtils::replace_doloop(al, do_loop_ref, -1, use_loop_variable_after_loop); } @@ -53,7 +67,7 @@ class DoLoopVisitor : public ASR::StatementWalkVisitor void pass_replace_do_loops(Allocator &al, ASR::TranslationUnit_t &unit, const LCompilers::PassOptions& pass_options) { - DoLoopVisitor v(al); + DoLoopVisitor v(al, pass_options); // Each call transforms only one layer of nested loops, so we call it twice // to transform doubly nested loops: v.asr_changed = true; diff --git a/src/libasr/pass/flip_sign.cpp b/src/libasr/pass/flip_sign.cpp index 518fba22e9..c3df5ad218 100644 --- a/src/libasr/pass/flip_sign.cpp +++ b/src/libasr/pass/flip_sign.cpp @@ -7,9 +7,6 @@ #include #include -#include -#include - namespace LCompilers { @@ -187,8 +184,7 @@ class FlipSignVisitor : public PassUtils::SkipOptimizationFunctionVisitortype == ASR::symbolType::ExternalSymbol ) { ASR::ExternalSymbol_t* ext_sym = ASR::down_cast(func_name); - if( std::string(ext_sym->m_original_name) == "modulo" && - std::string(ext_sym->m_module_name) == "lfortran_intrinsic_math2" ) { + if( std::string(ext_sym->m_original_name) == "modulo" ) { is_function_modulo = true; } } diff --git a/src/libasr/pass/fma.cpp b/src/libasr/pass/fma.cpp index 2cb478b5c3..16873ef0ce 100644 --- a/src/libasr/pass/fma.cpp +++ b/src/libasr/pass/fma.cpp @@ -6,9 +6,6 @@ #include #include -#include -#include - namespace LCompilers { @@ -32,26 +29,11 @@ code. d = fma(a, b, c) */ -class FMAVisitor : public PassUtils::SkipOptimizationFunctionVisitor -{ -private: - ASR::TranslationUnit_t &unit; - - LCompilers::PassOptions pass_options; - ASR::expr_t* fma_var; - - // To make sure that FMA is applied only for - // the nodes implemented in this class - bool from_fma; - -public: - FMAVisitor(Allocator &al_, ASR::TranslationUnit_t &unit_, - const LCompilers::PassOptions& pass_options_) : SkipOptimizationFunctionVisitor(al_), - unit(unit_), pass_options(pass_options_), fma_var(nullptr), from_fma(false) - { - pass_result.reserve(al, 1); - } +class ReplaceRealBinOpFMA : public ASR::BaseExprReplacer{ + Allocator& al; + const LCompilers::PassOptions& pass_options; + const ASR::TranslationUnit_t& unit; bool is_BinOpMul(ASR::expr_t* expr) { if (ASR::is_a(*expr)) { @@ -61,45 +43,27 @@ class FMAVisitor : public PassUtils::SkipOptimizationFunctionVisitor return false; } - void visit_IntegerBinOp(const ASR::IntegerBinOp_t& /*x*/) { } - void visit_ComplexBinOp(const ASR::ComplexBinOp_t& /*x*/) { } - void visit_LogicalBinOp(const ASR::LogicalBinOp_t& /*x*/) { } - - void visit_RealBinOp(const ASR::RealBinOp_t& x_const) { - if( !from_fma ) { - return ; - } - - from_fma = true; - LCOMPILERS_ASSERT(ASRUtils::is_real(*x_const.m_type)) - ASR::RealBinOp_t& x = const_cast(x_const); - - fma_var = nullptr; - visit_expr(*x.m_left); - if( fma_var ) { - x.m_left = fma_var; - } +public : + ReplaceRealBinOpFMA(Allocator& al, + const LCompilers::PassOptions& pass_options, const ASR::TranslationUnit_t& unit) + :al{al}, pass_options{pass_options}, unit{unit}{} + + void replace_RealBinOp(ASR::RealBinOp_t* x) { + BaseExprReplacer::replace_RealBinOp(x); - fma_var = nullptr; - visit_expr(*x.m_right); - if( fma_var ) { - x.m_right = fma_var; - } - fma_var = nullptr; - - if( x.m_op != ASR::binopType::Add && x.m_op != ASR::binopType::Sub ) { + if( x->m_op != ASR::binopType::Add && x->m_op != ASR::binopType::Sub ) { return ; } ASR::expr_t *mul_expr = nullptr, *other_expr = nullptr; bool is_mul_expr_negative = false, is_other_expr_negative = false; - if( is_BinOpMul(x.m_right) ) { - mul_expr = x.m_right; - other_expr = x.m_left; - is_mul_expr_negative = (x.m_op == ASR::binopType::Sub); - } else if( is_BinOpMul(x.m_left) ) { - mul_expr = x.m_left; - other_expr = x.m_right; - is_other_expr_negative = (x.m_op == ASR::binopType::Sub); + if( is_BinOpMul(x->m_right) ) { + mul_expr = x->m_right; + other_expr = x->m_left; + is_mul_expr_negative = (x->m_op == ASR::binopType::Sub); + } else if( is_BinOpMul(x->m_left) ) { + mul_expr = x->m_left; + other_expr = x->m_right; + is_other_expr_negative = (x->m_op == ASR::binopType::Sub); } else { return ; } @@ -111,64 +75,48 @@ class FMAVisitor : public PassUtils::SkipOptimizationFunctionVisitor ASR::RealBinOp_t* mul_binop = ASR::down_cast(mul_expr); ASR::expr_t *first_arg = mul_binop->m_left, *second_arg = mul_binop->m_right; - if( is_mul_expr_negative ) { first_arg = ASRUtils::EXPR(ASR::make_RealUnaryMinus_t(al, first_arg->base.loc, first_arg, ASRUtils::expr_type(first_arg), nullptr)); } - fma_var = PassUtils::get_fma(other_expr, first_arg, second_arg, - al, unit, x.base.base.loc, pass_options); - from_fma = false; + *current_expr = PassUtils::get_fma(other_expr, first_arg, second_arg, + al, const_cast(unit), x->base.base.loc, + const_cast(pass_options)); } - void visit_Assignment(const ASR::Assignment_t& x) { - from_fma = true; - ASR::Assignment_t& xx = const_cast(x); - fma_var = nullptr; - visit_expr(*x.m_value); - if( fma_var ) { - xx.m_value = fma_var; - } - fma_var = nullptr; - from_fma = false; - } - void visit_IntegerUnaryMinus(const ASR::IntegerUnaryMinus_t &x) { - visit_UnaryOp(x); - } - void visit_RealUnaryMinus(const ASR::RealUnaryMinus_t &x) { - visit_UnaryOp(x); - } - void visit_ComplexUnaryMinus(const ASR::ComplexUnaryMinus_t &x) { - visit_UnaryOp(x); - } - void visit_IntegerBitNot(const ASR::IntegerBitNot_t &x) { - visit_UnaryOp(x); - } - void visit_LogicalNot(const ASR::LogicalNot_t &x) { - visit_UnaryOp(x); - } +}; + - template - void visit_UnaryOp(const T& x) { - from_fma = true; - T& xx = const_cast(x); - fma_var = nullptr; - visit_expr(*x.m_arg); - if( fma_var ) { - xx.m_arg = fma_var; + +class CallReplacerFMA : public ASR::CallReplacerOnExpressionsVisitor{ + ReplaceRealBinOpFMA replacer; +public : + CallReplacerFMA(Allocator &al, const ASR::TranslationUnit_t &unit, + const LCompilers::PassOptions& pass_options) + : replacer{al, pass_options, unit}{} + void call_replacer(){ + if(ASR::is_a(**current_expr)){ + replacer.current_expr = current_expr; + replacer.replace_expr(*current_expr); } - fma_var = nullptr; - from_fma = false; } - + void visit_Function(const ASR::Function_t& x){ // Avoid visiting RealBinOp in the fma` function itself + if(std::string(x.m_name) == "_lcompilers_optimization_fma_f32" || + std::string(x.m_name) == "_lcompilers_optimization_fma_f64"){ + return; + } + CallReplacerOnExpressionsVisitor::visit_Function(x); + } + }; + void pass_replace_fma(Allocator &al, ASR::TranslationUnit_t &unit, const LCompilers::PassOptions& pass_options) { - FMAVisitor v(al, unit, pass_options); - v.visit_TranslationUnit(unit); + CallReplacerFMA realBinOpFMA_replacer{al, unit, pass_options}; + realBinOpFMA_replacer.visit_TranslationUnit(unit); PassUtils::UpdateDependenciesVisitor u(al); u.visit_TranslationUnit(unit); } diff --git a/src/libasr/pass/for_all.cpp b/src/libasr/pass/for_all.cpp index 6db553fb9f..fa0e48f898 100644 --- a/src/libasr/pass/for_all.cpp +++ b/src/libasr/pass/for_all.cpp @@ -32,9 +32,11 @@ class ForAllVisitor : public ASR::StatementWalkVisitor Vec body; body.reserve(al, 1); body.push_back(al, assign_stmt); - + Vec heads; // Create a vector of loop heads + heads.reserve(al,1); + heads.push_back(al, x.m_head); ASR::stmt_t *stmt = ASRUtils::STMT( - ASR::make_DoConcurrentLoop_t(al, loc, x.m_head, body.p, body.size()) + ASR::make_DoConcurrentLoop_t(al, loc, heads.p, heads.n, nullptr, 0, nullptr, 0, nullptr, 0, body.p, body.size()) ); Vec result; result.reserve(al, 1); diff --git a/src/libasr/pass/function_call_in_declaration.cpp b/src/libasr/pass/function_call_in_declaration.cpp index f94e2371c3..11421b3e69 100644 --- a/src/libasr/pass/function_call_in_declaration.cpp +++ b/src/libasr/pass/function_call_in_declaration.cpp @@ -46,6 +46,7 @@ class ReplaceFunctionCall : public ASR::BaseExprReplacer { public: Allocator& al; + SymbolTable* new_function_scope = nullptr; SymbolTable* current_scope = nullptr; ASR::expr_t* assignment_value = nullptr; ASR::expr_t* call_for_return_var = nullptr; @@ -61,6 +62,16 @@ class ReplaceFunctionCall : public ASR::BaseExprReplacer ReplaceFunctionCall(Allocator &al_) : al(al_) {} + void replace_Var(ASR::Var_t* x) { + if ( newargsp == nullptr) { + return ; + } + if ( new_function_scope == nullptr ) { + return ; + } + *current_expr = ASRUtils::EXPR(ASR::make_Var_t(al, x->base.base.loc, new_function_scope->get_symbol(ASRUtils::symbol_name(x->m_v)))); + } + void replace_FunctionParam(ASR::FunctionParam_t* x) { if( newargsp == nullptr ) { return ; @@ -80,51 +91,86 @@ class ReplaceFunctionCall : public ASR::BaseExprReplacer newargsp = nullptr; } - bool exists_in_arginfo(int arg_number, std::vector& indicies) { - for (auto info: indicies) { + bool exists_in_arginfo(int arg_number, std::vector& indices) { + for (auto info: indices) { if (info.arg_number == arg_number) return true; } return false; } - void helper_get_arg_indices_used(ASR::expr_t* arg, std::vector& indicies) { + void helper_get_arg_indices_used(ASR::expr_t* arg, std::vector& indices) { if (is_a(*arg)) { ASR::ArrayPhysicalCast_t* cast = ASR::down_cast(arg); arg = cast->m_arg; } if (is_a(*arg)) { - get_arg_indices_used_functioncall(ASR::down_cast(arg), indicies); + get_arg_indices_used_functioncall(ASR::down_cast(arg), indices); } else if (is_a(*arg)) { - get_arg_indices_used(ASR::down_cast(arg), indicies); + get_arg_indices_used(ASR::down_cast(arg), indices); + } else if (is_a(*arg)) { + get_arg_indices_used(ASR::down_cast(arg), indices); } else if (is_a(*arg)) { ASR::FunctionParam_t* param = ASR::down_cast(arg); ArgInfo info = {static_cast(param->m_param_number), param->m_type, current_function->m_args[param->m_param_number], arg}; - if (!exists_in_arginfo(param->m_param_number, indicies)) { - indicies.push_back(info); + if (!exists_in_arginfo(param->m_param_number, indices)) { + indices.push_back(info); } } else if (is_a(*arg)) { ASR::ArraySize_t* size = ASR::down_cast(arg); - helper_get_arg_indices_used(size->m_v, indicies); + helper_get_arg_indices_used(size->m_v, indices); } else if (is_a(*arg)) { ASR::IntegerCompare_t* comp = ASR::down_cast(arg); - helper_get_arg_indices_used(comp->m_left, indicies); - helper_get_arg_indices_used(comp->m_right, indicies); + helper_get_arg_indices_used(comp->m_left, indices); + helper_get_arg_indices_used(comp->m_right, indices); + } else if (is_a(*arg)) { + ASR::RealCompare_t* comp = ASR::down_cast(arg); + helper_get_arg_indices_used(comp->m_left, indices); + helper_get_arg_indices_used(comp->m_right, indices); + } else if (is_a(*arg)) { + ASR::RealBinOp_t* binop = ASR::down_cast(arg); + helper_get_arg_indices_used(binop->m_left, indices); + helper_get_arg_indices_used(binop->m_right, indices); + } else if (is_a(*arg)) { + ASR::IntegerBinOp_t* binop = ASR::down_cast(arg); + helper_get_arg_indices_used(binop->m_left, indices); + helper_get_arg_indices_used(binop->m_right, indices); + } else if (is_a(*arg)) { + ASR::RealUnaryMinus_t* r_minus = ASR::down_cast(arg); + helper_get_arg_indices_used(r_minus->m_arg, indices); + } else if (is_a(*arg)) { + ASR::IntegerUnaryMinus_t* i_minus = ASR::down_cast(arg); + helper_get_arg_indices_used(i_minus->m_arg, indices); + } else if (is_a(*arg)) { + int arg_num = -1; + int i = 0; + std::map func_scope = current_function->m_symtab->get_scope(); + for (auto sym: func_scope) { + if (sym.second == ASR::down_cast(arg)->m_v) { + arg_num = i; + break; + } + i++; + } + ArgInfo info = {static_cast(arg_num), ASRUtils::expr_type(arg), arg , arg}; + if (!exists_in_arginfo(arg_num, indices)) { + indices.push_back(info); + } } } - void get_arg_indices_used_functioncall(ASR::FunctionCall_t* x, std::vector& indicies) { + void get_arg_indices_used_functioncall(ASR::FunctionCall_t* x, std::vector& indices) { for (size_t i = 0; i < x->n_args; i++) { ASR::expr_t* arg = x->m_args[i].m_value; - helper_get_arg_indices_used(arg, indicies); + helper_get_arg_indices_used(arg, indices); } return; } template - void get_arg_indices_used(T* x, std::vector& indicies) { + void get_arg_indices_used(T* x, std::vector& indices) { for (size_t i = 0; i < x->n_args; i++) { ASR::expr_t* arg = x->m_args[i]; - helper_get_arg_indices_used(arg, indicies); + helper_get_arg_indices_used(arg, indices); } return; } @@ -136,34 +182,46 @@ class ReplaceFunctionCall : public ASR::BaseExprReplacer BaseExprReplacer::replace_IntrinsicArrayFunction(x); return ; } + std::vector indices; + get_arg_indices_used(x, indices); - std::vector indicies; - get_arg_indices_used(x, indicies); - - SymbolTable* global_scope = current_scope; - while (global_scope->parent) { - global_scope = global_scope->parent; - } + SymbolTable* global_scope = current_scope->get_global_scope(); SetChar current_function_dependencies; current_function_dependencies.clear(al); SymbolTable* new_scope = al.make_new(global_scope); + SymbolTable* new_function_scope_copy = new_function_scope; + new_function_scope = new_scope; ASRUtils::SymbolDuplicator sd(al); ASRUtils::ASRBuilder b(al, x->base.base.loc); - Vec new_args; new_args.reserve(al, indicies.size()); - Vec new_call_args; new_call_args.reserve(al, indicies.size()); - Vec args_for_return_var; args_for_return_var.reserve(al, indicies.size()); + Vec new_args; new_args.reserve(al, indices.size()); + Vec new_call_args; new_call_args.reserve(al, indices.size()); + Vec args_for_return_var; args_for_return_var.reserve(al, indices.size()); Vec new_body; new_body.reserve(al, 1); std::string new_function_name = global_scope->get_unique_name("__lcompilers_created_helper_function_", false); ASR::ttype_t* integer_type = ASRUtils::TYPE(ASR::make_Integer_t(al, x->base.base.loc, 4)); ASR::expr_t* return_var = b.Variable(new_scope, new_scope->get_unique_name("__lcompilers_return_var_", false), integer_type, ASR::intentType::ReturnVar); - for (auto arg: indicies) { + for (auto arg: indices) { ASR::expr_t* arg_expr = arg.arg_expr; if (is_a(*arg_expr)) { ASR::Var_t* var = ASR::down_cast(arg_expr); - sd.duplicate_symbol(var->m_v, new_scope); - ASR::expr_t* new_var_expr = ASRUtils::EXPR(ASR::make_Var_t(al, var->base.base.loc, new_scope->get_symbol(ASRUtils::symbol_name(var->m_v)))); + sd.duplicate_symbol(ASRUtils::symbol_get_past_external(var->m_v), new_scope); + ASR::symbol_t* new_sym = new_scope->get_symbol(ASRUtils::symbol_name(ASRUtils::symbol_get_past_external(var->m_v))); + if (ASRUtils::symbol_intent(new_sym) == ASR::intentType::Local) { + if (ASR::is_a(*new_sym)) { + ASR::Variable_t* temp_var = ASR::down_cast(new_sym); + ASR::symbol_t* updated_sym = ASR::down_cast( + ASRUtils::make_Variable_t_util(al, new_sym->base.loc, temp_var->m_parent_symtab, + temp_var->m_name, temp_var->m_dependencies, temp_var->n_dependencies, ASR::intentType::In, + nullptr, nullptr, ASR::storage_typeType::Default, temp_var->m_type, + temp_var->m_type_declaration, temp_var->m_abi, temp_var->m_access, + ASR::presenceType::Required, temp_var->m_value_attr, temp_var->m_target_attr)); + new_scope->add_or_overwrite_symbol(ASRUtils::symbol_name(new_sym), updated_sym); + new_sym = updated_sym; + } + } + ASR::expr_t* new_var_expr = ASRUtils::EXPR(ASR::make_Var_t(al, var->base.base.loc, new_sym)); new_args.push_back(al, new_var_expr); } ASR::call_arg_t new_call_arg; new_call_arg.loc = arg_expr->base.loc; new_call_arg.m_value = arg.arg_param; @@ -172,6 +230,7 @@ class ReplaceFunctionCall : public ASR::BaseExprReplacer ASR::call_arg_t arg_for_return_var; arg_for_return_var.loc = arg_expr->base.loc; arg_for_return_var.m_value = arg.arg_expr; args_for_return_var.push_back(al, arg_for_return_var); } + replace_FunctionParam_with_FunctionArgs(assignment_value, new_args); new_body.push_back(al, b.Assignment(return_var, assignment_value)); ASR::asr_t* new_function = ASRUtils::make_Function_t_util(al, current_function->base.base.loc, @@ -192,7 +251,8 @@ class ReplaceFunctionCall : public ASR::BaseExprReplacer new_call_args.p, new_call_args.n, integer_type, nullptr, - nullptr)); + nullptr, + false)); *current_expr = new_function_call; ASR::expr_t* function_call_for_return_var = ASRUtils::EXPR(ASRUtils::make_FunctionCall_t_util(al, x->base.base.loc, @@ -201,8 +261,10 @@ class ReplaceFunctionCall : public ASR::BaseExprReplacer args_for_return_var.p, args_for_return_var.n, integer_type, nullptr, - nullptr)); + nullptr, + false)); call_for_return_var = function_call_for_return_var; + new_function_scope = new_function_scope_copy; } }; @@ -264,6 +326,88 @@ class FunctionTypeVisitor : public ASR::CallReplacerOnExpressionsVisitorm_return_var)->m_type = return_type_copy; } + void visit_Array(const ASR::Array_t &x) { + if (!current_scope) return; + + if (is_function_call_or_intrinsic_array_function(x.m_dims->m_length)) { + ASR::expr_t** current_expr_copy = current_expr; + current_expr = const_cast(&(x.m_dims->m_length)); + this->call_replacer_(x.m_dims->m_length); + current_expr = current_expr_copy; + } + + ASR::CallReplacerOnExpressionsVisitor::visit_Array(x); + } + + void visit_IntegerBinOp(const ASR::IntegerBinOp_t &x) { + if (!current_scope) return; + + if (is_function_call_or_intrinsic_array_function(x.m_left)) { + ASR::expr_t** current_expr_copy = current_expr; + current_expr = const_cast(&(x.m_left)); + this->call_replacer_(x.m_left); + current_expr = current_expr_copy; + } + + if (is_function_call_or_intrinsic_array_function(x.m_right)) { + ASR::expr_t** current_expr_copy = current_expr; + current_expr = const_cast(&(x.m_right)); + this->call_replacer_(x.m_right); + current_expr = current_expr_copy; + } + + ASR::CallReplacerOnExpressionsVisitor::visit_IntegerBinOp(x); + } + + void visit_IntrinsicElementalFunction(const ASR::IntrinsicElementalFunction_t &x) { + if (!current_scope) return; + + for (size_t i = 0; i < x.n_args; i++) { + ASR::expr_t* arg = x.m_args[i]; + if (is_function_call_or_intrinsic_array_function(arg)) { + ASR::expr_t** current_expr_copy = current_expr; + current_expr = const_cast(&(x.m_args[i])); + this->call_replacer_(x.m_args[i]); + current_expr = current_expr_copy; + } + } + + ASR::CallReplacerOnExpressionsVisitor::visit_IntrinsicElementalFunction(x); + } + + void visit_RealBinOp(const ASR::RealBinOp_t &x) { + if (!current_scope) return; + + if (is_function_call_or_intrinsic_array_function(x.m_left)) { + ASR::expr_t** current_expr_copy = current_expr; + current_expr = const_cast(&(x.m_left)); + this->call_replacer_(x.m_left); + current_expr = current_expr_copy; + } + + if (is_function_call_or_intrinsic_array_function(x.m_right)) { + ASR::expr_t** current_expr_copy = current_expr; + current_expr = const_cast(&(x.m_right)); + this->call_replacer_(x.m_right); + current_expr = current_expr_copy; + } + + ASR::CallReplacerOnExpressionsVisitor::visit_RealBinOp(x); + } + + void visit_Cast(const ASR::Cast_t &x) { + if (!current_scope) return; + + if (is_function_call_or_intrinsic_array_function(x.m_arg)) { + ASR::expr_t** current_expr_copy = current_expr; + current_expr = const_cast(&(x.m_arg)); + this->call_replacer_(x.m_arg); + current_expr = current_expr_copy; + } + + ASR::CallReplacerOnExpressionsVisitor::visit_Cast(x); + } + void visit_FunctionType(const ASR::FunctionType_t &x) { if (!current_scope) return; @@ -337,7 +481,16 @@ class FunctionTypeVisitor : public ASR::CallReplacerOnExpressionsVisitorvisit_ttype(*x.m_function_signature); + for( auto sym: x.m_symtab->get_scope() ) { + if ( ASR::is_a(*sym.second) ) { + ASR::Variable_t* sym_variable = ASR::down_cast(sym.second); + this->visit_ttype(*sym_variable->m_type); + } + } current_scope = nullptr; + for( auto sym: x.m_symtab->get_scope() ) { + visit_symbol(*sym.second); + } } }; diff --git a/src/libasr/pass/global_stmts.cpp b/src/libasr/pass/global_stmts.cpp index 7fc1e8e6c4..257321d399 100644 --- a/src/libasr/pass/global_stmts.cpp +++ b/src/libasr/pass/global_stmts.cpp @@ -31,7 +31,7 @@ void pass_wrap_global_stmts(Allocator &al, char *fn_name = s.c_str(al); SymbolTable *fn_scope = al.make_new(unit.m_symtab); - ASR::ttype_t *type = nullptr; + ASR::ttype_t *type; Location loc = unit.base.base.loc; ASR::asr_t *return_var=nullptr; ASR::expr_t *return_var_ref=nullptr; @@ -45,19 +45,59 @@ void pass_wrap_global_stmts(Allocator &al, ASR::expr_t *target; ASR::expr_t *value = EXPR(unit.m_items[i]); // Create a new variable with the right type - if ((ASRUtils::expr_type(value)->type == ASR::ttypeType::Integer) || - (ASRUtils::expr_type(value)->type == ASR::ttypeType::UnsignedInteger) || - (ASRUtils::expr_type(value)->type == ASR::ttypeType::Logical) || - (ASRUtils::expr_type(value)->type == ASR::ttypeType::Real) || - (ASRUtils::expr_type(value)->type == ASR::ttypeType::Complex) || - (ASRUtils::expr_type(value)->type == ASR::ttypeType::Character) || - (ASRUtils::expr_type(value)->type == ASR::ttypeType::List) || - (ASRUtils::expr_type(value)->type == ASR::ttypeType::Tuple) || - (ASRUtils::expr_type(value)->type == ASR::ttypeType::StructType)) { + if (ASRUtils::expr_type(value)->type == ASR::ttypeType::Integer) { + s.from_str(al, fn_name_s + std::to_string(idx)); + var_name = s.c_str(al); + + int a_kind = down_cast(ASRUtils::expr_type(value))->m_kind; + + type = ASRUtils::TYPE(ASR::make_Integer_t(al, loc, a_kind)); + return_var = ASRUtils::make_Variable_t_util(al, loc, + fn_scope, var_name, nullptr, 0, ASRUtils::intent_local, nullptr, nullptr, + ASR::storage_typeType::Default, type, + nullptr, ASR::abiType::BindC, + ASR::Public, ASR::presenceType::Required, false); + return_var_ref = EXPR(ASR::make_Var_t(al, loc, + down_cast(return_var))); + fn_scope->add_symbol(std::string(var_name), down_cast(return_var)); + target = return_var_ref; + idx++; + } else if (ASRUtils::expr_type(value)->type == ASR::ttypeType::Logical) { + s.from_str(al, fn_name_s + std::to_string(idx)); + var_name = s.c_str(al); + + int a_kind = down_cast(ASRUtils::expr_type(value))->m_kind; + + type = ASRUtils::TYPE(ASR::make_Logical_t(al, loc, a_kind)); + return_var = ASRUtils::make_Variable_t_util(al, loc, + fn_scope, var_name, nullptr, 0, ASRUtils::intent_local, nullptr, nullptr, + ASR::storage_typeType::Default, type, + nullptr, ASR::abiType::BindC, + ASR::Public, ASR::presenceType::Required, false); + return_var_ref = EXPR(ASR::make_Var_t(al, loc, + down_cast(return_var))); + fn_scope->add_symbol(std::string(var_name), down_cast(return_var)); + target = return_var_ref; + idx++; + } else if (ASRUtils::expr_type(value)->type == ASR::ttypeType::Real) { + s.from_str(al, fn_name_s + std::to_string(idx)); + var_name = s.c_str(al); + type = ASRUtils::expr_type(value); + return_var = ASRUtils::make_Variable_t_util(al, loc, + fn_scope, var_name, nullptr, 0, ASRUtils::intent_local, nullptr, nullptr, + ASR::storage_typeType::Default, type, + nullptr, ASR::abiType::BindC, + ASR::Public, ASR::presenceType::Required, false); + return_var_ref = EXPR(ASR::make_Var_t(al, loc, + down_cast(return_var))); + fn_scope->add_symbol(std::string(var_name), down_cast(return_var)); + target = return_var_ref; + idx++; + } else if (ASRUtils::expr_type(value)->type == ASR::ttypeType::Complex) { s.from_str(al, fn_name_s + std::to_string(idx)); var_name = s.c_str(al); type = ASRUtils::expr_type(value); - return_var = ASR::make_Variable_t(al, loc, + return_var = ASRUtils::make_Variable_t_util(al, loc, fn_scope, var_name, nullptr, 0, ASRUtils::intent_local, nullptr, nullptr, ASR::storage_typeType::Default, type, nullptr, ASR::abiType::BindC, @@ -67,7 +107,7 @@ void pass_wrap_global_stmts(Allocator &al, fn_scope->add_symbol(std::string(var_name), down_cast(return_var)); target = return_var_ref; idx++; - } else { + } else { throw LCompilersException("Return type not supported in interactive mode"); } ASR::stmt_t* asr_stmt = ASRUtils::STMT(ASR::make_Assignment_t(al, loc, target, value, nullptr)); @@ -83,33 +123,7 @@ void pass_wrap_global_stmts(Allocator &al, if (return_var) { // The last defined `return_var` is the actual return value - LCOMPILERS_ASSERT(type) - LCOMPILERS_ASSERT(return_var_ref) - ASR::down_cast2(return_var)->m_intent = ASRUtils::intent_return_var; - std::string global_underscore_name = "_" + fn_name_s; - s.from_str(al, global_underscore_name); - - ASR::asr_t *global_underscore = ASR::make_Variable_t(al, loc, - unit.m_symtab, s.c_str(al), nullptr, 0, ASRUtils::intent_local, nullptr, nullptr, - ASR::storage_typeType::Default, type, - nullptr, ASR::abiType::Source, - ASR::Public, ASR::presenceType::Required, false); - ASR::expr_t * global_underscore_ref = EXPR(ASR::make_Var_t(al, loc, down_cast(global_underscore))); - - if (fn_scope->parent->get_symbol(global_underscore_name) != nullptr) { - throw LCompilersException("Global variable already defined"); - } - unit.m_symtab->add_symbol(global_underscore_name, down_cast(global_underscore)); - ASR::stmt_t* asr_stmt = ASRUtils::STMT(ASR::make_Assignment_t(al, loc, global_underscore_ref, return_var_ref, nullptr)); - body.push_back(al, asr_stmt); - - if ((ASRUtils::expr_type(return_var_ref)->type == ASR::ttypeType::List) || - (ASRUtils::expr_type(return_var_ref)->type == ASR::ttypeType::Tuple) || - (ASRUtils::expr_type(return_var_ref)->type == ASR::ttypeType::StructType)) { - return_var_ref = nullptr; - return_var = nullptr; - } } ASR::asr_t *fn = ASRUtils::make_Function_t_util( diff --git a/src/libasr/pass/implied_do_loops.cpp b/src/libasr/pass/implied_do_loops.cpp index f490105bd8..931b406fea 100644 --- a/src/libasr/pass/implied_do_loops.cpp +++ b/src/libasr/pass/implied_do_loops.cpp @@ -7,8 +7,6 @@ #include #include -#include -#include namespace LCompilers { @@ -35,9 +33,10 @@ class ReplaceArrayConstant: public ASR::BaseExprReplacer { bool realloc_lhs_, bool allocate_target_) : al(al_), pass_result(pass_result_), remove_original_statement(remove_original_statement_), - current_scope(nullptr), result_var(nullptr), result_counter(0), - resultvar2value(resultvar2value_), realloc_lhs(realloc_lhs_), - allocate_target(allocate_target_) {} + current_scope(nullptr), + result_var(nullptr), result_counter(0), + resultvar2value(resultvar2value_), + realloc_lhs(realloc_lhs_), allocate_target(allocate_target_) {} ASR::expr_t* get_ImpliedDoLoop_size(ASR::ImpliedDoLoop_t* implied_doloop) { const Location& loc = implied_doloop->base.base.loc; @@ -47,14 +46,13 @@ class ReplaceArrayConstant: public ASR::BaseExprReplacer { ASR::expr_t* d = implied_doloop->m_increment; ASR::expr_t* implied_doloop_size = nullptr; int kind = ASRUtils::extract_kind_from_ttype_t(ASRUtils::expr_type(end)); + start = builder.i2i_t(start, ASRUtils::expr_type(end)); if( d == nullptr ) { - implied_doloop_size = builder.ElementalAdd( - builder.ElementalSub(end, start, loc), - make_ConstantWithKind(make_IntegerConstant_t, make_Integer_t, 1, kind, loc), loc); + implied_doloop_size = ASRUtils::compute_length_from_start_end(al, start, end); } else { - implied_doloop_size = builder.ElementalAdd(builder.ElementalDiv( - builder.ElementalSub(end, start, loc), d, loc), - make_ConstantWithKind(make_IntegerConstant_t, make_Integer_t, 1, kind, loc), loc); + implied_doloop_size = builder.Add(builder.Div( + builder.Sub(end, start), d), + make_ConstantWithKind(make_IntegerConstant_t, make_Integer_t, 1, kind, loc)); } int const_elements = 0; ASR::expr_t* implied_doloop_size_ = nullptr; @@ -64,9 +62,9 @@ class ReplaceArrayConstant: public ASR::BaseExprReplacer { implied_doloop_size_ = get_ImpliedDoLoop_size( ASR::down_cast(implied_doloop->m_values[i])); } else { - implied_doloop_size_ = builder.ElementalAdd(get_ImpliedDoLoop_size( + implied_doloop_size_ = builder.Add(get_ImpliedDoLoop_size( ASR::down_cast(implied_doloop->m_values[i])), - implied_doloop_size_, loc); + implied_doloop_size_); } } else { const_elements += 1; @@ -77,20 +75,20 @@ class ReplaceArrayConstant: public ASR::BaseExprReplacer { implied_doloop_size_ = make_ConstantWithKind(make_IntegerConstant_t, make_Integer_t, const_elements, kind, loc); } else { - implied_doloop_size_ = builder.ElementalAdd( + implied_doloop_size_ = builder.Add( make_ConstantWithKind(make_IntegerConstant_t, make_Integer_t, const_elements, kind, loc), - implied_doloop_size_, loc); + implied_doloop_size_); } } if( implied_doloop_size_ ) { - implied_doloop_size = builder.ElementalMul(implied_doloop_size_, implied_doloop_size, loc); + implied_doloop_size = builder.Mul(implied_doloop_size_, implied_doloop_size); } return implied_doloop_size; } size_t get_constant_ArrayConstant_size(ASR::ArrayConstant_t* x) { - return x->n_args; + return ASRUtils::get_fixed_size_of_array(x->m_type); } ASR::expr_t* get_ArrayConstructor_size(ASR::ArrayConstructor_t* x, bool& is_allocatable) { @@ -111,8 +109,8 @@ class ReplaceArrayConstant: public ASR::BaseExprReplacer { if( array_size == nullptr ) { array_size = element_array_size; } else { - array_size = builder.ElementalAdd(array_size, - element_array_size, x->base.base.loc); + array_size = builder.Add(array_size, + element_array_size); } } } else if( ASR::is_a(*element) ) { @@ -121,8 +119,26 @@ class ReplaceArrayConstant: public ASR::BaseExprReplacer { if( array_size == nullptr ) { array_size = element_array_size; } else { - array_size = builder.ElementalAdd(array_size, - element_array_size, x->base.base.loc); + array_size = builder.Add(array_size, + element_array_size); + } + } else if ( ASR::is_a(*element) ) { + ASR::ArrayItem_t* array_item = ASR::down_cast(element); + if ( ASR::is_a(*array_item->m_type) ) { + if ( ASRUtils::is_fixed_size_array(array_item->m_type) ) { + ASR::Array_t* array_type = ASR::down_cast(array_item->m_type); + constant_size += ASRUtils::get_fixed_size_of_array(array_type->m_dims, array_type->n_dims); + } else { + ASR::expr_t* element_array_size = ASRUtils::get_size(element, al, false); + if( array_size == nullptr ) { + array_size = element_array_size; + } else { + array_size = builder.Add(array_size, + element_array_size); + } + } + } else { + constant_size += 1; } } else if( ASR::is_a(*element) ) { ASR::ttype_t* element_type = ASRUtils::type_get_past_allocatable( @@ -137,8 +153,8 @@ class ReplaceArrayConstant: public ASR::BaseExprReplacer { if( array_size == nullptr ) { array_size = element_array_size; } else { - array_size = builder.ElementalAdd(array_size, - element_array_size, x->base.base.loc); + array_size = builder.Add(array_size, + element_array_size); } } } else { @@ -148,7 +164,7 @@ class ReplaceArrayConstant: public ASR::BaseExprReplacer { ASR::expr_t* implied_doloop_size = get_ImpliedDoLoop_size( ASR::down_cast(element)); if( array_size ) { - array_size = builder.ElementalAdd(implied_doloop_size, array_size, loc); + array_size = builder.Add(implied_doloop_size, array_size); } else { array_size = implied_doloop_size; } @@ -162,19 +178,76 @@ class ReplaceArrayConstant: public ASR::BaseExprReplacer { if( d == nullptr ) { continue; } - ASR::expr_t* dim_size = builder.ElementalAdd(builder.ElementalDiv( - builder.ElementalSub(end, start, loc), d, loc), - make_ConstantWithKind(make_IntegerConstant_t, make_Integer_t, 1, 4, loc), loc); + ASR::expr_t* dim_size = builder.Add(builder.Div( + builder.Sub(end, start), d), + make_ConstantWithKind(make_IntegerConstant_t, make_Integer_t, 1, 4, loc)); if( array_section_size == nullptr ) { array_section_size = dim_size; } else { - array_section_size = builder.ElementalMul(array_section_size, dim_size, loc); + array_section_size = builder.Mul(array_section_size, dim_size); } } if( array_size == nullptr ) { array_size = array_section_size; } else { - builder.ElementalAdd(array_section_size, array_size, loc); + array_size = builder.Add(array_section_size, array_size); + } + } else if( ASR::is_a(*element) && + ASRUtils::is_array(ASRUtils::expr_type(element)) ) { + ASR::IntrinsicElementalFunction_t* intrinsic_element_t = ASR::down_cast(element); + if( ASRUtils::is_fixed_size_array(intrinsic_element_t->m_type) ) { + constant_size += ASRUtils::get_fixed_size_of_array(intrinsic_element_t->m_type); + } else { + ASR::expr_t* element_array_size = ASRUtils::get_size(element, al, false); + if( array_size == nullptr ) { + array_size = element_array_size; + } else { + array_size = builder.Add(array_size, + element_array_size); + } + } + } else if( ASR::is_a(*element) && + ASRUtils::is_array(ASRUtils::expr_type(element)) ) { + ASR::FunctionCall_t* fc_element_t = ASR::down_cast(element); + if( ASRUtils::is_fixed_size_array(fc_element_t->m_type) ) { + constant_size += ASRUtils::get_fixed_size_of_array(fc_element_t->m_type); + } else { + ASR::expr_t* element_array_size = ASRUtils::get_size(element, al, false); + if( array_size == nullptr ) { + array_size = element_array_size; + } else { + array_size = builder.Add(array_size, + element_array_size); + } + } + } else if( ASR::is_a(*element) && + ASRUtils::is_array(ASRUtils::expr_type(element)) ) { + ASR::IntrinsicArrayFunction_t* intrinsic_element_t = ASR::down_cast(element); + if( ASRUtils::is_fixed_size_array(intrinsic_element_t->m_type) ) { + constant_size += ASRUtils::get_fixed_size_of_array(intrinsic_element_t->m_type); + } else { + ASR::expr_t* element_array_size = ASRUtils::get_size(element, al, false); + if( array_size == nullptr ) { + array_size = element_array_size; + } else { + array_size = builder.Add(array_size, + element_array_size); + } + } + } else if( (ASR::is_a(*element) || ASR::is_a(*element) || + ASR::is_a(*element) || ASR::is_a(*element)) && + ASRUtils::is_array(ASRUtils::expr_type(element)) ) { + ASR::ttype_t* arr_type = ASRUtils::expr_type(element); + if( ASRUtils::is_fixed_size_array(arr_type) ) { + constant_size += ASRUtils::get_fixed_size_of_array(arr_type); + } else { + ASR::expr_t* element_array_size = ASRUtils::get_size(element, al, false); + if( array_size == nullptr ) { + array_size = element_array_size; + } else { + array_size = builder.Add(array_size, + element_array_size); + } } } else { constant_size += 1; @@ -192,7 +265,7 @@ class ReplaceArrayConstant: public ASR::BaseExprReplacer { } } if( constant_size_asr ) { - array_size = builder.ElementalAdd(array_size, constant_size_asr, x->base.base.loc); + array_size = builder.Add(array_size, constant_size_asr); } is_allocatable = true; if( array_size == nullptr ) { @@ -287,10 +360,18 @@ class ReplaceArrayConstant: public ASR::BaseExprReplacer { al, loc, alloc_args.p, alloc_args.size(), nullptr, nullptr, nullptr)); pass_result.push_back(al, allocate_stmt); } + for (size_t i = 0; i < x->n_args; i++) { + if(ASR::is_a(*x->m_args[i]) || ASR::is_a(*x->m_args[i])){ + ASR::expr_t** temp = current_expr; + current_expr = &(x->m_args[i]); + self().replace_expr(x->m_args[i]); + current_expr = temp; + } + } LCOMPILERS_ASSERT(result_var != nullptr); Vec* result_vec = &pass_result; - PassUtils::ReplacerUtils::replace_ArrayConstructor(x, this, - remove_original_statement, result_vec); + PassUtils::ReplacerUtils::replace_ArrayConstructor_(al, x, result_var, + result_vec, current_scope); result_var = result_var_copy; } @@ -322,7 +403,7 @@ class ReplaceArrayConstant: public ASR::BaseExprReplacer { is_allocatable = false; } else { if( is_allocatable ) { - result_type_ = ASRUtils::TYPE(ASR::make_Allocatable_t(al, x->m_type->base.loc, + result_type_ = ASRUtils::TYPE(ASRUtils::make_Allocatable_t_util(al, x->m_type->base.loc, ASRUtils::type_get_past_allocatable( ASRUtils::duplicate_type_with_empty_dims(al, x->m_type)))); } else { @@ -381,9 +462,16 @@ class ReplaceArrayConstant: public ASR::BaseExprReplacer { } void replace_ArrayPhysicalCast(ASR::ArrayPhysicalCast_t* x) { + [[maybe_unused]] bool is_arr_construct_arg = ASR::is_a(*x->m_arg); ASR::BaseExprReplacer::replace_ArrayPhysicalCast(x); - // TODO: Allow for DescriptorArray to DescriptorArray physical cast for allocatables - // later on + if( x->m_old != ASRUtils::extract_physical_type(ASRUtils::expr_type(x->m_arg)) ) { + x->m_old = ASRUtils::extract_physical_type(ASRUtils::expr_type(x->m_arg)); + } + if( (is_arr_construct_arg && ASRUtils::is_fixed_size_array(ASRUtils::expr_type(x->m_arg))) ){ + *current_expr = x->m_arg; + return; + } + if( (x->m_old == x->m_new && x->m_old != ASR::array_physical_typeType::DescriptorArray) || (x->m_old == x->m_new && x->m_old == ASR::array_physical_typeType::DescriptorArray && @@ -411,6 +499,8 @@ class ArrayConstantVisitor : public ASR::CallReplacerOnExpressionsVisitor pass_result; Vec* parent_body; @@ -423,8 +513,12 @@ class ArrayConstantVisitor : public ASR::CallReplacerOnExpressionsVisitor(&(x.m_value)); this->call_replacer(); + current_expr = const_cast(&(x.m_target)); + this->call_replacer(); current_expr = current_expr_copy_9; if( !remove_original_statement ) { this->visit_expr(*x.m_value); @@ -525,7 +621,45 @@ class ArrayConstantVisitor : public ASR::CallReplacerOnExpressionsVisitorbase.base.loc; do_loop_head.m_v = x->m_var; + do_loop_head.m_start = x->m_start; do_loop_head.m_end = x->m_end; + do_loop_head.m_increment = x->m_increment; + + Vec do_loop_body; do_loop_body.reserve(al, x->n_values); + for (size_t i = 0; i < x->n_values; i++ ) { + if ( ASR::is_a(*x->m_values[i]) ) { + do_loop_body.push_back(al, create_do_loop_form_idl( + ASR::down_cast(x->m_values[i]))); + } else { + Vec print_values; print_values.reserve(al, 1); + ASR::stmt_t* stmt = nullptr; + Vec args; + args.reserve(al, 1); + args.push_back(al, x->m_values[i]); + ASR::expr_t* fmt_val = ASRUtils::EXPR(ASR::make_StringFormat_t(al,x->base.base.loc, nullptr, + args.p, 1,ASR::string_format_kindType::FormatFortran, + ASRUtils::TYPE(ASR::make_String_t(al,x->base.base.loc,-1,-1,nullptr, ASR::string_physical_typeType::PointerString)), nullptr)); + print_values.push_back(al, fmt_val); + if ( print ) { + stmt = ASRUtils::STMT(ASRUtils::make_print_t_util(al, x->m_values[i]->base.loc, print_values.p, print_values.size())); + } else { + // this will be file_write + LCOMPILERS_ASSERT(file_write); + stmt = ASRUtils::STMT(ASR::make_FileWrite_t(al, x->m_values[i]->base.loc, 0, m_unit, nullptr, nullptr, nullptr, print_values.p, print_values.size(), nullptr, nullptr, nullptr)); + } + do_loop_body.push_back(al, stmt); + } + } + do_loop = ASRUtils::STMT(ASR::make_DoLoop_t(al, x->base.base.loc, nullptr, do_loop_head, do_loop_body.p, do_loop_body.size(), nullptr, 0)); + return do_loop; + } + void visit_Print(const ASR::Print_t &x) { + print = true; /* integer :: i print *, (i, i=1, 10) @@ -535,31 +669,18 @@ class ArrayConstantVisitor : public ASR::CallReplacerOnExpressionsVisitor(&x); - for(size_t i = 0; i < x.n_values; i++) { - ASR::expr_t* value = x.m_values[i]; - if (ASR::is_a(*value)) { - ASR::asr_t* array_constant = create_array_constant(x, value); - print_stmt->m_values[i] = ASRUtils::EXPR(array_constant); - - replacer.result_var = value; - resultvar2value[replacer.result_var] = ASRUtils::EXPR(array_constant); - ASR::expr_t** current_expr_copy_9 = current_expr; - current_expr = const_cast(&(print_stmt->m_values[i])); - this->call_replacer(); - current_expr = current_expr_copy_9; - if( !remove_original_statement ) { - this->visit_expr(*print_stmt->m_values[i]); - } - } else { - ASR::expr_t** current_expr_copy_9 = current_expr; - current_expr = const_cast(&(print_stmt->m_values[i])); - this->call_replacer(); - current_expr = current_expr_copy_9; - if( !remove_original_statement ) { - this->visit_expr(*print_stmt->m_values[i]); - } + if(ASR::is_a(*ASRUtils::expr_type(x.m_text))){ + ASR::Print_t* print_stmt = const_cast(&x); + ASR::expr_t** current_expr_copy_9 = current_expr; + current_expr = const_cast(&(print_stmt->m_text)); + this->call_replacer(); + current_expr = current_expr_copy_9; + if( !remove_original_statement ) { + this->visit_expr(*print_stmt->m_text); } + print = false; + } else { + LCOMPILERS_ASSERT_MSG(false, "print should support stringFormat or single string"); } } @@ -577,6 +698,12 @@ class ArrayConstantVisitor : public ASR::CallReplacerOnExpressionsVisitor(*value)) { + ASR::ImpliedDoLoop_t* implied_do_loop = ASR::down_cast(value); + if ( ASR::is_a(*implied_do_loop->m_type) ) { + remove_original_statement = true; + pass_result.push_back(al, create_do_loop_form_idl(implied_do_loop)); + continue; + } ASR::asr_t* array_constant = create_array_constant(x, value); string_format_stmt->m_args[i] = ASRUtils::EXPR(array_constant); @@ -610,9 +737,12 @@ class ArrayConstantVisitor : public ASR::CallReplacerOnExpressionsVisitorvisit_stmt(*x.m_overloaded); remove_original_statement = false; + file_write = false; return; } @@ -652,6 +782,7 @@ class ArrayConstantVisitor : public ASR::CallReplacerOnExpressionsVisitor #include -#include namespace LCompilers { @@ -59,13 +58,11 @@ class ReplaceInitExpr: public ASR::BaseExprReplacer { symtab2decls[current_scope] = result_vec_; } Vec* result_vec = &symtab2decls[current_scope]; - bool remove_original_statement = false; if( casted_type != nullptr ) { casted_type = ASRUtils::type_get_past_array(casted_type); } - PassUtils::ReplacerUtils::replace_ArrayConstructor(x, this, - remove_original_statement, result_vec, - perform_cast, cast_kind, casted_type); + PassUtils::ReplacerUtils::replace_ArrayConstructor_(al, x, result_var, result_vec, + current_scope, perform_cast, cast_kind, casted_type); *current_expr = nullptr; } @@ -186,7 +183,9 @@ class InitExprVisitor : public ASR::CallReplacerOnExpressionsVisitor(*symbolic_value))) || (ASR::is_a(*asr_owner) && (ASR::is_a(*symbolic_value) || - ASR::is_a(*symbolic_value)))) { + ASR::is_a(*symbolic_value))) || + (x.m_storage == ASR::storage_typeType::Save && + ASR::is_a(*ASR::down_cast(current_scope->asr_owner)))) { return ; } diff --git a/src/libasr/pass/inline_function_calls.cpp b/src/libasr/pass/inline_function_calls.cpp index 9ec9e8a93a..7a1872f3cc 100644 --- a/src/libasr/pass/inline_function_calls.cpp +++ b/src/libasr/pass/inline_function_calls.cpp @@ -207,6 +207,7 @@ class InlineFunctionCall : public ASR::BaseExprReplacer // Avoid inlining if function call accepts a callback argument for( size_t i = 0; i < x->n_args; i++ ) { if( x->m_args[i].m_value && + ASRUtils::expr_type(x->m_args[i].m_value) && ASR::is_a( *ASRUtils::type_get_past_pointer( ASRUtils::expr_type(x->m_args[i].m_value))) ) { @@ -243,7 +244,9 @@ class InlineFunctionCall : public ASR::BaseExprReplacer if( ASRUtils::is_intrinsic_function2(func) || std::string(func->m_name) == current_routine || // Never Inline BindC Function - ASRUtils::get_FunctionType(func)->m_abi == ASR::abiType::BindC) { + ASRUtils::get_FunctionType(func)->m_abi == ASR::abiType::BindC || + // Never Inline Interface Function + ASRUtils::get_FunctionType(func)->m_deftype == ASR::deftypeType::Interface) { return ; } @@ -314,7 +317,7 @@ class InlineFunctionCall : public ASR::BaseExprReplacer ASRUtils::is_character(*ASRUtils::symbol_type(itr.second)) || ASRUtils::is_array(ASRUtils::symbol_type(itr.second)) || ASR::is_a(*ASRUtils::symbol_type(itr.second)) || - ASR::is_a(*ASRUtils::symbol_type(itr.second)) ) { + ASR::is_a(*ASRUtils::symbol_type(itr.second)) ) { arg2value.clear(); return ; } @@ -335,7 +338,7 @@ class InlineFunctionCall : public ASR::BaseExprReplacer break; } ASR::ttype_t* local_var_type = func_var->m_type; - ASR::symbol_t* local_var = (ASR::symbol_t*) ASR::make_Variable_t( + ASR::symbol_t* local_var = (ASR::symbol_t*) ASRUtils::make_Variable_t_util( al, func_var->base.base.loc, current_scope, s2c(al, local_var_name), nullptr, 0, ASR::intentType::Local, nullptr, nullptr, ASR::storage_typeType::Default, @@ -525,7 +528,7 @@ class InlineFunctionCallVisitor : public ASR::CallReplacerOnExpressionsVisitor #include #include - -#include -#include +#include namespace LCompilers { @@ -16,43 +14,157 @@ class InsertDeallocate: public ASR::CallReplacerOnExpressionsVisitor implicitDeallocate_stmt_stack; // A stack to hold implicit_deallocate statement node due to nested visiting. - public: + void push_implicitDeallocate_into_stack(SymbolTable* symtab, Location &loc){ + Vec default_storage_variables_to_deallocate = get_allocatable_default_storage_variables(symtab); + if(default_storage_variables_to_deallocate.empty()){ + implicitDeallocate_stmt_stack.push(nullptr); + } else { + ASR::stmt_t* implicit_deallocation_node = ASRUtils::STMT(ASR::make_ImplicitDeallocate_t( + al, loc, default_storage_variables_to_deallocate.p, default_storage_variables_to_deallocate.size())); + implicitDeallocate_stmt_stack.push(implicit_deallocation_node); + } + } - InsertDeallocate(Allocator& al_) : al(al_) {} + inline bool is_deallocatable(ASR::symbol_t* s){ + if( ASR::is_a(*s) && + ASR::is_a(*ASRUtils::symbol_type(s)) && + (ASR::is_a(*ASRUtils::type_get_past_allocatable(ASRUtils::symbol_type(s))) || + ASRUtils::is_array(ASRUtils::symbol_type(s))) && + ASRUtils::symbol_intent(s) == ASRUtils::intent_local){ + return true; + } + return false; + } - template - void visit_Symbol(const T& x) { - Vec to_be_deallocated; - to_be_deallocated.reserve(al, 1); - for( auto& itr: x.m_symtab->get_scope() ) { - if( ASR::is_a(*itr.second) && - ASR::is_a(*ASRUtils::symbol_type(itr.second)) && - ASRUtils::is_array(ASRUtils::symbol_type(itr.second)) && - ASRUtils::symbol_intent(itr.second) == ASRUtils::intent_local ) { - to_be_deallocated.push_back(al, ASRUtils::EXPR( - ASR::make_Var_t(al, x.base.base.loc, itr.second))); + // Returns vector of default-storage `Var` expressions that're deallocatable. + Vec get_allocatable_default_storage_variables(SymbolTable* symtab){ + Vec allocatable_local_variables; + allocatable_local_variables.reserve(al, 1); + for(auto& itr: symtab->get_scope()) { + if( is_deallocatable(itr.second) && + ASRUtils::symbol_StorageType(itr.second) == ASR::storage_typeType::Default) { + allocatable_local_variables.push_back(al, ASRUtils::EXPR( + ASR::make_Var_t(al, itr.second->base.loc, itr.second))); } } - if( to_be_deallocated.size() > 0 ) { - T& xx = const_cast(x); - Vec body; - body.from_pointer_n_copy(al, xx.m_body, xx.n_body); - body.push_back(al, ASRUtils::STMT(ASR::make_ImplicitDeallocate_t( - al, x.base.base.loc, to_be_deallocated.p, to_be_deallocated.size()))); - xx.m_body = body.p; - xx.n_body = body.size(); + return allocatable_local_variables; + } + + Vec get_allocatable_save_storage_variables(SymbolTable* /*symtab*/){ + LCOMPILERS_ASSERT_MSG(false, "Not implemented"); + return Vec(); + } + + // Insert `ImplicitDeallocate` before construct terminating statements. + void visit_body_and_insert_ImplicitDeallocate(ASR::stmt_t** &m_body, size_t &n_body, + const std::vector &construct_terminating_stmts = {ASR::stmtType::Return}){ + if(implicitDeallocate_stmt_stack.top() == nullptr){ // No variables to deallocate. + return; + } + + Vec new_body; // Final body after inserting finalization nodes. + new_body.reserve(al, 1); + bool return_or_exit_encounterd = false; // No need to insert finaliztion node once we encounter a `return` or `exit` stmt in signle body (Unreachable code). + for(size_t i = 0; i < n_body; i++){ + for(ASR::stmtType statement_type : construct_terminating_stmts){ + if( !return_or_exit_encounterd && + (statement_type == m_body[i]->type)){ + new_body.push_back(al, implicitDeallocate_stmt_stack.top()); + } + } + if( ASR::is_a(*m_body[i]) || + ASR::is_a(*m_body[i])){ + return_or_exit_encounterd = true; // Next statements are 'Unreachable Code'. + } + if(!return_or_exit_encounterd){ + visit_stmt(*(m_body[i])); + } + new_body.push_back(al, m_body[i]); } + m_body = new_body.p; + n_body = new_body.size(); } + template + void insert_ImplicitDeallocate_at_end(T& x){ + LCOMPILERS_ASSERT_MSG( + x.class_type == ASR::symbolType::Program || + x.class_type == ASR::symbolType::Function || + x.class_type == ASR::symbolType::Block, "Only use with ASR::Program_t, Function_t or Block_t"); + if(implicitDeallocate_stmt_stack.top() == nullptr){ + return; + } + for(size_t i = 0; i < x.n_body; i++){ + if( ASR::is_a(*x.m_body[i]) || + ASR::is_a(*x.m_body[i])){ + return; // already handled, and no need to insert at end. + } + } + Vec new_body; + new_body.from_pointer_n_copy(al, x.m_body, x.n_body); + new_body.push_back(al, implicitDeallocate_stmt_stack.top()); + x.m_body = new_body.p; + x.n_body = new_body.size(); + } + + + + public: + + InsertDeallocate(Allocator& al_) : al(al_) {} + void visit_Function(const ASR::Function_t& x) { - visit_Symbol(x); - ASR::CallReplacerOnExpressionsVisitor::visit_Function(x); + ASR::Function_t &xx = const_cast(x); + push_implicitDeallocate_into_stack(xx.m_symtab, xx.base.base.loc); + for (auto &a : x.m_symtab->get_scope()) { + visit_symbol(*a.second); + } + visit_body_and_insert_ImplicitDeallocate(xx.m_body,xx.n_body); + insert_ImplicitDeallocate_at_end(xx); + implicitDeallocate_stmt_stack.pop(); } void visit_Program(const ASR::Program_t& x) { - visit_Symbol(x); - ASR::CallReplacerOnExpressionsVisitor::visit_Program(x); + ASR::Program_t &xx = const_cast(x); + push_implicitDeallocate_into_stack(xx.m_symtab, xx.base.base.loc); + + for (auto &a : x.m_symtab->get_scope()) { + visit_symbol(*a.second); + } + visit_body_and_insert_ImplicitDeallocate(xx.m_body, xx.n_body); + insert_ImplicitDeallocate_at_end(xx); + implicitDeallocate_stmt_stack.pop(); + } + + void visit_Block(const ASR::Block_t& x){ + ASR::Block_t& xx = const_cast(x); + push_implicitDeallocate_into_stack(xx.m_symtab, xx.base.base.loc); + for (auto &a : x.m_symtab->get_scope()) { + visit_symbol(*a.second); + } + visit_body_and_insert_ImplicitDeallocate(xx.m_body, xx.n_body,{ASR::stmtType::Return, ASR::stmtType::Exit}); + insert_ImplicitDeallocate_at_end(xx); + implicitDeallocate_stmt_stack.pop(); + } + + void visit_If(const ASR::If_t& x){ + ASR::If_t &xx = const_cast(x); + visit_body_and_insert_ImplicitDeallocate(xx.m_body, xx.n_body); + visit_body_and_insert_ImplicitDeallocate(xx.m_orelse, xx.n_orelse); + } + + void visit_WhileLoop(const ASR::WhileLoop_t &x){ + ASR::WhileLoop_t &xx = const_cast(x); + visit_body_and_insert_ImplicitDeallocate(xx.m_body, xx.n_body); + visit_body_and_insert_ImplicitDeallocate(xx.m_orelse, xx.n_orelse); + } + + void visit_DoLoop(const ASR::DoLoop_t &x){ + ASR::DoLoop_t &xx = const_cast(x); + visit_body_and_insert_ImplicitDeallocate(xx.m_body, xx.n_body); + visit_body_and_insert_ImplicitDeallocate(xx.m_orelse, xx.n_orelse); } }; diff --git a/src/libasr/pass/instantiate_template.cpp b/src/libasr/pass/instantiate_template.cpp index bae3d9235e..4af025910f 100644 --- a/src/libasr/pass/instantiate_template.cpp +++ b/src/libasr/pass/instantiate_template.cpp @@ -68,7 +68,7 @@ class SymbolRenamer : public ASR::BaseExprStmtDuplicator return current_scope->get_symbol(new_sym_name); } - ASR::symbol_t* new_v = ASR::down_cast(ASR::make_Variable_t( + ASR::symbol_t* new_v = ASR::down_cast(ASRUtils::make_Variable_t_util( al, x->base.base.loc, current_scope, s2c(al, new_sym_name), x->m_dependencies, x->n_dependencies, x->m_intent, x->m_symbolic_value, @@ -140,7 +140,7 @@ class SymbolRenamer : public ASR::BaseExprStmtDuplicator t = ASRUtils::duplicate_type(al, type_subs[tp->m_param]); } - ASR::symbol_t* new_v = ASR::down_cast(ASR::make_Variable_t( + ASR::symbol_t* new_v = ASR::down_cast(ASRUtils::make_Variable_t_util( al, x->base.base.loc, current_scope, x->m_name, x->m_dependencies, x->n_dependencies, x->m_intent, x->m_symbolic_value, x->m_value, x->m_storage, t, x->m_type_declaration, @@ -397,7 +397,7 @@ class SymbolInstantiator : public ASR::BaseExprStmtDuplicator(ASR::make_Variable_t(al, + ASR::symbol_t* s = ASR::down_cast(ASRUtils::make_Variable_t_util(al, x->base.base.loc, current_scope, s2c(al, x->m_name), variable_dependencies_vec.p, variable_dependencies_vec.size(), x->m_intent, nullptr, nullptr, x->m_storage, new_type, nullptr, x->m_abi, x->m_access, x->m_presence, x->m_value_attr)); @@ -474,12 +474,12 @@ class SymbolInstantiator : public ASR::BaseExprStmtDuplicator m_args; - m_args.reserve(al, x->n_args); - for (size_t i = 0; i < x->n_args; i++) { - m_args.push_back(al, self().duplicate_expr(x->m_args[i])); + m_args.reserve(al, ASRUtils::get_fixed_size_of_array(x->m_type)); + for (size_t i = 0; i < (size_t) ASRUtils::get_fixed_size_of_array(x->m_type); i++) { + m_args.push_back(al, self().duplicate_expr(ASRUtils::fetch_ArrayConstant_value(al, x, i))); } ASR::ttype_t* m_type = substitute_type(x->m_type); - return make_ArrayConstant_t(al, x->base.base.loc, m_args.p, x->n_args, m_type, x->m_storage_format); + return ASRUtils::make_ArrayConstructor_t_util(al, x->base.base.loc, m_args.p, ASRUtils::get_fixed_size_of_array(x->m_type), m_type, x->m_storage_format); } ASR::asr_t* duplicate_ArrayConstructor(ASR::ArrayConstructor_t *x) { @@ -587,7 +587,7 @@ class SymbolInstantiator : public ASR::BaseExprStmtDuplicatorbase.base.loc, name, x->m_original_name, - args.p, args.size(), type, value, dt); + args.p, args.size(), type, value, dt, false); } ASR::asr_t* duplicate_SubroutineCall(ASR::SubroutineCall_t *x) { @@ -667,10 +667,10 @@ class SymbolInstantiator : public ASR::BaseExprStmtDuplicatorbase.loc, tnew->m_kind)); break; } - case ASR::ttypeType::Character: { - ASR::Character_t* tnew = ASR::down_cast(t); - t = ASRUtils::TYPE(ASR::make_Character_t(al, t->base.loc, - tnew->m_kind, tnew->m_len, tnew->m_len_expr)); + case ASR::ttypeType::String: { + ASR::String_t* tnew = ASR::down_cast(t); + t = ASRUtils::TYPE(ASR::make_String_t(al, t->base.loc, + tnew->m_kind, tnew->m_len, tnew->m_len_expr, ASR::string_physical_typeType::PointerString)); break; } case ASR::ttypeType::Complex: { @@ -726,15 +726,15 @@ class SymbolInstantiator : public ASR::BaseExprStmtDuplicator(ttype); - return ASRUtils::TYPE(ASR::make_Allocatable_t(al, ttype->base.loc, + return ASRUtils::TYPE(ASRUtils::make_Allocatable_t_util(al, ttype->base.loc, substitute_type(a->m_type))); } - case (ASR::ttypeType::Class): { - ASR::Class_t *c = ASR::down_cast(ttype); + case (ASR::ttypeType::ClassType): { + ASR::ClassType_t *c = ASR::down_cast(ttype); std::string c_name = ASRUtils::symbol_name(c->m_class_type); if (context_map.find(c_name) != context_map.end()) { std::string new_c_name = context_map[c_name]; - return ASRUtils::TYPE(ASR::make_Class_t(al, + return ASRUtils::TYPE(ASR::make_ClassType_t(al, ttype->base.loc, func_scope->get_symbol(new_c_name))); } return ttype; @@ -849,10 +849,10 @@ void report_check_restriction(std::map type_subs, = ASR::down_cast(f_param); if (!ASRUtils::check_equal_type(type_subs[f_tp->m_param], arg_param)) { - std::string rtype = ASRUtils::type_to_str(type_subs[f_tp->m_param]); + std::string rtype = ASRUtils::type_to_str_fortran(type_subs[f_tp->m_param]); std::string rvar = ASRUtils::symbol_name( ASR::down_cast(f->m_args[i])->m_v); - std::string atype = ASRUtils::type_to_str(arg_param); + std::string atype = ASRUtils::type_to_str_fortran(arg_param); std::string avar = ASRUtils::symbol_name( ASR::down_cast(arg->m_args[i])->m_v); diagnostics.add(diag::Diagnostic( @@ -871,9 +871,12 @@ void report_check_restriction(std::map type_subs, } if (f->m_return_var) { if (!arg->m_return_var) { - std::string msg = "The restriction argument " + arg_name - + " should have a return value"; - throw SemanticError(msg, loc); + diagnostics.add(diag::Diagnostic( + "The restriction argument " + arg_name + + " should have a return value", + diag::Level::Error, diag::Stage::Semantic, { + diag::Label("", {loc})})); + throw SemanticAbort(); } ASR::ttype_t *f_ret = ASRUtils::expr_type(f->m_return_var); ASR::ttype_t *arg_ret = ASRUtils::expr_type(arg->m_return_var); @@ -881,8 +884,8 @@ void report_check_restriction(std::map type_subs, ASR::TypeParameter_t *return_tp = ASR::down_cast(f_ret); if (!ASRUtils::check_equal_type(type_subs[return_tp->m_param], arg_ret)) { - std::string rtype = ASRUtils::type_to_str(type_subs[return_tp->m_param]); - std::string atype = ASRUtils::type_to_str(arg_ret); + std::string rtype = ASRUtils::type_to_str_fortran(type_subs[return_tp->m_param]); + std::string atype = ASRUtils::type_to_str_fortran(arg_ret); diagnostics.add(diag::Diagnostic( "Restriction type mismatch with provided function argument", diag::Level::Error, diag::Stage::Semantic, { @@ -898,9 +901,12 @@ void report_check_restriction(std::map type_subs, } } else { if (arg->m_return_var) { - std::string msg = "The restriction argument " + arg_name - + " should not have a return value"; - throw SemanticError(msg, loc); + diagnostics.add(diag::Diagnostic( + "The restriction argument " + arg_name + + " should not have a return value", + diag::Level::Error, diag::Stage::Semantic, { + diag::Label("", {loc})})); + throw SemanticAbort(); } } symbol_subs[f_name] = sym_arg; @@ -969,7 +975,7 @@ class SymbolRenamer : public ASR::BaseExprStmtDuplicator return current_scope->get_symbol(new_sym_name); } - ASR::symbol_t* new_v = ASR::down_cast(ASR::make_Variable_t( + ASR::symbol_t* new_v = ASR::down_cast(ASRUtils::make_Variable_t_util( al, x->base.base.loc, current_scope, s2c(al, new_sym_name), x->m_dependencies, x->n_dependencies, x->m_intent, x->m_symbolic_value, @@ -1036,7 +1042,7 @@ class SymbolRenamer : public ASR::BaseExprStmtDuplicator ASR::symbol_t *v = current_scope->get_symbol(x->m_name); if (!v) { ASR::ttype_t *t = substitute_type(x->m_type); - v = ASR::down_cast(ASR::make_Variable_t( + v = ASR::down_cast(ASRUtils::make_Variable_t_util( al, x->base.base.loc, current_scope, x->m_name, x->m_dependencies, x->n_dependencies, x->m_intent, x->m_symbolic_value, x->m_value, x->m_storage, t, x->m_type_declaration, @@ -1211,7 +1217,7 @@ class SymbolInstantiator : public ASR::BaseExprStmtDuplicator(ASR::make_Variable_t(al, + ASR::symbol_t* s = ASR::down_cast(ASRUtils::make_Variable_t_util(al, x->base.base.loc, target_scope, s2c(al, x->m_name), variable_dependencies_vec.p, variable_dependencies_vec.size(), x->m_intent, nullptr, nullptr, x->m_storage, new_type, nullptr, x->m_abi, x->m_access, x->m_presence, x->m_value_attr)); @@ -1404,15 +1410,15 @@ class SymbolInstantiator : public ASR::BaseExprStmtDuplicator(ttype); - return ASRUtils::TYPE(ASR::make_Allocatable_t(al, ttype->base.loc, + return ASRUtils::TYPE(ASRUtils::make_Allocatable_t_util(al, ttype->base.loc, substitute_type(a->m_type))); } - case (ASR::ttypeType::Class) : { - ASR::Class_t *c = ASR::down_cast(ttype); + case (ASR::ttypeType::ClassType) : { + ASR::ClassType_t *c = ASR::down_cast(ttype); std::string class_name = ASRUtils::symbol_name(c->m_class_type); if (symbol_subs.find(class_name) != symbol_subs.end()) { ASR::symbol_t *new_c = symbol_subs[class_name]; - return ASRUtils::TYPE(ASR::make_Class_t(al, ttype->base.loc, new_c)); + return ASRUtils::TYPE(ASR::make_ClassType_t(al, ttype->base.loc, new_c)); } return ttype; } @@ -1615,7 +1621,7 @@ class BodyInstantiator : public ASR::BaseExprStmtDuplicator } return ASRUtils::make_FunctionCall_t_util(al, x->base.base.loc, name, - x->m_original_name, args.p, args.size(), type, value, dt); + x->m_original_name, args.p, args.size(), type, value, dt, false); } ASR::asr_t* duplicate_SubroutineCall(ASR::SubroutineCall_t* x) { @@ -1696,12 +1702,12 @@ class BodyInstantiator : public ASR::BaseExprStmtDuplicator ASR::asr_t* duplicate_ArrayConstant(ASR::ArrayConstant_t *x) { Vec m_args; - m_args.reserve(al, x->n_args); - for (size_t i = 0; i < x->n_args; i++) { - m_args.push_back(al, self().duplicate_expr(x->m_args[i])); + m_args.reserve(al,ASRUtils::get_fixed_size_of_array(x->m_type)); + for (size_t i = 0; i < (size_t) ASRUtils::get_fixed_size_of_array(x->m_type); i++) { + m_args.push_back(al, self().duplicate_expr(ASRUtils::fetch_ArrayConstant_value(al, x, i))); } ASR::ttype_t* m_type = substitute_type(x->m_type); - return make_ArrayConstant_t(al, x->base.base.loc, m_args.p, x->n_args, m_type, x->m_storage_format); + return ASRUtils::make_ArrayConstructor_t_util(al, x->base.base.loc, m_args.p, ASRUtils::get_fixed_size_of_array(x->m_type), m_type, x->m_storage_format); } ASR::asr_t* duplicate_ArrayPhysicalCast(ASR::ArrayPhysicalCast_t *x) { @@ -1824,15 +1830,15 @@ class BodyInstantiator : public ASR::BaseExprStmtDuplicator } case (ASR::ttypeType::Allocatable): { ASR::Allocatable_t *a = ASR::down_cast(ttype); - return ASRUtils::TYPE(ASR::make_Allocatable_t(al, ttype->base.loc, + return ASRUtils::TYPE(ASRUtils::make_Allocatable_t_util(al, ttype->base.loc, substitute_type(a->m_type))); } - case (ASR::ttypeType::Class) : { - ASR::Class_t *c = ASR::down_cast(ttype); + case (ASR::ttypeType::ClassType) : { + ASR::ClassType_t *c = ASR::down_cast(ttype); std::string class_name = ASRUtils::symbol_name(c->m_class_type); if (symbol_subs.find(class_name) != symbol_subs.end()) { ASR::symbol_t *new_c = symbol_subs[class_name]; - return ASRUtils::TYPE(ASR::make_Class_t(al, ttype->base.loc, new_c)); + return ASRUtils::TYPE(ASR::make_ClassType_t(al, ttype->base.loc, new_c)); } return ttype; } @@ -1900,7 +1906,7 @@ bool check_restriction(std::map type_subs, std::string rtype = ASRUtils::type_to_str_with_substitution(f_param, type_subs); std::string rvar = ASRUtils::symbol_name( ASR::down_cast(f->m_args[i])->m_v); - std::string atype = ASRUtils::type_to_str(arg_param); + std::string atype = ASRUtils::type_to_str_fortran(arg_param); std::string avar = ASRUtils::symbol_name( ASR::down_cast(arg->m_args[i])->m_v); diagnostics.add(diag::Diagnostic( @@ -1934,7 +1940,7 @@ bool check_restriction(std::map type_subs, if (!ASRUtils::types_equal_with_substitution(f_ret, arg_ret, type_subs)) { if (report) { std::string rtype = ASRUtils::type_to_str_with_substitution(f_ret, type_subs); - std::string atype = ASRUtils::type_to_str(arg_ret); + std::string atype = ASRUtils::type_to_str_fortran(arg_ret); diagnostics.add(diag::Diagnostic( "Restriction type mismatch with provided function argument", diag::Level::Error, diag::Stage::Semantic, { diff --git a/src/libasr/pass/intrinsic_array_function_registry.h b/src/libasr/pass/intrinsic_array_function_registry.h index d4ccba7231..c4cc34640e 100644 --- a/src/libasr/pass/intrinsic_array_function_registry.h +++ b/src/libasr/pass/intrinsic_array_function_registry.h @@ -16,23 +16,33 @@ namespace LCompilers { namespace ASRUtils { + /************************* Intrinsic Array Functions **************************/ enum class IntrinsicArrayFunctions : int64_t { Any, + All, + Iany, + Iall, + Norm2, MatMul, MaxLoc, MaxVal, - Merge, MinLoc, MinVal, + FindLoc, Product, Shape, Sum, + Iparity, Transpose, Pack, Unpack, Count, + Parity, DotProduct, + Cshift, + Eoshift, + Spread, // ... }; @@ -41,23 +51,32 @@ enum class IntrinsicArrayFunctions : int64_t { return #X; \ } -inline std::string get_array_intrinsic_name(int x) { +inline std::string get_array_intrinsic_name(int64_t x) { switch (x) { ARRAY_INTRINSIC_NAME_CASE(Any) + ARRAY_INTRINSIC_NAME_CASE(All) + ARRAY_INTRINSIC_NAME_CASE(Iany) + ARRAY_INTRINSIC_NAME_CASE(Iall) + ARRAY_INTRINSIC_NAME_CASE(Norm2) ARRAY_INTRINSIC_NAME_CASE(MatMul) ARRAY_INTRINSIC_NAME_CASE(MaxLoc) ARRAY_INTRINSIC_NAME_CASE(MaxVal) - ARRAY_INTRINSIC_NAME_CASE(Merge) ARRAY_INTRINSIC_NAME_CASE(MinLoc) ARRAY_INTRINSIC_NAME_CASE(MinVal) + ARRAY_INTRINSIC_NAME_CASE(FindLoc) ARRAY_INTRINSIC_NAME_CASE(Product) ARRAY_INTRINSIC_NAME_CASE(Shape) ARRAY_INTRINSIC_NAME_CASE(Sum) + ARRAY_INTRINSIC_NAME_CASE(Iparity) ARRAY_INTRINSIC_NAME_CASE(Transpose) ARRAY_INTRINSIC_NAME_CASE(Pack) ARRAY_INTRINSIC_NAME_CASE(Unpack) ARRAY_INTRINSIC_NAME_CASE(Count) + ARRAY_INTRINSIC_NAME_CASE(Parity) ARRAY_INTRINSIC_NAME_CASE(DotProduct) + ARRAY_INTRINSIC_NAME_CASE(Cshift) + ARRAY_INTRINSIC_NAME_CASE(Eoshift) + ARRAY_INTRINSIC_NAME_CASE(Spread) default : { throw LCompilersException("pickle: intrinsic_id not implemented"); } @@ -65,7 +84,7 @@ inline std::string get_array_intrinsic_name(int x) { } typedef ASR::expr_t* (ASRBuilder::*elemental_operation_func)(ASR::expr_t*, - ASR::expr_t*, const Location&, ASR::expr_t*); + ASR::expr_t*); typedef void (*verify_array_func)(ASR::expr_t*, ASR::ttype_t*, const Location&, diag::Diagnostics&, @@ -75,185 +94,11 @@ typedef void (*verify_array_function)( const ASR::IntrinsicArrayFunction_t&, diag::Diagnostics&); -namespace Merge { - - static inline void verify_args(const ASR::IntrinsicArrayFunction_t& x, - diag::Diagnostics& diagnostics) { - const Location& loc = x.base.base.loc; - ASR::expr_t *tsource = x.m_args[0], *fsource = x.m_args[1], *mask = x.m_args[2]; - ASR::ttype_t *tsource_type = ASRUtils::expr_type(tsource); - ASR::ttype_t *fsource_type = ASRUtils::expr_type(fsource); - ASR::ttype_t *mask_type = ASRUtils::expr_type(mask); - int tsource_ndims, fsource_ndims; - ASR::dimension_t *tsource_mdims = nullptr, *fsource_mdims = nullptr; - tsource_ndims = ASRUtils::extract_dimensions_from_ttype(tsource_type, tsource_mdims); - fsource_ndims = ASRUtils::extract_dimensions_from_ttype(fsource_type, fsource_mdims); - if( tsource_ndims > 0 && fsource_ndims > 0 ) { - ASRUtils::require_impl(tsource_ndims == fsource_ndims, - "All arguments of `merge` should be of same rank and dimensions", loc, diagnostics); - - if( ASRUtils::extract_physical_type(tsource_type) == ASR::array_physical_typeType::FixedSizeArray && - ASRUtils::extract_physical_type(fsource_type) == ASR::array_physical_typeType::FixedSizeArray ) { - ASRUtils::require_impl(ASRUtils::get_fixed_size_of_array(tsource_mdims, tsource_ndims) == - ASRUtils::get_fixed_size_of_array(fsource_mdims, fsource_ndims), - "`tsource` and `fsource` arguments should have matching size", loc, diagnostics); - } - } - - ASRUtils::require_impl(ASRUtils::check_equal_type(tsource_type, fsource_type), - "`tsource` and `fsource` arguments to `merge` should be of same type, found " + - ASRUtils::get_type_code(tsource_type) + ", " + - ASRUtils::get_type_code(fsource_type), loc, diagnostics); - ASRUtils::require_impl(ASRUtils::is_logical(*mask_type), - "`mask` argument to `merge` should be of logical type, found " + - ASRUtils::get_type_code(mask_type), loc, diagnostics); - } - - static inline ASR::expr_t* eval_Merge( - Allocator &/*al*/, const Location &/*loc*/, ASR::ttype_t *, - Vec& args, diag::Diagnostics& /*diag*/) { - LCOMPILERS_ASSERT(args.size() == 3); - ASR::expr_t *tsource = args[0], *fsource = args[1], *mask = args[2]; - if( ASRUtils::is_array(ASRUtils::expr_type(mask)) ) { - return nullptr; - } - - bool mask_value = false; - if( ASRUtils::is_value_constant(mask, mask_value) ) { - if( mask_value ) { - return tsource; - } else { - return fsource; - } - } - return nullptr; - } - - static inline ASR::asr_t* create_Merge(Allocator& al, const Location& loc, - Vec& args, - diag::Diagnostics& diag) { - if( args.size() != 3 ) { - append_error(diag, "`merge` intrinsic accepts 3 positional arguments, found " + - std::to_string(args.size()), loc); - return nullptr; - } - - ASR::expr_t *tsource = args[0], *fsource = args[1], *mask = args[2]; - ASR::ttype_t *tsource_type = ASRUtils::expr_type(tsource); - ASR::ttype_t *fsource_type = ASRUtils::expr_type(fsource); - ASR::ttype_t *mask_type = ASRUtils::expr_type(mask); - ASR::ttype_t* result_type = tsource_type; - int tsource_ndims, fsource_ndims, mask_ndims; - ASR::dimension_t *tsource_mdims = nullptr, *fsource_mdims = nullptr, *mask_mdims = nullptr; - tsource_ndims = ASRUtils::extract_dimensions_from_ttype(tsource_type, tsource_mdims); - fsource_ndims = ASRUtils::extract_dimensions_from_ttype(fsource_type, fsource_mdims); - mask_ndims = ASRUtils::extract_dimensions_from_ttype(mask_type, mask_mdims); - if( tsource_ndims > 0 && fsource_ndims > 0 ) { - if( tsource_ndims != fsource_ndims ) { - append_error(diag, "All arguments of `merge` should be of same rank and dimensions", loc); - return nullptr; - } - - if( ASRUtils::extract_physical_type(tsource_type) == ASR::array_physical_typeType::FixedSizeArray && - ASRUtils::extract_physical_type(fsource_type) == ASR::array_physical_typeType::FixedSizeArray && - ASRUtils::get_fixed_size_of_array(tsource_mdims, tsource_ndims) != - ASRUtils::get_fixed_size_of_array(fsource_mdims, fsource_ndims) ) { - append_error(diag, "`tsource` and `fsource` arguments should have matching size", loc); - return nullptr; - } - } else { - if( tsource_ndims > 0 && fsource_ndims == 0 ) { - result_type = tsource_type; - } else if( tsource_ndims == 0 && fsource_ndims > 0 ) { - result_type = fsource_type; - } else if( tsource_ndims == 0 && fsource_ndims == 0 && mask_ndims > 0 ) { - Vec mask_mdims_vec; - mask_mdims_vec.from_pointer_n(mask_mdims, mask_ndims); - result_type = ASRUtils::duplicate_type(al, tsource_type, &mask_mdims_vec, - ASRUtils::extract_physical_type(mask_type), true); - if( ASR::is_a(*mask_type) ) { - result_type = ASRUtils::TYPE(ASR::make_Allocatable_t(al, loc, result_type)); - } - } - } - if( !ASRUtils::check_equal_type(tsource_type, fsource_type) ) { - append_error(diag, "`tsource` and `fsource` arguments to `merge` should be of same type, found " + - ASRUtils::get_type_code(tsource_type) + ", " + - ASRUtils::get_type_code(fsource_type), loc); - return nullptr; - } - if( !ASRUtils::is_logical(*mask_type) ) { - append_error(diag, "`mask` argument to `merge` should be of logical type, found " + - ASRUtils::get_type_code(mask_type), loc); - return nullptr; - } - - return ASR::make_IntrinsicArrayFunction_t(al, loc, - static_cast(ASRUtils::IntrinsicArrayFunctions::Merge), - args.p, args.size(), 0, result_type, nullptr); - } - - static inline ASR::expr_t* instantiate_Merge(Allocator &al, - const Location &loc, SymbolTable *scope, - Vec& arg_types, ASR::ttype_t *return_type, - Vec& new_args, int64_t /*overload_id*/) { - LCOMPILERS_ASSERT(arg_types.size() == 3); - - // Array inputs should be elementalised in array_op pass already - LCOMPILERS_ASSERT( !ASRUtils::is_array(arg_types[2]) ); - ASR::ttype_t *tsource_type = ASRUtils::duplicate_type(al, arg_types[0]); - ASR::ttype_t *fsource_type = ASRUtils::duplicate_type(al, arg_types[1]); - ASR::ttype_t *mask_type = ASRUtils::duplicate_type(al, arg_types[2]); - if( ASR::is_a(*tsource_type) ) { - ASR::Character_t* tsource_char = ASR::down_cast(tsource_type); - ASR::Character_t* fsource_char = ASR::down_cast(fsource_type); - tsource_char->m_len_expr = nullptr; fsource_char->m_len_expr = nullptr; - tsource_char->m_len = -2; fsource_char->m_len = -2; - ASR::Character_t* return_char = ASR::down_cast( - ASRUtils::type_get_past_allocatable(return_type)); - return_char->m_len = -2; return_char->m_len_expr = nullptr; - - } - std::string new_name = "_lcompilers_merge_" + get_type_code(tsource_type); - - declare_basic_variables(new_name); - if (scope->get_symbol(new_name)) { - ASR::symbol_t *s = scope->get_symbol(new_name); - ASR::Function_t *f = ASR::down_cast(s); - return b.Call(s, new_args, expr_type(f->m_return_var), nullptr); - } - - auto tsource_arg = declare("tsource", tsource_type, In); - args.push_back(al, tsource_arg); - auto fsource_arg = declare("fsource", fsource_type, In); - args.push_back(al, fsource_arg); - auto mask_arg = declare("mask", mask_type, In); - args.push_back(al, mask_arg); - // TODO: In case of Character type, set len of ReturnVar to len(tsource) expression - auto result = declare("merge", type_get_past_allocatable(return_type), ReturnVar); - - { - Vec if_body; if_body.reserve(al, 1); - if_body.push_back(al, b.Assignment(result, tsource_arg)); - Vec else_body; else_body.reserve(al, 1); - else_body.push_back(al, b.Assignment(result, fsource_arg)); - body.push_back(al, STMT(ASR::make_If_t(al, loc, mask_arg, - if_body.p, if_body.n, else_body.p, else_body.n))); - } - - ASR::symbol_t *new_symbol = make_ASR_Function_t(fn_name, fn_symtab, dep, args, - body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); - scope->add_symbol(fn_name, new_symbol); - return b.Call(new_symbol, new_args, return_type, nullptr); - } - -} // namespace Merge - namespace ArrIntrinsic { static inline void verify_array_int_real_cmplx(ASR::expr_t* array, ASR::ttype_t* return_type, const Location& loc, diag::Diagnostics& diagnostics, ASRUtils::IntrinsicArrayFunctions intrinsic_func_id) { - std::string intrinsic_func_name = ASRUtils::get_array_intrinsic_name(static_cast(intrinsic_func_id)); + std::string intrinsic_func_name = ASRUtils::get_array_intrinsic_name(static_cast(intrinsic_func_id)); ASR::ttype_t* array_type = ASRUtils::expr_type(array); ASRUtils::require_impl(ASRUtils::is_integer(*array_type) || ASRUtils::is_real(*array_type) || @@ -274,7 +119,7 @@ static inline void verify_array_int_real_cmplx(ASR::expr_t* array, ASR::ttype_t* static inline void verify_array_int_real(ASR::expr_t* array, ASR::ttype_t* return_type, const Location& loc, diag::Diagnostics& diagnostics, ASRUtils::IntrinsicArrayFunctions intrinsic_func_id) { - std::string intrinsic_func_name = ASRUtils::get_array_intrinsic_name(static_cast(intrinsic_func_id)); + std::string intrinsic_func_name = ASRUtils::get_array_intrinsic_name(static_cast(intrinsic_func_id)); ASR::ttype_t* array_type = ASRUtils::expr_type(array); ASRUtils::require_impl(ASRUtils::is_integer(*array_type) || ASRUtils::is_real(*array_type), @@ -294,19 +139,18 @@ static inline void verify_array_int_real(ASR::expr_t* array, ASR::ttype_t* retur static inline void verify_array_dim(ASR::expr_t* array, ASR::expr_t* dim, ASR::ttype_t* return_type, const Location& loc, diag::Diagnostics& diagnostics, ASRUtils::IntrinsicArrayFunctions intrinsic_func_id) { - std::string intrinsic_func_name = ASRUtils::get_array_intrinsic_name(static_cast(intrinsic_func_id)); + std::string intrinsic_func_name = ASRUtils::get_array_intrinsic_name(static_cast(intrinsic_func_id)); ASR::ttype_t* array_type = ASRUtils::expr_type(array); ASRUtils::require_impl(ASRUtils::is_integer(*array_type) || - ASRUtils::is_real(*array_type) || - ASRUtils::is_complex(*array_type), - "Input to " + intrinsic_func_name + " intrinsic must be of integer, real or complex type, found: " + - ASRUtils::get_type_code(array_type), loc, diagnostics); + ASRUtils::is_real(*array_type) || ASRUtils::is_complex(*array_type), + "Input to `" + intrinsic_func_name + "` intrinsic must be of integer, real or complex type, found: " + + ASRUtils::get_type_code(array_type), loc, diagnostics); int array_n_dims = ASRUtils::extract_n_dims_from_ttype(array_type); - ASRUtils::require_impl(array_n_dims > 0, "Input to " + intrinsic_func_name + " intrinsic must always be an array", + ASRUtils::require_impl(array_n_dims > 0, "Input to `" + intrinsic_func_name + "` intrinsic must always be an array", loc, diagnostics); ASRUtils::require_impl(ASRUtils::is_integer(*ASRUtils::expr_type(dim)), - "dim argument must be an integer", loc, diagnostics); + "`dim` argument must be an integer", loc, diagnostics); ASRUtils::require_impl(ASRUtils::check_equal_type( return_type, array_type, false), @@ -320,31 +164,30 @@ static inline void verify_array_dim(ASR::expr_t* array, ASR::expr_t* dim, static inline void verify_args(const ASR::IntrinsicArrayFunction_t& x, diag::Diagnostics& diagnostics, ASRUtils::IntrinsicArrayFunctions intrinsic_func_id, verify_array_func verify_array) { - std::string intrinsic_func_name = ASRUtils::get_array_intrinsic_name(static_cast(intrinsic_func_id)); + std::string intrinsic_func_name = ASRUtils::get_array_intrinsic_name(static_cast(intrinsic_func_id)); ASRUtils::require_impl(x.n_args >= 1, intrinsic_func_name + " intrinsic must accept at least one argument", x.base.base.loc, diagnostics); - ASRUtils::require_impl(x.m_args[0] != nullptr, "Array argument to " + intrinsic_func_name + " intrinsic cannot be nullptr", + ASRUtils::require_impl(x.m_args[0] != nullptr, "`array` argument to `" + intrinsic_func_name + "` intrinsic cannot be nullptr", x.base.base.loc, diagnostics); - const int64_t id_array = 0, id_array_dim = 1, id_array_mask = 2; - const int64_t id_array_dim_mask = 3; + const int64_t id_array = 0, id_array_dim = 1, id_array_mask = 2, id_array_dim_mask = 3; switch( x.m_overload_id ) { - case id_array: + case id_array: { + break; + } case id_array_mask: { - if( x.m_overload_id == id_array_mask ) { - ASRUtils::require_impl(x.n_args == 2 && x.m_args[1] != nullptr, - "mask argument cannot be nullptr", x.base.base.loc, diagnostics); - } + ASRUtils::require_impl(x.n_args == 2 && x.m_args[1] != nullptr, + "`mask` argument cannot be nullptr", x.base.base.loc, diagnostics); verify_array(x.m_args[0], x.m_type, x.base.base.loc, diagnostics, intrinsic_func_id); break; } - case id_array_dim: + case id_array_dim: { + break; + } case id_array_dim_mask: { - if( x.m_overload_id == id_array_dim_mask ) { - ASRUtils::require_impl(x.n_args == 3 && x.m_args[2] != nullptr, - "mask argument cannot be nullptr", x.base.base.loc, diagnostics); - } + ASRUtils::require_impl(x.n_args == 3 && x.m_args[2] != nullptr, + "`mask` argument cannot be nullptr", x.base.base.loc, diagnostics); ASRUtils::require_impl(x.n_args >= 2 && x.m_args[1] != nullptr, - "dim argument to any intrinsic cannot be nullptr", + "`dim` argument to any intrinsic cannot be nullptr", x.base.base.loc, diagnostics); verify_array_dim(x.m_args[0], x.m_args[1], x.m_type, x.base.base.loc, diagnostics, intrinsic_func_id); break; @@ -354,8 +197,7 @@ static inline void verify_args(const ASR::IntrinsicArrayFunction_t& x, diag::Dia x.base.base.loc, diagnostics); } } - if( x.m_overload_id == id_array_mask || - x.m_overload_id == id_array_dim_mask ) { + if( x.m_overload_id == id_array_mask || x.m_overload_id == id_array_dim_mask ) { ASR::expr_t* mask = nullptr; if( x.m_overload_id == id_array_mask ) { mask = x.m_args[1]; @@ -367,128 +209,560 @@ static inline void verify_args(const ASR::IntrinsicArrayFunction_t& x, diag::Dia ASR::ttype_t* mask_type = ASRUtils::expr_type(mask); size_t array_n_dims = ASRUtils::extract_dimensions_from_ttype(array_type, array_dims); size_t mask_n_dims = ASRUtils::extract_dimensions_from_ttype(mask_type, mask_dims); - ASRUtils::require_impl(ASRUtils::dimensions_equal(array_dims, array_n_dims, mask_dims, mask_n_dims), - "The dimensions of array and mask arguments of " + intrinsic_func_name + " intrinsic must be same", - x.base.base.loc, diagnostics); + if (mask_n_dims != 0) { + ASRUtils::require_impl(ASRUtils::dimensions_compatible(array_dims, array_n_dims, mask_dims, mask_n_dims), + "The dimensions of `array` and `mask` arguments of `" + intrinsic_func_name + "` intrinsic must be same", + x.base.base.loc, diagnostics); + } } } -static inline ASR::expr_t *eval_ArrIntrinsic(Allocator & /*al*/, - const Location & /*loc*/, ASR::ttype_t *, Vec& /*args*/, - diag::Diagnostics& /*diag*/) { - return nullptr; +template +T find_sum(size_t size, T* data, bool* mask = nullptr) { + T result = 0; + if (mask) { + for (size_t i = 0; i < size; i++) { + if (mask[i]) { + result += data[i]; + } + } + } else { + for (size_t i = 0; i < size; i++) { + result += data[i]; + } + } + return result; } -static inline ASR::asr_t* create_ArrIntrinsic( - Allocator& al, const Location& loc, Vec& args, - diag::Diagnostics& diag, - ASRUtils::IntrinsicArrayFunctions intrinsic_func_id) { - std::string intrinsic_func_name = ASRUtils::get_array_intrinsic_name(static_cast(intrinsic_func_id)); - int64_t id_array = 0, id_array_dim = 1, id_array_mask = 2; - int64_t id_array_dim_mask = 3; - int64_t overload_id = id_array; +template +T find_product(size_t size, T* data, bool* mask = nullptr) { + T result = 1; + if (mask) { + for (size_t i = 0; i < size; i++) { + if (mask[i]) { + result *= data[i]; + } + } + } else { + for (size_t i = 0; i < size; i++) { + result *= data[i]; + } + } + return result; +} + +template +T find_iparity(size_t size, T* data, bool* mask = nullptr) { + T result = 0; + if (mask) { + for (size_t i = 0; i < size; i++) { + if (mask[i]) { + result ^= data[i]; + } + } + } else { + for (size_t i = 0; i < size; i++) { + result ^= data[i]; + } + } + return result; +} + +template +T find_minval(size_t size, T* data, bool* mask = nullptr) { + T result = std::numeric_limits::max(); + if (mask) { + for (size_t i = 0; i < size; i++) { + if (mask[i] && data[i] < result) { + result = data[i]; + } + } + } else { + for (size_t i = 0; i < size; i++) { + if (data[i] < result) { + result = data[i]; + } + } + } + return result; +} + +template +T find_maxval(size_t size, T* data, bool* mask = nullptr) { + T result = std::numeric_limits::min(); + if (mask) { + for (size_t i = 0; i < size; i++) { + if (mask[i] && data[i] > result) { + result = data[i]; + } + } + } else { + for (size_t i = 0; i < size; i++) { + if (data[i] > result) { + result = data[i]; + } + } + } + return result; +} +static inline ASR::expr_t *eval_ArrIntrinsic(Allocator & al, + const Location & loc, ASR::ttype_t *t, Vec& args, + diag::Diagnostics& /*diag*/, ASRUtils::IntrinsicArrayFunctions intrinsic_func_id) { + ASRBuilder b(al, loc); ASR::expr_t* array = args[0]; - ASR::expr_t *arg2 = nullptr, *arg3 = nullptr; - if( args.size() >= 2 ) { - arg2 = args[1]; + if (!array) return nullptr; + ASR::expr_t* value = nullptr, *args_value0 = nullptr; + ASR::ArrayConstant_t *a = nullptr; + size_t size = 0; + int64_t kind = ASRUtils::extract_kind_from_ttype_t(t); + if (ASR::is_a(*array)) { + a = ASR::down_cast(array); + size = ASRUtils::get_fixed_size_of_array(a->m_type); + args_value0 = ASRUtils::fetch_ArrayConstant_value(al, a, 0); + if (!args_value0) return nullptr; + } else { + return nullptr; + } + ASR::ArrayConstant_t *mask = nullptr; + ASR::expr_t* dim = b.i32(1); + if (args[1] && is_logical(*ASRUtils::expr_type(args[1]))) { + if (ASR::is_a(*args[1])) { + mask = ASR::down_cast(args[1]); + } else if (ASR::is_a(*args[1])) { + std::vector mask_values(size, args[1]); + ASR::expr_t *arr = b.ArrayConstant(mask_values, logical, false); + mask = ASR::down_cast(arr); + } else { + return nullptr; + } + } else if(args[2]) { + if (ASR::is_a(*args[2])) { + mask = ASR::down_cast(args[2]); + } else if (ASR::is_a(*args[2])) { + std::vector mask_values(size, args[2]); + ASR::expr_t *arr = b.ArrayConstant(mask_values, logical, false); + mask = ASR::down_cast(arr); + } else { + return nullptr; + } + } + bool *mask_data = nullptr; + switch( intrinsic_func_id ) { + case ASRUtils::IntrinsicArrayFunctions::Sum: { + if (mask) mask_data = (bool*)(mask->m_data); + if (ASR::is_a(*array) && ASR::is_a(*dim)) { + if (ASR::is_a(*args_value0)) { + int64_t result = 0; + switch (kind) { + case 1: result = find_sum(size, (int8_t*)(a->m_data), mask_data); break; + case 2: result = find_sum(size, (int16_t*)(a->m_data), mask_data); break; + case 4: result = find_sum(size, (int32_t*)(a->m_data), mask_data); break; + case 8: result = find_sum(size, (int64_t*)(a->m_data), mask_data); break; + default: break; + } + value = ASRUtils::EXPR(ASR::make_IntegerConstant_t(al, + loc, result, t)); + } else if (ASR::is_a(*args_value0)) { + if (kind == 4) { + float result = 0.0; + result += find_sum(size, (float*)(a->m_data), mask_data); + value = ASRUtils::EXPR(ASR::make_RealConstant_t(al, + loc, result, t)); + } else { + double result = 0.0; + result += find_sum(size, (double*)(a->m_data), mask_data); + value = ASRUtils::EXPR(ASR::make_RealConstant_t(al, + loc, result, t)); + } + } else if (ASR::is_a(*args_value0)) { + if (kind == 4) { + std::complex result = {0.0, 0.0}; + if (mask) { + for (size_t i = 0; i < size; i++) { + if (mask_data[i]) { + result.real(result.real() + *(((float*)(a->m_data)) + 2*i)); + result.imag(result.imag() + *(((float*)(a->m_data)) + 2*i + 1)); + } + } + } else { + for (size_t i = 0; i < size; i++) { + result.real(result.real() + *(((float*)(a->m_data)) + 2*i)); + result.imag(result.imag() + *(((float*)(a->m_data)) + 2*i + 1)); + } + } + value = ASRUtils::EXPR(ASR::make_ComplexConstant_t(al, + loc, result.real(), result.imag(), t)); + } else { + std::complex result = {0.0, 0.0}; + if (mask) { + for (size_t i = 0; i < size; i++) { + if (mask_data[i]) { + result.real(result.real() + *(((double*)(a->m_data)) + 2*i)); + result.imag(result.imag() + *(((double*)(a->m_data)) + 2*i + 1)); + } + } + } else { + for (size_t i = 0; i < size; i++) { + result.real(result.real() + *(((double*)(a->m_data)) + 2*i)); + result.imag(result.imag() + *(((double*)(a->m_data)) + 2*i + 1)); + } + } + value = ASRUtils::EXPR(ASR::make_ComplexConstant_t(al, + loc, result.real(), result.imag(), t)); + } + } + } + return value; + } + case ASRUtils::IntrinsicArrayFunctions::Product: { + if (mask) mask_data = (bool*)(mask->m_data); + if (ASR::is_a(*array)) { + if (ASR::is_a(*args_value0)) { + int64_t result = 1; + switch (kind) { + case 1: result = find_product(size, (int8_t*)(a->m_data), mask_data); break; + case 2: result = find_product(size, (int16_t*)(a->m_data), mask_data); break; + case 4: result = find_product(size, (int32_t*)(a->m_data), mask_data); break; + case 8: result = find_product(size, (int64_t*)(a->m_data), mask_data); break; + default: break; + } + value = ASRUtils::EXPR(ASR::make_IntegerConstant_t(al, + loc, result, t)); + } else if (ASR::is_a(*args_value0)) { + if (kind == 4) { + float result = 1.0; + result = find_product(size, (float*)(a->m_data), mask_data); + value = ASRUtils::EXPR(ASR::make_RealConstant_t(al, + loc, result, t)); + } else { + double result = 1.0; + result = find_product(size, (double*)(a->m_data), mask_data); + value = ASRUtils::EXPR(ASR::make_RealConstant_t(al, + loc, result, t)); + } + } else if (ASR::is_a(*args_value0)) { + if (ASRUtils::extract_kind_from_ttype_t(t) == 4) { + std::complex result = {*(float*)(a->m_data), *((float*)(a->m_data) + 1)}; + float temp_real = result.real(); + float temp_imag = result.imag(); + if (mask) { + for (size_t i = 1; i < size; i++) { + if (mask_data[i]) { + result.real(temp_real * *(((float*)(a->m_data)) + 2*i) - temp_imag * *(((float*)(a->m_data)) + 2*i + 1)); + result.imag(temp_real * *(((float*)(a->m_data)) + 2*i + 1) + temp_imag * *(((float*)(a->m_data)) + 2*i)); + temp_real = result.real(); + temp_imag = result.imag(); + } + } + } else { + for (size_t i = 1; i < size; i++) { + result.real(temp_real * *(((float*)(a->m_data)) + 2*i) - temp_imag * *(((float*)(a->m_data)) + 2*i + 1)); + result.imag(temp_real * *(((float*)(a->m_data)) + 2*i + 1) + temp_imag * *(((float*)(a->m_data)) + 2*i)); + temp_real = result.real(); + temp_imag = result.imag(); + } + } + value = ASRUtils::EXPR(ASR::make_ComplexConstant_t(al, + loc, result.real(), result.imag(), t)); + } else { + std::complex result = {*(double*)(a->m_data), *((double*)(a->m_data) + 1)}; + double temp_real = result.real(); + double temp_imag = result.imag(); + if (mask) { + for (size_t i = 1; i < size; i++) { + if (mask_data[i]) { + // x1*x2 - y1*y2 + i(x1*y2 + x2*y1) + result.real(temp_real * *(((double*)(a->m_data)) + 2*i) - temp_imag * *(((double*)(a->m_data)) + 2*i + 1)); + result.imag(temp_real * *(((double*)(a->m_data)) + 2*i + 1) + temp_imag * *(((double*)(a->m_data)) + 2*i)); + temp_real = result.real(); + temp_imag = result.imag(); + } + } + } else { + for (size_t i = 1; i < size; i++) { + result.real(temp_real * *(((double*)(a->m_data)) + 2*i) - temp_imag * *(((double*)(a->m_data)) + 2*i + 1)); + result.imag(temp_real * *(((double*)(a->m_data)) + 2*i + 1) + temp_imag * *(((double*)(a->m_data)) + 2*i)); + temp_real = result.real(); + temp_imag = result.imag(); + } + } + value = ASRUtils::EXPR(ASR::make_ComplexConstant_t(al, + loc, result.real(), result.imag(), t)); + } + } + } + return value; + } + case ASRUtils::IntrinsicArrayFunctions::Iparity: { + if (mask) mask_data = (bool*)(mask->m_data); + if (ASR::is_a(*array)) { + int64_t result = 0; + switch (kind) { + case 1: result = find_iparity(size, (int8_t*)(a->m_data), mask_data); break; + case 2: result = find_iparity(size, (int16_t*)(a->m_data), mask_data); break; + case 4: result = find_iparity(size, (int32_t*)(a->m_data), mask_data); break; + case 8: result = find_iparity(size, (int64_t*)(a->m_data), mask_data); break; + default: break; + } + value = ASRUtils::EXPR(ASR::make_IntegerConstant_t(al, + loc, result, t)); + } + return value; + } + case ASRUtils::IntrinsicArrayFunctions::MinVal: { + if (ASR::is_a(*array)) { + if (mask) mask_data = (bool*)(mask->m_data); + if (ASR::is_a(*args_value0)) { + int64_t result = std::numeric_limits::max(); + switch (kind) { + case 1: result = find_minval(size, (int8_t*)(a->m_data), mask_data); break; + case 2: result = find_minval(size, (int16_t*)(a->m_data), mask_data); break; + case 4: result = find_minval(size, (int32_t*)(a->m_data), mask_data); break; + case 8: result = find_minval(size, (int64_t*)(a->m_data), mask_data); break; + default: break; + } + value = ASRUtils::EXPR(ASR::make_IntegerConstant_t(al, + loc, result, t)); + } else if (ASR::is_a(*args_value0)) { + if (kind == 4) { + float result = std::numeric_limits::max(); + result = find_minval(size, (float*)(a->m_data), mask_data); + value = ASRUtils::EXPR(ASR::make_RealConstant_t(al, + loc, result, t)); + } else { + double result = std::numeric_limits::max(); + result = find_minval(size, (double*)(a->m_data), mask_data); + value = ASRUtils::EXPR(ASR::make_RealConstant_t(al, + loc, result, t)); + } + } + } + return value; + } + case ASRUtils::IntrinsicArrayFunctions::MaxVal: { + if (ASR::is_a(*array)) { + if (mask) mask_data = (bool*)(mask->m_data); + if (ASR::is_a(*args_value0)) { + int64_t result = std::numeric_limits::min(); + switch (kind) { + case 1: result = find_maxval(size, (int8_t*)(a->m_data), mask_data); break; + case 2: result = find_maxval(size, (int16_t*)(a->m_data), mask_data); break; + case 4: result = find_maxval(size, (int32_t*)(a->m_data), mask_data); break; + case 8: result = find_maxval(size, (int64_t*)(a->m_data), mask_data); break; + default: break; + } + value = ASRUtils::EXPR(ASR::make_IntegerConstant_t(al, + loc, result, t)); + } else if (ASR::is_a(*args_value0)) { + if (kind == 4) { + float result = std::numeric_limits::min(); + result = find_maxval(size, (float*)(a->m_data), mask_data); + value = ASRUtils::EXPR(ASR::make_RealConstant_t(al, + loc, result, t)); + } else { + double result = std::numeric_limits::min(); + result = find_maxval(size, (double*)(a->m_data), mask_data); + value = ASRUtils::EXPR(ASR::make_RealConstant_t(al, + loc, result, t)); + } + } + } + return value; + } + default: { + return value; + } } - if( args.size() == 3 ) { - arg3 = args[2]; + return nullptr; +} + +static inline void fill_dimensions_for_ArrIntrinsic(Allocator& al, size_t n_dims, + ASR::expr_t* array, ASR::expr_t* dim, diag::Diagnostics& diag, bool runtime_dim, + Vec& dims) { + Location loc; loc.first = 1, loc.last = 1; + dims.reserve(al, n_dims); + for( size_t it = 0; it < n_dims; it++ ) { + Vec args_merge; args_merge.reserve(al, 3); + ASRUtils::ASRBuilder b(al, loc); + args_merge.push_back(al, b.ArraySize(array, b.i32(it+1), int32)); + args_merge.push_back(al, b.ArraySize(array, b.i32(it+2), int32)); + args_merge.push_back(al, b.Lt(b.i32(it+1), dim)); + ASR::expr_t* merge = EXPR(Merge::create_Merge(al, loc, args_merge, diag)); + ASR::dimension_t dim; + dim.loc = array->base.loc; + dim.m_start = b.i32(1); + dim.m_length = runtime_dim ? merge : nullptr; + dims.push_back(al, dim); } +} - if( !arg2 && arg3 ) { - std::swap(arg2, arg3); +static inline bool is_same_shape(ASR::expr_t* &array, ASR::expr_t* &mask, const std::string &intrinsic_func_name, diag::Diagnostics &diag, const std::vector &location) { + ASR::ttype_t* array_type = ASRUtils::expr_type(array); + ASR::ttype_t* mask_type = ASRUtils::expr_type(mask); + ASR::dimension_t* mask_dims = nullptr; + ASR::dimension_t* array_dims = nullptr; + int array_n_dims = ASRUtils::extract_dimensions_from_ttype(array_type, array_dims); + int mask_n_dims = ASRUtils::extract_dimensions_from_ttype(mask_type, mask_dims); + if (array_n_dims != mask_n_dims) { + diag.add(diag::Diagnostic("The ranks of the `array` and `mask` arguments of the `" + intrinsic_func_name + "` intrinsic must be the same", + diag::Level::Error, + diag::Stage::Semantic, + {diag::Label("`array` is rank " + std::to_string(array_n_dims) + ", but `mask` is rank " + std::to_string(mask_n_dims), location)})); + return false; + } + for (int i = 0; i < array_n_dims; i++) { + if (array_dims[i].m_length != nullptr && mask_dims[i].m_length != nullptr && !(ASRUtils::expr_equal(array_dims[i].m_length, mask_dims[i].m_length))) { + diag.add(diag::Diagnostic("The shapes of the `array` and `mask` arguments of the `" + intrinsic_func_name + "` intrinsic must be the same", + diag::Level::Error, + diag::Stage::Semantic, + {diag::Label("`array` has shape " + ASRUtils::type_encode_dims(array_n_dims, array_dims) + + ", but `mask` has shape " + ASRUtils::type_encode_dims(mask_n_dims, mask_dims), location)})); + return false; + } } + return true; +} + +static inline ASR::asr_t* create_ArrIntrinsic( + Allocator& al, const Location& loc, Vec& args, + diag::Diagnostics& diag, ASRUtils::IntrinsicArrayFunctions intrinsic_func_id) { + std::string intrinsic_func_name = ASRUtils::get_array_intrinsic_name(static_cast(intrinsic_func_id)); + int64_t id_array = 0, id_array_dim = 1, id_array_mask = 2, id_array_dim_mask = 3; + int64_t overload_id = id_array; + ASR::expr_t* array = args[0]; + ASR::expr_t *dim = nullptr; + ASR::expr_t *mask = nullptr; ASR::ttype_t* array_type = ASRUtils::expr_type(array); - if( arg2 && !arg3 ) { - size_t arg2_rank = ASRUtils::extract_n_dims_from_ttype(ASRUtils::expr_type(arg2)); - if( arg2_rank == 0 ) { - overload_id = id_array_dim; + if (!is_array(array_type)){ + append_error(diag, "Argument to intrinsic `" + intrinsic_func_name + "` is expected to be an array, found: " + type_to_str_fortran(array_type), loc); + return nullptr; + } + if (args[1]) { + if (is_integer(*ASRUtils::expr_type(args[1]))) { + dim = args[1]; + if ( ASRUtils::is_value_constant(dim) ) { + int dim_val = extract_dim_value_int(dim); + int n_dims = ASRUtils::extract_n_dims_from_ttype(array_type); + if (dim_val <= 0 || dim_val > n_dims) { + diag.add(diag::Diagnostic("`dim` argument of the `" + intrinsic_func_name + "` intrinsic is out of bounds", + diag::Level::Error, + diag::Stage::Semantic, + {diag::Label("Must have 0 < dim <= " + std::to_string(n_dims) + " for array of rank " + std::to_string(n_dims), { args[1]->base.loc })})); + return nullptr; + } + } + if (args[2] && is_logical(*ASRUtils::expr_type(args[2]))) { + mask = args[2]; + if (!ASRUtils::is_value_constant(mask)) { + if (!is_same_shape(array, mask, intrinsic_func_name, diag, {args[0]->base.loc, args[2]->base.loc})) { + return nullptr; + } + } + } else if (args[2]) { + append_error(diag, "`mask` argument to `" + intrinsic_func_name + "` must be a scalar or array of logical type", + args[2]->base.loc); + return nullptr; + } + } else if (is_logical(*ASRUtils::expr_type(args[1]))) { + mask = args[1]; + if (!ASRUtils::is_value_constant(mask)) { + if (!is_same_shape(array, mask, intrinsic_func_name, diag, {args[0]->base.loc, args[1]->base.loc})) { + return nullptr; + } + } + if (args[2] && is_integer(*ASRUtils::expr_type(args[2]))) { + dim = args[2]; + if ( ASRUtils::is_value_constant(dim) ) { + int dim_val = extract_dim_value_int(dim); + int n_dims = ASRUtils::extract_n_dims_from_ttype(array_type); + if (dim_val <= 0 || dim_val > n_dims) { + diag.add(diag::Diagnostic("`dim` argument of the `" + intrinsic_func_name + "` intrinsic is out of bounds", + diag::Level::Error, + diag::Stage::Semantic, + {diag::Label("Must have 0 < dim <= " + std::to_string(n_dims) + " for array of rank " + std::to_string(n_dims), { args[2]->base.loc })})); + return nullptr; + } + } + } else if (args[2]) { + append_error(diag, "`dim` argument to `" + intrinsic_func_name + "` must be a scalar and of integer type", + args[2]->base.loc); + return nullptr; + } } else { - overload_id = id_array_mask; + append_error(diag, "Invalid argument type for `dim` or `mask`", + args[1]->base.loc); + return nullptr; } - } else if( arg2 && arg3 ) { - ASR::expr_t* arg2 = args[1]; - ASR::expr_t* arg3 = args[2]; - size_t arg2_rank = ASRUtils::extract_n_dims_from_ttype(ASRUtils::expr_type(arg2)); - size_t arg3_rank = ASRUtils::extract_n_dims_from_ttype(ASRUtils::expr_type(arg3)); - - if( arg2_rank != 0 ) { - append_error(diag, "dim argument to " + intrinsic_func_name + " must be a scalar and must not be an array", - arg2->base.loc); + } else if (args[2]) { + if (!is_logical(*ASRUtils::expr_type(args[2]))) { + diag.add(diag::Diagnostic("'mask' argument of 'sum' intrinsic must be logical", + diag::Level::Error, diag::Stage::Semantic, {diag::Label("", {loc})})); return nullptr; } - - if( arg3_rank == 0 ) { - append_error(diag, "mask argument to " + intrinsic_func_name + " must be an array and must not be a scalar", - arg3->base.loc); + mask = args[2]; + } + if (dim) { + size_t dim_rank = ASRUtils::extract_n_dims_from_ttype(ASRUtils::expr_type(dim)); + if( dim_rank != 0 || !is_integer(*ASRUtils::expr_type(dim))) { + append_error(diag, "`dim` argument to `" + intrinsic_func_name + "` must be a scalar and of integer type", + dim->base.loc); return nullptr; } - + overload_id = id_array_dim; + } + if (mask) { + if(!is_logical(*ASRUtils::expr_type(mask))) { + append_error(diag, "`mask` argument to `" + intrinsic_func_name + "` must be a scalar or array of logical type", + mask->base.loc); + return nullptr; + } + overload_id = id_array_mask; + } + if (dim && mask) { overload_id = id_array_dim_mask; } - // TODO: Add a check for range of values axis can take - // if axis is available at compile time - ASR::expr_t *value = nullptr; bool runtime_dim = false; Vec arg_values; arg_values.reserve(al, 3); ASR::expr_t *array_value = ASRUtils::expr_value(array); arg_values.push_back(al, array_value); - if( arg2 ) { - ASR::expr_t *arg2_value = ASRUtils::expr_value(arg2); - runtime_dim = arg2_value == nullptr; - arg_values.push_back(al, arg2_value); + if( dim ) { + ASR::expr_t *dim_value = ASRUtils::expr_value(dim); + runtime_dim = dim_value == nullptr; + arg_values.push_back(al, dim_value); } - if( arg3 ) { - ASR::expr_t* mask = arg3; + if( mask ) { ASR::expr_t *mask_value = ASRUtils::expr_value(mask); arg_values.push_back(al, mask_value); } ASR::ttype_t* return_type = nullptr; - if( overload_id == id_array || - overload_id == id_array_mask ) { + if( overload_id == id_array || overload_id == id_array_mask ) { ASR::ttype_t* type = ASRUtils::type_get_past_allocatable( - ASRUtils::type_get_past_pointer(array_type)); - return_type = ASRUtils::duplicate_type_without_dims( - al, type, loc); - } else if( overload_id == id_array_dim || - overload_id == id_array_dim_mask ) { + ASRUtils::type_get_past_pointer(array_type)); + return_type = ASRUtils::duplicate_type_without_dims(al, type, loc); + } else if( overload_id == id_array_dim || overload_id == id_array_dim_mask ) { Vec dims; size_t n_dims = ASRUtils::extract_n_dims_from_ttype(array_type); - dims.reserve(al, (int) n_dims - 1); - for( int it = 0; it < (int) n_dims - 1; it++ ) { - Vec args_merge; args_merge.reserve(al, 3); - ASRUtils::ASRBuilder b(al, loc); - args_merge.push_back(al, b.ArraySize(args[0], b.i32(it+1), int32)); - args_merge.push_back(al, b.ArraySize(args[0], b.i32(it+2), int32)); - args_merge.push_back(al, b.iLt(b.i32(it+1), args[1])); - ASR::expr_t* merge = EXPR(Merge::create_Merge(al, loc, args_merge, diag)); - ASR::dimension_t dim; - dim.loc = array->base.loc; - dim.m_start = b.i32(1); - dim.m_length = runtime_dim ? merge : nullptr; - dims.push_back(al, dim); - } + fill_dimensions_for_ArrIntrinsic(al, (int64_t) n_dims - 1, + args[0], args[1], diag, runtime_dim, dims); return_type = ASRUtils::duplicate_type(al, array_type, &dims, ASR::array_physical_typeType::DescriptorArray, true); } - value = eval_ArrIntrinsic(al, loc, return_type, arg_values, diag); + value = eval_ArrIntrinsic(al, loc, return_type, arg_values, diag, intrinsic_func_id); Vec arr_intrinsic_args; arr_intrinsic_args.reserve(al, 3); arr_intrinsic_args.push_back(al, array); - if( arg2 ) { - arr_intrinsic_args.push_back(al, arg2); + if( dim ) { + arr_intrinsic_args.push_back(al, dim); } - if( arg3 ) { - arr_intrinsic_args.push_back(al, arg3); + if( mask ) { + arr_intrinsic_args.push_back(al, mask); } - return ASRUtils::make_IntrinsicArrayFunction_t_util(al, loc, static_cast(intrinsic_func_id), arr_intrinsic_args.p, arr_intrinsic_args.n, overload_id, return_type, value); @@ -511,7 +785,7 @@ static inline void generate_body_for_array_input(Allocator& al, const Location& }, [=, &al, &idx_vars, &doloop_body, &builder] () { ASR::expr_t* array_ref = PassUtils::create_array_ref(array, idx_vars, al); - ASR::expr_t* elemental_operation_val = (builder.*elemental_operation)(return_var, array_ref, loc, nullptr); + ASR::expr_t* elemental_operation_val = (builder.*elemental_operation)(return_var, array_ref); ASR::stmt_t* loop_invariant = builder.Assignment(return_var, elemental_operation_val); doloop_body.push_back(al, loop_invariant); }); @@ -535,7 +809,7 @@ static inline void generate_body_for_array_mask_input(Allocator& al, const Locat [=, &al, &idx_vars, &doloop_body, &builder] () { ASR::expr_t* array_ref = PassUtils::create_array_ref(array, idx_vars, al); ASR::expr_t* mask_ref = PassUtils::create_array_ref(mask, idx_vars, al); - ASR::expr_t* elemental_operation_val = (builder.*elemental_operation)(return_var, array_ref, loc, nullptr); + ASR::expr_t* elemental_operation_val = (builder.*elemental_operation)(return_var, array_ref); ASR::stmt_t* loop_invariant = builder.Assignment(return_var, elemental_operation_val); Vec if_mask; if_mask.reserve(al, 1); @@ -567,7 +841,7 @@ static inline void generate_body_for_array_dim_input( [=, &al, &idx_vars, &target_idx_vars, &doloop_body, &builder, &result] () { ASR::expr_t* result_ref = PassUtils::create_array_ref(result, target_idx_vars, al); ASR::expr_t* array_ref = PassUtils::create_array_ref(array, idx_vars, al); - ASR::expr_t* elemental_operation_val = (builder.*elemental_operation)(result_ref, array_ref, loc, nullptr); + ASR::expr_t* elemental_operation_val = (builder.*elemental_operation)(result_ref, array_ref); ASR::stmt_t* loop_invariant = builder.Assignment(result_ref, elemental_operation_val); doloop_body.push_back(al, loop_invariant); }); @@ -595,7 +869,7 @@ static inline void generate_body_for_array_dim_mask_input( ASR::expr_t* result_ref = PassUtils::create_array_ref(result, target_idx_vars, al); ASR::expr_t* array_ref = PassUtils::create_array_ref(array, idx_vars, al); ASR::expr_t* mask_ref = PassUtils::create_array_ref(mask, idx_vars, al); - ASR::expr_t* elemental_operation_val = (builder.*elemental_operation)(result_ref, array_ref, loc, nullptr); + ASR::expr_t* elemental_operation_val = (builder.*elemental_operation)(result_ref, array_ref); ASR::stmt_t* loop_invariant = builder.Assignment(result_ref, elemental_operation_val); Vec if_mask; if_mask.reserve(al, 1); @@ -614,11 +888,10 @@ static inline ASR::expr_t* instantiate_ArrIntrinsic(Allocator &al, int64_t overload_id, ASRUtils::IntrinsicArrayFunctions intrinsic_func_id, get_initial_value_func get_initial_value, elemental_operation_func elemental_operation) { - std::string intrinsic_func_name = ASRUtils::get_array_intrinsic_name(static_cast(intrinsic_func_id)); + std::string intrinsic_func_name = ASRUtils::get_array_intrinsic_name(static_cast(intrinsic_func_id)); ASRBuilder builder(al, loc); ASRBuilder& b = builder; - int64_t id_array = 0, id_array_dim = 1, id_array_mask = 2; - int64_t id_array_dim_mask = 3; + int64_t id_array = 0, id_array_dim = 1, id_array_mask = 2, id_array_dim_mask = 3; ASR::ttype_t* arg_type = ASRUtils::type_get_past_allocatable( ASRUtils::type_get_past_pointer(arg_types[0])); @@ -636,7 +909,9 @@ static inline ASR::expr_t* instantiate_ArrIntrinsic(Allocator &al, ASR::Function_t *f = ASR::down_cast(s); int orig_array_rank = ASRUtils::extract_n_dims_from_ttype( ASRUtils::expr_type(f->m_args[0])); - if (ASRUtils::types_equal(ASRUtils::expr_type(f->m_args[0]), + bool same_allocatable_type = (ASRUtils::is_allocatable(arg_type) == + ASRUtils::is_allocatable(ASRUtils::expr_type(f->m_args[0]))); + if (same_allocatable_type && ASRUtils::types_equal(ASRUtils::expr_type(f->m_args[0]), arg_type) && orig_array_rank == rank) { return builder.Call(s, new_args, return_type, nullptr); } else { @@ -654,14 +929,12 @@ static inline ASR::expr_t* instantiate_ArrIntrinsic(Allocator &al, ASR::ttype_t* array_type = ASRUtils::duplicate_type_with_empty_dims(al, arg_type); fill_func_arg("array", array_type) - if( overload_id == id_array_dim || - overload_id == id_array_dim_mask ) { + if( overload_id == id_array_dim || overload_id == id_array_dim_mask ) { ASR::ttype_t* dim_type = ASRUtils::TYPE(ASR::make_Integer_t( - al, arg_type->base.loc, 4)); + al, arg_type->base.loc, 4)); fill_func_arg("dim", dim_type) } - if( overload_id == id_array_mask || - overload_id == id_array_dim_mask ) { + if( overload_id == id_array_mask || overload_id == id_array_dim_mask ) { Vec mask_dims; mask_dims.reserve(al, rank); for( int i = 0; i < rank; i++ ) { @@ -672,11 +945,10 @@ static inline ASR::expr_t* instantiate_ArrIntrinsic(Allocator &al, mask_dims.push_back(al, mask_dim); } ASR::ttype_t* mask_type = ASRUtils::TYPE(ASR::make_Logical_t( - al, arg_type->base.loc, 4)); + al, arg_type->base.loc, 4)); if( mask_dims.size() > 0 ) { - mask_type = ASRUtils::make_Array_t_util( - al, arg_type->base.loc, mask_type, - mask_dims.p, mask_dims.size()); + mask_type = ASRUtils::make_Array_t_util(al, arg_type->base.loc, + mask_type, mask_dims.p, mask_dims.size()); } fill_func_arg("mask", mask_type) } @@ -699,7 +971,7 @@ static inline ASR::expr_t* instantiate_ArrIntrinsic(Allocator &al, return_type_ = ASRUtils::make_Array_t_util(al, loc, ASRUtils::extract_type(return_type_), empty_dims.p, empty_dims.size()); if( is_allocatable ) { - return_type_ = ASRUtils::TYPE(ASR::make_Allocatable_t(al, loc, return_type_)); + return_type_ = ASRUtils::TYPE(ASRUtils::make_Allocatable_t_util(al, loc, return_type_)); } } ASR::expr_t *result = declare("result", return_type_, Out); @@ -750,41 +1022,148 @@ static inline ASR::expr_t* instantiate_ArrIntrinsic(Allocator &al, static inline void verify_MaxMinLoc_args(const ASR::IntrinsicArrayFunction_t& x, diag::Diagnostics& diagnostics) { std::string intrinsic_name = get_array_intrinsic_name( - static_cast(x.m_arr_intrinsic_id)); - require_impl(x.n_args >= 1, "`"+ intrinsic_name +"` intrinsic " + static_cast(x.m_arr_intrinsic_id)); + require_impl(x.n_args >= 1 && x.n_args <= 5, "`"+ intrinsic_name +"` intrinsic " "must accept at least one argument", x.base.base.loc, diagnostics); require_impl(x.m_args[0], "`array` argument of `"+ intrinsic_name + "` intrinsic cannot be nullptr", x.base.base.loc, diagnostics); - require_impl(x.m_args[1], "`dim` argument of `" + intrinsic_name + require_impl(x.n_args > 1 ? x.m_args[1] != nullptr : true, "`dim` argument of `" + intrinsic_name + "` intrinsic cannot be nullptr", x.base.base.loc, diagnostics); } static inline ASR::expr_t *eval_MaxMinLoc(Allocator &al, const Location &loc, - ASR::ttype_t *type, Vec &args, int intrinsic_id) { + ASR::ttype_t *type, Vec &args, ASRUtils::IntrinsicArrayFunctions intrinsic_func_id) { ASRBuilder b(al, loc); - if (all_args_evaluated(args) && - extract_n_dims_from_ttype(expr_type(args[0])) == 1) { - // Only supported for arrays with rank 1 - ASR::ArrayConstant_t *arr = ASR::down_cast(args[0]); - std::vector m_eles; - for (size_t i = 0; i < arr->n_args; i++) { - double ele = 0; - if(extract_value(arr->m_args[i], ele)) { - m_eles.push_back(ele); + ASR::expr_t* array = args[0]; + array = ASRUtils::expr_value(array); + if (!array) return nullptr; + if (extract_n_dims_from_ttype(expr_type(array)) == 1) { + int arr_size = 0; + ASR::ArrayConstant_t *arr = nullptr; + if (ASR::is_a(*array)) { + arr = ASR::down_cast(array); + arr_size = ASRUtils::get_fixed_size_of_array(arr->m_type); + } else { + return nullptr; + } + ASR::ArrayConstant_t *mask = nullptr; + if (args[2] && ASR::is_a(*args[2])) { + mask = ASR::down_cast(ASRUtils::expr_value(args[2])); + } else if(args[2] && ASR::is_a(*args[2])) { + bool mask_val = ASR::down_cast(ASRUtils::expr_value(args[2])) -> m_value; + if (mask_val == false) return b.i_t(0, type); + mask = ASR::down_cast(b.ArrayConstant({b.bool_t(mask_val, logical)}, logical, false)); + } else { + std::vector mask_data; + for (int i = 0; i < arr_size; i++) { + mask_data.push_back(b.bool_t(true, logical)); } + mask = ASR::down_cast(b.ArrayConstant(mask_data, logical, false)); } + ASR::LogicalConstant_t *back = ASR::down_cast(ASRUtils::expr_value(args[4])); int index = 0; - if (static_cast(IntrinsicArrayFunctions::MaxLoc) == intrinsic_id) { - index = std::distance(m_eles.begin(), - std::max_element(m_eles.begin(), m_eles.end())) + 1; + int flag = 0; + for (int i = 0; i < arr_size; i++) { + if (((bool*)mask->m_data)[i] != 0) { + flag = 1; + index = i; + break; + } + } + if (static_cast(IntrinsicArrayFunctions::MaxLoc) == static_cast(intrinsic_func_id)) { + if (is_character(*expr_type(args[0]))) { + std::string ele = ASR::down_cast(ASRUtils::fetch_ArrayConstant_value(al, arr, index))->m_s; + for (int i = index+1; i < arr_size; i++) { + if (((bool*)mask->m_data)[i] != 0) { + flag = 1; + std::string ele2 = ASR::down_cast(ASRUtils::fetch_ArrayConstant_value(al, arr, i))->m_s; + if (back && back->m_value) { + if (ele.compare(ele2) <= 0) { + ele = ele2; + index = i; + } + } else { + if (ele.compare(ele2) < 0) { + ele = ele2; + index = i; + } + } + } + } + } else { + double ele = 0; + if (extract_value(ASRUtils::fetch_ArrayConstant_value(al, arr, index), ele)) { + for (int i = index+1; i < arr_size; i++) { + if (((bool*)mask->m_data)[i] != 0) { + flag = 1; + double ele2 = 0; + if (extract_value(ASRUtils::fetch_ArrayConstant_value(al, arr, i), ele2)) { + if (back && back->m_value) { + if (ele <= ele2) { + ele = ele2; + index = i; + } + } else { + if (ele < ele2) { + ele = ele2; + index = i; + } + } + } + } + } + } + } } else { - index = std::distance(m_eles.begin(), - std::min_element(m_eles.begin(), m_eles.end())) + 1; + if (is_character(*expr_type(args[0]))) { + std::string ele = ASR::down_cast(ASRUtils::fetch_ArrayConstant_value(al, arr, index))->m_s; + for (int i = index+1; i < arr_size; i++) { + if (((bool*)mask->m_data)[i] != 0) { + flag = 1; + std::string ele2 = ASR::down_cast(ASRUtils::fetch_ArrayConstant_value(al, arr, i))->m_s; + if (back && back->m_value) { + if (ele.compare(ele2) >= 0) { + ele = ele2; + index = i; + } + } else { + if (ele.compare(ele2) > 0) { + ele = ele2; + index = i; + } + } + } + } + } else { + double ele = 0; + if (extract_value(ASRUtils::fetch_ArrayConstant_value(al, arr, index), ele)) { + for (int i = index+1; i < arr_size; i++) { + if (((bool*)mask->m_data)[i] != 0) { + flag = 1; + double ele2 = 0; + if (extract_value(ASRUtils::fetch_ArrayConstant_value(al, arr, i), ele2)) { + if (back && back->m_value) { + if (ele >= ele2) { + ele = ele2; + index = i; + } + } else { + if (ele > ele2) { + ele = ele2; + index = i; + } + } + } + } + } + } + } } - if (!is_array(type)) { - return b.i(index, type); + if (flag == 0) return b.i_t(0, type); + else if (!is_array(type)) { + return b.i_t(index + 1, type); } else { - return b.ArrayConstant({b.i32(index)}, extract_type(type), false); + return b.ArrayConstant({b.i32(index + 1)}, extract_type(type), false); } } else { return nullptr; @@ -792,36 +1171,33 @@ static inline ASR::expr_t *eval_MaxMinLoc(Allocator &al, const Location &loc, } static inline ASR::asr_t* create_MaxMinLoc(Allocator& al, const Location& loc, - Vec& args, int intrinsic_id, + Vec& args, ASRUtils::IntrinsicArrayFunctions intrinsic_func_id, diag::Diagnostics& diag) { - std::string intrinsic_name = get_array_intrinsic_name(static_cast(intrinsic_id)); + int64_t array_id = 0, array_mask = 1, array_dim = 2, array_dim_mask = 3; + int64_t overload_id = array_id; + std::string intrinsic_name = get_array_intrinsic_name(static_cast(intrinsic_func_id)); ASRUtils::ASRBuilder b(al, loc); - ASR::ttype_t *array_type = expr_type(args[0]); + ASR::expr_t* array = args[0]; + ASR::ttype_t *array_type = expr_type(array); if ( !is_array(array_type) ) { append_error(diag, "`array` argument of `"+ intrinsic_name +"` must be an array", loc); return nullptr; - } else if ( !is_integer(*array_type) && !is_real(*array_type) ) { - append_error(diag, "`array` argument of `"+ intrinsic_name +"` must be integer or " - "real for now", loc); - return nullptr; - } else if ( args[2] || args[4] ) { - append_error(diag, "`mask` and `back` keyword argument is not supported yet", loc); + } else if ( !is_integer(*array_type) && !is_real(*array_type) && !is_character(*array_type)) { + append_error(diag, "`array` argument of `"+ intrinsic_name +"` must be integer, " + "real or character", loc); return nullptr; } ASR::ttype_t *return_type = nullptr; - Vec m_args; m_args.reserve(al, 1); - m_args.push_back(al, args[0]); + Vec m_args; m_args.reserve(al, 5); + m_args.push_back(al, array); Vec result_dims; result_dims.reserve(al, 1); ASR::dimension_t *m_dims; int n_dims = extract_dimensions_from_ttype(array_type, m_dims); int dim = 0, kind = 4; // default kind - if (args[3]) { - if (!extract_value(expr_value(args[3]), kind)) { - append_error(diag, "Runtime value for `kind` argument is not supported yet", loc); - return nullptr; - } - } - if ( args[1] ) { + ASR::expr_t *dim_expr = nullptr; + ASR::expr_t *mask_expr = nullptr; + if (args[1]) { + dim_expr = args[1]; if ( !ASR::is_a(*expr_type(args[1])) ) { append_error(diag, "`dim` should be a scalar integer type", loc); return nullptr; @@ -829,7 +1205,7 @@ static inline ASR::asr_t* create_MaxMinLoc(Allocator& al, const Location& loc, append_error(diag, "Runtime values for `dim` argument is not supported yet", loc); return nullptr; } - if ( 1 > dim || dim > n_dims ) { + if ( dim < 1 || dim > n_dims ) { append_error(diag, "`dim` argument of `"+ intrinsic_name +"` is out of " "array index range", loc); return nullptr; @@ -855,22 +1231,64 @@ static inline ASR::asr_t* create_MaxMinLoc(Allocator& al, const Location& loc, tmp_dim.m_start = b.i32(1); tmp_dim.m_length = b.i32(n_dims); result_dims.push_back(al, tmp_dim); + m_args.push_back(al, b.i32(-1)); + } + if (args[2]) { + mask_expr = args[2]; + if (!is_array(expr_type(args[2])) || !is_logical(*expr_type(args[2]))) { + append_error(diag, "`mask` argument of `"+ intrinsic_name +"` must be a logical array", loc); + return nullptr; + } + m_args.push_back(al, args[2]); + } else { + m_args.push_back(al, b.ArrayConstant({b.bool_t(1, logical)}, logical, true)); + } + if (args[3]) { + if (!extract_value(expr_value(args[3]), kind)) { + append_error(diag, "Runtime value for `kind` argument is not supported yet", loc); + return nullptr; + } + int kind = ASR::down_cast(ASRUtils::expr_value(args[3]))->m_n; + ASRUtils::set_kind_to_ttype_t(return_type, kind); + m_args.push_back(al, args[3]); + } else { + m_args.push_back(al, b.i32(4)); + } + if (args[4]) { + if (!ASR::is_a(*expr_type(args[4]))) { + append_error(diag, "`back` argument of `"+ intrinsic_name +"` must be a logical scalar", loc); + return nullptr; + } + m_args.push_back(al, args[4]); + } else { + m_args.push_back(al, b.bool_t(false, logical)); + } + + if (dim_expr) { + overload_id = array_dim; + } + if (mask_expr) { + overload_id = array_mask; + } + if (dim_expr && mask_expr) { + overload_id = array_dim_mask; } if ( !return_type ) { return_type = duplicate_type(al, TYPE( ASR::make_Integer_t(al, loc, kind)), &result_dims); } - ASR::expr_t *m_value = eval_MaxMinLoc(al, loc, return_type, m_args, - intrinsic_id); + ASR::expr_t *m_value = nullptr; + m_value = eval_MaxMinLoc(al, loc, return_type, m_args, + intrinsic_func_id); return make_IntrinsicArrayFunction_t_util(al, loc, - intrinsic_id, m_args.p, m_args.n, 0, return_type, m_value); + static_cast(intrinsic_func_id), m_args.p, m_args.size(), overload_id, return_type, m_value); } static inline ASR::expr_t *instantiate_MaxMinLoc(Allocator &al, - const Location &loc, SymbolTable *scope, int intrinsic_id, + const Location &loc, SymbolTable *scope, ASRUtils::IntrinsicArrayFunctions intrinsic_func_id, Vec& arg_types, ASR::ttype_t *return_type, - Vec& m_args, int64_t /*overload_id*/) { - std::string intrinsic_name = get_array_intrinsic_name(static_cast(intrinsic_id)); + Vec& m_args, int64_t overload_id) { + std::string intrinsic_name = get_array_intrinsic_name(static_cast(intrinsic_func_id)); declare_basic_variables("_lcompilers_" + intrinsic_name) /* * max_index = 1; min_index @@ -886,29 +1304,45 @@ static inline ASR::expr_t *instantiate_MaxMinLoc(Allocator &al, * end ... * end do */ - fill_func_arg("array", arg_types[0]); + ASR::ttype_t* array_type = ASRUtils::duplicate_type_with_empty_dims(al, arg_types[0]); + fill_func_arg("array", array_type); + fill_func_arg("dim", arg_types[1]); + fill_func_arg("mask", ASRUtils::duplicate_type_with_empty_dims( + al, arg_types[2], ASR::array_physical_typeType::DescriptorArray, true)); + fill_func_arg("kind", arg_types[3]); + fill_func_arg("back", arg_types[4]); + ASR::expr_t *result = nullptr; int n_dims = extract_n_dims_from_ttype(arg_types[0]); ASR::ttype_t *type = extract_type(return_type); - if (m_args.n > 1) { - // TODO: Use overload_id - fill_func_arg("dim", arg_types[1]); + if( !ASRUtils::is_array(return_type) ) { + result = declare("result", return_type, ReturnVar); + } else { + result = declare("result", ASRUtils::duplicate_type_with_empty_dims( + al, return_type, ASR::array_physical_typeType::DescriptorArray, true), Out); + args.push_back(al, result); } - ASR::expr_t *result = declare("result", return_type, ReturnVar); Vec idx_vars, target_idx_vars; Vec doloop_body; - if (m_args.n == 1) { + if (overload_id < 2) { b.generate_reduction_intrinsic_stmts_for_scalar_output( loc, args[0], fn_symtab, body, idx_vars, doloop_body, [=, &al, &body, &b] () { - body.push_back(al, b.Assignment(result, b.i(1, type))); + ASR::expr_t *i = declare("i", type, Local); + ASR::expr_t *maskval = b.ArrayItem_01(args[2], {i}); + body.push_back(al, b.DoLoop(i, LBound(args[2], 1), UBound(args[2], 1), { + b.If(b.Eq(maskval, b.bool_t(1, logical)), { + b.Assignment(result, i), + b.Exit() + }, {}) + }, nullptr)); }, [=, &al, &b, &idx_vars, &doloop_body] () { std::vector if_body; if_body.reserve(n_dims); Vec result_idx; result_idx.reserve(al, n_dims); for (int i = 0; i < n_dims; i++) { - ASR::expr_t *idx = b.ArrayItem_01(result, {b.i32(i+1)}); + ASR::expr_t *idx = b.ArrayItem_01(result, {b.i32(i + 1)}); if (extract_kind_from_ttype_t(type) != 4) { - if_body.push_back(b.Assignment(idx, b.i2i(idx_vars[i], type))); - result_idx.push_back(al, b.i2i32(idx)); + if_body.push_back(b.Assignment(idx, b.i2i_t(idx_vars[i], type))); + result_idx.push_back(al, b.i2i_t(idx, int32)); } else { if_body.push_back(b.Assignment(idx, idx_vars[i])); result_idx.push_back(al, idx); @@ -916,12 +1350,35 @@ static inline ASR::expr_t *instantiate_MaxMinLoc(Allocator &al, } ASR::expr_t *array_ref_01 = ArrayItem_02(args[0], idx_vars); ASR::expr_t *array_ref_02 = ArrayItem_02(args[0], result_idx); - if (static_cast(IntrinsicArrayFunctions::MaxLoc) == intrinsic_id) { - doloop_body.push_back(al, b.If(b.Gt(array_ref_01, - array_ref_02), if_body, {})); + ASR::expr_t *mask_val = ArrayItem_02(args[2], idx_vars); + if (overload_id == 1) { + if (static_cast(IntrinsicArrayFunctions::MaxLoc) == static_cast(intrinsic_func_id)) { + doloop_body.push_back(al, b.If(b.Eq(args[4], b.bool_t(1, logical)), { + b.If(b.And(b.GtE(array_ref_01, array_ref_02), b.Eq(mask_val, b.bool_t(1, logical))), if_body, {})} + , { + b.If(b.And(b.Gt(array_ref_01, array_ref_02), b.Eq(mask_val, b.bool_t(1, logical))), if_body, {}) + })); + } else { + doloop_body.push_back(al, b.If(b.Eq(args[4], b.bool_t(1, logical)), { + b.If(b.And(b.LtE(array_ref_01, array_ref_02), b.Eq(mask_val, b.bool_t(1, logical))), if_body, {})} + , { + b.If(b.And(b.Lt(array_ref_01, array_ref_02), b.Eq(mask_val, b.bool_t(1, logical))), if_body, {}) + })); + } } else { - doloop_body.push_back(al, b.If(b.Lt(array_ref_01, - array_ref_02), if_body, {})); + if (static_cast(IntrinsicArrayFunctions::MaxLoc) == static_cast(intrinsic_func_id)) { + doloop_body.push_back(al, b.If(b.Eq(args[4], b.bool_t(1, logical)), { + b.If(b.GtE(array_ref_01, array_ref_02), if_body, {}) + }, { + b.If(b.Gt(array_ref_01, array_ref_02), if_body, {}) + })); + } else { + doloop_body.push_back(al, b.If(b.Eq(args[4], b.bool_t(1, logical)), { + b.If(b.LtE(array_ref_01, array_ref_02), if_body, {}) + }, { + b.If(b.Lt(array_ref_01, array_ref_02), if_body, {}) + })); + } } }); } else { @@ -931,14 +1388,23 @@ static inline ASR::expr_t *instantiate_MaxMinLoc(Allocator &al, loc, args[0], args[1], fn_symtab, body, idx_vars, target_idx_vars, doloop_body, [=, &al, &body, &b] () { - body.push_back(al, b.Assignment(result, b.i(1, type))); + ASR::expr_t *i = declare("i", type, Local); + ASR::expr_t *maskval = b.ArrayItem_01(args[2], {i}); + body.push_back(al, b.DoLoop(i, LBound(args[2], 1), UBound(args[2], 1), { + b.If(b.Eq(maskval, b.bool_t(1, logical)), { + b.Assignment(result, i), + b.Exit() + }, {}) + }, nullptr)); }, [=, &al, &b, &idx_vars, &target_idx_vars, &doloop_body] () { ASR::expr_t *result_ref, *array_ref_02; - if (is_array(return_type)) { + bool condition = is_array(return_type); + condition = condition && n_dims > 1; + if (condition) { result_ref = ArrayItem_02(result, target_idx_vars); Vec tmp_idx_vars; tmp_idx_vars.from_pointer_n_copy(al, idx_vars.p, idx_vars.n); - tmp_idx_vars.p[dim - 1] = b.i2i32(result_ref); + tmp_idx_vars.p[dim - 1] = b.i2i_t(result_ref, int32); array_ref_02 = ArrayItem_02(args[0], tmp_idx_vars); } else { // 1D scalar output @@ -948,22 +1414,49 @@ static inline ASR::expr_t *instantiate_MaxMinLoc(Allocator &al, ASR::expr_t *array_ref_01 = ArrayItem_02(args[0], idx_vars); ASR::expr_t *res_idx = idx_vars.p[dim - 1]; if (extract_kind_from_ttype_t(type) != 4) { - res_idx = b.i2i(res_idx, type); + res_idx = b.i2i_t(res_idx, type); } - if (static_cast(IntrinsicArrayFunctions::MaxLoc) == intrinsic_id) { - doloop_body.push_back(al, b.If(b.Gt(array_ref_01, array_ref_02), { - b.Assignment(result_ref, res_idx) - }, {})); + ASR::expr_t *mask_val = ArrayItem_02(args[2], idx_vars); + if (overload_id == 3) { + if (static_cast(IntrinsicArrayFunctions::MaxLoc) == static_cast(intrinsic_func_id)) { + doloop_body.push_back(al, b.If(b.Eq(args[4], b.bool_t(1, logical)), { + b.If(b.And(b.GtE(array_ref_01, array_ref_02), b.Eq(mask_val, b.bool_t(1, logical))), {b.Assignment(result_ref, res_idx)}, {})} + , { + b.If(b.And(b.Gt(array_ref_01, array_ref_02), b.Eq(mask_val, b.bool_t(1, logical))), {b.Assignment(result_ref, res_idx)}, {}) + })); + } else { + doloop_body.push_back(al, b.If(b.Eq(args[4], b.bool_t(1, logical)), { + b.If(b.And(b.LtE(array_ref_01, array_ref_02), b.Eq(mask_val, b.bool_t(1, logical))), {b.Assignment(result_ref, res_idx)}, {})} + , { + b.If(b.And(b.Lt(array_ref_01, array_ref_02), b.Eq(mask_val, b.bool_t(1, logical))), {b.Assignment(result_ref, res_idx)}, {}) + })); + } } else { - doloop_body.push_back(al, b.If(b.Lt(array_ref_01, array_ref_02), { - b.Assignment(result_ref, res_idx) - }, {})); + if (static_cast(IntrinsicArrayFunctions::MaxLoc) == static_cast(intrinsic_func_id)) { + doloop_body.push_back(al, b.If(b.Eq(args[4], b.bool_t(1, logical)), { + b.If(b.GtE(array_ref_01, array_ref_02), {b.Assignment(result_ref, res_idx)}, {}) + }, { + b.If(b.Gt(array_ref_01, array_ref_02), {b.Assignment(result_ref, res_idx)}, {}) + })); + } else { + doloop_body.push_back(al, b.If(b.Eq(args[4], b.bool_t(1, logical)), { + b.If(b.LtE(array_ref_01, array_ref_02), {b.Assignment(result_ref, res_idx)}, {}) + }, { + b.If(b.Lt(array_ref_01, array_ref_02), {b.Assignment(result_ref, res_idx)}, {}) + })); + } } }); } - body.push_back(al, Return()); - ASR::symbol_t *fn_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, + body.push_back(al, b.Return()); + ASR::symbol_t *fn_sym = nullptr; + if( ASRUtils::expr_intent(result) == ASR::intentType::ReturnVar ) { + fn_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); + } else { + fn_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, + body, nullptr, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); + } scope->add_symbol(fn_name, fn_sym); return b.Call(fn_sym, m_args, return_type, nullptr); } @@ -982,11 +1475,12 @@ namespace Shape { static ASR::expr_t *eval_Shape(Allocator &al, const Location &loc, ASR::ttype_t *type, Vec &args, diag::Diagnostics& /*diag*/) { + ASR::expr_t* arg_value = expr_value(args[0]); ASR::dimension_t *m_dims; - size_t n_dims = extract_dimensions_from_ttype(expr_type(args[0]), m_dims); + size_t n_dims = extract_dimensions_from_ttype(expr_type(arg_value ? arg_value : args[0]), m_dims); Vec m_shapes; m_shapes.reserve(al, n_dims); if( n_dims == 0 ){ - return EXPR(ASR::make_ArrayConstant_t(al, loc, m_shapes.p, 0, + return EXPR(ASRUtils::make_ArrayConstructor_t_util(al, loc, m_shapes.p, 0, type, ASR::arraystorageType::ColMajor)); } else { for (size_t i = 0; i < n_dims; i++) { @@ -994,7 +1488,7 @@ namespace Shape { ASR::expr_t *e = nullptr; if (extract_kind_from_ttype_t(type) != 4) { ASRUtils::ASRBuilder b(al, loc); - e = b.i2i(m_dims[i].m_length, extract_type(type)); + e = b.i2i_t(m_dims[i].m_length, extract_type(type)); } else { e = m_dims[i].m_length; } @@ -1006,7 +1500,7 @@ namespace Shape { bool all_args_evaluated_ = all_args_evaluated(m_shapes); if (m_shapes.n > 0) { if (all_args_evaluated_) { - value = EXPR(ASR::make_ArrayConstant_t(al, loc, m_shapes.p, m_shapes.n, + value = EXPR(ASRUtils::make_ArrayConstructor_t_util(al, loc, m_shapes.p, m_shapes.n, type, ASR::arraystorageType::ColMajor)); } else { value = EXPR(ASR::make_ArrayConstructor_t(al, loc, m_shapes.p, m_shapes.n, @@ -1017,8 +1511,7 @@ namespace Shape { } static inline ASR::asr_t* create_Shape(Allocator& al, const Location& loc, - Vec& args, - diag::Diagnostics& diag) { + Vec& args, diag::Diagnostics& diag) { ASRBuilder b(al, loc); Vecm_args; m_args.reserve(al, 1); m_args.push_back(al, args[0]); @@ -1049,180 +1542,1353 @@ namespace Shape { declare_basic_variables("_lcompilers_shape"); fill_func_arg("source", ASRUtils::duplicate_type_with_empty_dims(al, arg_types[0])); - auto result = declare(fn_name, return_type, ReturnVar); + ASR::expr_t* result = nullptr; + result = declare(fn_name, return_type, Out); + args.push_back(al, result); int iter = extract_n_dims_from_ttype(arg_types[0]) + 1; auto i = declare("i", int32, Local); body.push_back(al, b.Assignment(i, b.i32(1))); - body.push_back(al, b.While(b.iLt(i, b.i32(iter)), { + body.push_back(al, b.While(b.Lt(i, b.i32(iter)), { b.Assignment(b.ArrayItem_01(result, {i}), - b.ArraySize_2(args[0], i, extract_type(return_type))), - b.Assignment(i, b.iAdd(i, b.i32(1))) + b.ArraySize(args[0], i, extract_type(return_type))), + b.Assignment(i, b.Add(i, b.i32(1))) })); - body.push_back(al, Return()); - ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, - body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); + body.push_back(al, b.Return()); + ASR::symbol_t *f_sym = make_Function_Without_ReturnVar_t( + fn_name, fn_symtab, dep, args, + body, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); scope->add_symbol(fn_name, f_sym); return b.Call(f_sym, new_args, return_type, nullptr); } } // namespace Shape -namespace Any { - +namespace Cshift { + static inline void verify_args(const ASR::IntrinsicArrayFunction_t &x, + diag::Diagnostics &diagnostics) { + ASRUtils::require_impl(x.n_args == 2 || x.n_args == 3, + "`cshift` intrinsic accepts 2 or 3 arguments", + x.base.base.loc, diagnostics); + ASRUtils::require_impl(x.m_args[0], "`array` argument of `cshift` " + "cannot be nullptr", x.base.base.loc, diagnostics); + ASRUtils::require_impl(x.m_args[1], "`shift` argument of `cshift` " + "cannot be nullptr", x.base.base.loc, diagnostics); + } + + static ASR::expr_t *eval_Cshift(Allocator &al, const Location &loc, + ASR::ttype_t *type, Vec &args, diag::Diagnostics& /*diag*/) { + ASRBuilder b(al, loc); + if (all_args_evaluated(args) && + extract_n_dims_from_ttype(expr_type(args[0])) == 1) { + ASR::ArrayConstant_t *arr = ASR::down_cast(ASRUtils::expr_value(args[0])); + ASR::ttype_t* arr_type = expr_type(args[0]); + std::vector m_eles; + if (is_integer(*arr_type)) { + for (size_t i = 0; i < (size_t) ASRUtils::get_fixed_size_of_array(arr->m_type); i++) { + int ele = 0; + if(extract_value(ASRUtils::fetch_ArrayConstant_value(al, arr, i), ele)) { + m_eles.push_back(b.i_t(ele, arr_type)); + } + } + } else if (is_real(*arr_type)) { + for (size_t i = 0; i < (size_t) ASRUtils::get_fixed_size_of_array(arr->m_type); i++) { + double ele = 0; + if(extract_value(ASRUtils::fetch_ArrayConstant_value(al, arr, i), ele)) { + m_eles.push_back(b.f_t(ele, arr_type)); + } + } + } else if (is_logical(*arr_type)) { + for (size_t i = 0; i < (size_t) ASRUtils::get_fixed_size_of_array(arr->m_type); i++) { + bool ele = false; + if(extract_value(ASRUtils::fetch_ArrayConstant_value(al, arr, i), ele)) { + m_eles.push_back(b.bool_t(ele, arr_type)); + } + } + } else if (is_character(*arr_type)) { + for (size_t i = 0; i < (size_t) ASRUtils::get_fixed_size_of_array(arr->m_type); i++) { + std::string str = ""; + str = ASR::down_cast(ASRUtils::fetch_ArrayConstant_value(al, arr, i))->m_s; + m_eles.push_back(b.StringConstant(str, arr_type)); + } + } + int shift = 0; + if (extract_value(expr_value(args[1]), shift)) { + if (shift < 0) { + shift = m_eles.size() + shift; + } + std::rotate(m_eles.begin(), m_eles.begin() + shift, m_eles.end()); + } + return b.ArrayConstant(m_eles, extract_type(type), false); + } else { + return nullptr; + } + } + + static inline ASR::asr_t* create_Cshift(Allocator& al, const Location& loc, + Vec& args, diag::Diagnostics& diag) { + ASR::expr_t *array = args[0], *shift = args[1], *dim = args[2]; + bool is_type_allocatable = false; + bool is_dim_present = false; + if (ASRUtils::is_allocatable(array)) { + is_type_allocatable = true; + } + if (dim) { + is_dim_present = true; + } + + ASR::ttype_t *type_array = ASRUtils::type_get_past_allocatable_pointer(expr_type(array)); + ASR::ttype_t *type_shift = ASRUtils::type_get_past_allocatable_pointer(expr_type(shift)); + ASR::ttype_t *ret_type = ASRUtils::type_get_past_allocatable_pointer(expr_type(array)); + if ( !is_array(type_array) ) { + append_error(diag, "The argument `array` in `cshift` must be of type Array", array->base.loc); + return nullptr; + } + if( !is_integer(*type_shift) ) { + append_error(diag, "The argument `shift` in `cshift` must be of type Integer", shift->base.loc); + return nullptr; + } + ASR::dimension_t* array_dims = nullptr; + int array_rank = extract_dimensions_from_ttype(type_array, array_dims); + int array_dim = -1; + extract_value(array_dims[0].m_length, array_dim); + ASRUtils::require_impl(array_rank > 0, "The argument `array` in `cshift` must be of rank > 0", array->base.loc, diag); + ASRBuilder b(al, loc); + Vec result_dims; result_dims.reserve(al, 1); + int overload_id = 2; + if (!is_dim_present) { + result_dims.push_back(al, b.set_dim(array_dims[0].m_start, array_dims[0].m_length)); + ret_type = ASRUtils::duplicate_type(al, ret_type, &result_dims); + } else { + result_dims.push_back(al, b.set_dim(dim, dim)); + ret_type = ASRUtils::duplicate_type(al, ret_type, &result_dims); + } + if (is_type_allocatable) { + ret_type = TYPE(ASRUtils::make_Allocatable_t_util(al, loc, ret_type)); + } + Vec m_args; m_args.reserve(al, 2); + m_args.push_back(al, array); m_args.push_back(al, shift); + ASR::expr_t *value = nullptr; + if (all_args_evaluated(m_args)) { + value = eval_Cshift(al, loc, ret_type, m_args, diag); + } + return make_IntrinsicArrayFunction_t_util(al, loc, + static_cast(IntrinsicArrayFunctions::Cshift), + m_args.p, m_args.n, overload_id, ret_type, value); + } + + static inline ASR::expr_t* instantiate_Cshift(Allocator &al, + const Location &loc, SymbolTable *scope, + Vec &arg_types, ASR::ttype_t *return_type, + Vec &m_args, int64_t /*overload_id*/) { + declare_basic_variables("_lcompilers_cshift"); + fill_func_arg("array", duplicate_type_with_empty_dims(al, arg_types[0])); + fill_func_arg("shift", arg_types[1]); + ASR::ttype_t* return_type_ = return_type; + /* + cshift(array, shift, dim) + int i = 0 + do j = shift, size(array) + result[i] = array[j] + i = i + 1 + end for + do j = 1, shift + result[i] = array[j] + i = i + 1 + end do + */ + if( !ASRUtils::is_fixed_size_array(return_type) ) { + int64_t n_dims_return_type = ASRUtils::extract_n_dims_from_ttype(return_type); + bool is_allocatable = ASRUtils::is_allocatable(return_type); + Vec empty_dims; + empty_dims.reserve(al, 2); + for( int idim = 0; idim < n_dims_return_type; idim++ ) { + ASR::dimension_t empty_dim; + empty_dim.loc = loc; + empty_dim.m_start = nullptr; + empty_dim.m_length = nullptr; + empty_dims.push_back(al, empty_dim); + } + return_type_ = ASRUtils::make_Array_t_util(al, loc, + ASRUtils::extract_type(return_type_), empty_dims.p, empty_dims.size()); + if( is_allocatable ) { + return_type_ = ASRUtils::TYPE(ASRUtils::make_Allocatable_t_util(al, loc, return_type_)); + } + } + ASR::expr_t *result = declare("result", return_type_, Out); + args.push_back(al, result); + ASR::expr_t *i = declare("i", int32, Local); + ASR::expr_t *j = declare("j", int32, Local); + ASR::expr_t* shift_val = declare("shift_val", int32, Local);; + body.push_back(al, b.Assignment(shift_val, args[1])); + body.push_back(al, b.If(b.Lt(args[1], b.i32(0)), { + b.Assignment(shift_val, b.Add(shift_val, UBound(args[0], 1))) + }, { + b.Assignment(shift_val, shift_val) + } + )); + body.push_back(al, b.Assignment(i, b.i32(1))); + + body.push_back(al, b.DoLoop(j, b.Add(shift_val, b.i32(1)), UBound(args[0], 1), { + b.Assignment(b.ArrayItem_01(result, {i}), b.ArrayItem_01(args[0], {j})), + b.Assignment(i, b.Add(i, b.i32(1))), + }, nullptr)); + body.push_back(al, b.DoLoop(j, LBound(args[0], 1), shift_val, { + b.Assignment(b.ArrayItem_01(result, {i}), b.ArrayItem_01(args[0], {j})), + b.Assignment(i, b.Add(i, b.i32(1))), + }, nullptr)); + + body.push_back(al, b.Return()); + ASR::symbol_t *fn_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, + body, nullptr, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); + scope->add_symbol(fn_name, fn_sym); + return b.Call(fn_sym, m_args, return_type, nullptr); + } + +} // namespace Cshift + +namespace Spread { + static inline void verify_args(const ASR::IntrinsicArrayFunction_t &x, + diag::Diagnostics &diagnostics) { + ASRUtils::require_impl(x.n_args == 3, + "`spread` intrinsic accepts 3 arguments", + x.base.base.loc, diagnostics); + ASRUtils::require_impl(x.m_args[0], "`source` argument of `spread` " + "cannot be nullptr", x.base.base.loc, diagnostics); + ASRUtils::require_impl(x.m_args[1], "`dim` argument of `spread` " + "cannot be nullptr", x.base.base.loc, diagnostics); + ASRUtils::require_impl(x.m_args[2], "`ncopies` argument of `spread` " + "cannot be nullptr", x.base.base.loc, diagnostics); + } + + static ASR::expr_t *eval_Spread(Allocator &al, const Location &loc, + ASR::ttype_t *type, Vec &args, diag::Diagnostics& diag) { + ASRBuilder b(al, loc); + int dim_val = ASR::down_cast(ASRUtils::expr_value(args[1])) -> m_n; + if (all_args_evaluated(args) && + (extract_n_dims_from_ttype(expr_type(args[0])) == 1) && (dim_val == 1 || dim_val == 2)) { + ASR::ArrayConstant_t *arr = ASR::down_cast(ASRUtils::expr_value(args[0])); + int ncopies = ASR::down_cast(ASRUtils::expr_value(args[2]))->m_n; + size_t array_size = ASRUtils::get_fixed_size_of_array(arr->m_type); + ASR::ttype_t* arr_type = expr_type(args[0]); + std::vector m_eles; + ASR::expr_t *value = nullptr; + if (is_integer(*arr_type)) { + if (dim_val == 1) { + for (size_t i = 0; i < array_size; i++) { + std::vector res; + int ele = 0; + if(extract_value(ASRUtils::fetch_ArrayConstant_value(al, arr, i), ele)) { + for (int j = 0; j < ncopies; j++) { + res.push_back(b.i_t(ele, arr_type)); + } + } + value = b.ArrayConstant(res, extract_type(arr_type), false); + res = {}; + m_eles.push_back(value); + } + } else if (dim_val == 2) { + for (int j = 0; j < ncopies; j++) { + std::vector res; + int ele = 0; + for (size_t i = 0; i < array_size; i++) { + if(extract_value(ASRUtils::fetch_ArrayConstant_value(al, arr, i), ele)) { + res.push_back(b.i_t(ele, arr_type)); + } + } + value = b.ArrayConstant(res, extract_type(arr_type), false); + res = {}; + m_eles.push_back(value); + } + } + } else if (is_real(*arr_type)) { + if (dim_val == 1) { + for (size_t i = 0; i < array_size; i++) { + std::vector res; + double ele = 0; + if(extract_value(ASRUtils::fetch_ArrayConstant_value(al, arr, i), ele)) { + for (int j = 0; j < ncopies; j++) { + res.push_back(b.f_t(ele, arr_type)); + } + } + value = b.ArrayConstant(res, extract_type(arr_type), false); + res = {}; + m_eles.push_back(value); + } + } else if (dim_val == 2) { + for (int j = 0; j < ncopies; j++) { + std::vector res; + double ele = 0; + for (size_t i = 0; i < array_size; i++) { + if(extract_value(ASRUtils::fetch_ArrayConstant_value(al, arr, i), ele)) { + res.push_back(b.f_t(ele, arr_type)); + } + } + value = b.ArrayConstant(res, extract_type(arr_type), false); + res = {}; + m_eles.push_back(value); + } + } + } else if (is_logical(*arr_type)) { + if (dim_val == 1) { + for (size_t i = 0; i < array_size; i++) { + std::vector res; + bool ele = false; + if(extract_value(ASRUtils::fetch_ArrayConstant_value(al, arr, i), ele)) { + for (int j = 0; j < ncopies; j++) { + res.push_back(b.bool_t(ele, arr_type)); + } + } + value = b.ArrayConstant(res, extract_type(arr_type), false); + res = {}; + m_eles.push_back(value); + } + } else if (dim_val == 2) { + for (int j = 0; j < ncopies; j++) { + std::vector res; + bool ele = false; + for (size_t i = 0; i < array_size; i++) { + if(extract_value(ASRUtils::fetch_ArrayConstant_value(al, arr, i), ele)) { + res.push_back(b.bool_t(ele, arr_type)); + } + } + value = b.ArrayConstant(res, extract_type(arr_type), false); + res = {}; + m_eles.push_back(value); + } + } + } else if (is_character(*arr_type)) { + if (dim_val == 1) { + for (size_t i = 0; i < array_size; i++) { + std::vector res; + std::string str = ""; + str = ASR::down_cast(ASRUtils::fetch_ArrayConstant_value(al, arr, i))->m_s; + for (int j = 0; j < ncopies; j++) { + res.push_back(b.StringConstant(str, arr_type)); + } + value = b.ArrayConstant(res, extract_type(arr_type), false); + res = {}; + m_eles.push_back(value); + } + } else if (dim_val == 2) { + for (int j = 0; j < ncopies; j++) { + std::vector res; + std::string str = ""; + for (size_t i = 0; i < array_size; i++) { + str = ASR::down_cast(ASRUtils::fetch_ArrayConstant_value(al, arr, i))->m_s; + res.push_back(b.StringConstant(str, arr_type)); + } + value = b.ArrayConstant(res, extract_type(arr_type), false); + res = {}; + m_eles.push_back(value); + } + } + } else if (is_complex(*arr_type)) { + if (dim_val == 1) { + for (size_t i = 0; i < array_size; i++) { + std::vector res; + std::complex ele; + if(extract_value(ASRUtils::fetch_ArrayConstant_value(al, arr, i), ele)) { + for (int j = 0; j < ncopies; j++) { + res.push_back(b.complex_t(ele.real(), ele.imag(), arr_type)); + } + } + value = b.ArrayConstant(res, extract_type(arr_type), false); + res = {}; + m_eles.push_back(value); + } + } else if (dim_val == 2) { + for (int j = 0; j < ncopies; j++) { + std::vector res; + std::complex ele; + for (size_t i = 0; i < array_size; i++) { + if(extract_value(ASRUtils::fetch_ArrayConstant_value(al, arr, i), ele)) { + res.push_back(b.complex_t(ele.real(), ele.imag(), arr_type)); + } + } + value = b.ArrayConstant(res, extract_type(arr_type), false); + res = {}; + m_eles.push_back(value); + } + } + } + return b.ArrayConstant(m_eles, extract_type(type), false); + } else { + append_error(diag, "`dim` argument of `spread` intrinsic is not a valid dimension index", loc); + return nullptr; + } + } + + static inline ASR::asr_t* create_Spread(Allocator& al, const Location& loc, + Vec& args, diag::Diagnostics& diag) { + ASR::expr_t *source = args[0], *dim = args[1], *ncopies = args[2]; + bool is_scalar = false; + ASR::ttype_t *type_source = ASRUtils::type_get_past_allocatable_pointer(expr_type(source)); + ASR::ttype_t *type_dim = ASRUtils::type_get_past_allocatable_pointer(expr_type(dim)); + ASR::ttype_t *type_ncopies = ASRUtils::type_get_past_allocatable_pointer(expr_type(ncopies)); + ASR::ttype_t *ret_type = ASRUtils::type_get_past_allocatable_pointer(expr_type(source)); + + ASRBuilder b(al, loc); + int overload_id = 2; + if(ASR::is_a(*type_source) || ASR::is_a(*type_source) || + ASR::is_a(*type_source) || ASR::is_a(*type_source) ){ + // Case : When Scalar is passed as source in Spread() + is_scalar = true; + Vec m_eles; m_eles.reserve(al, 1); + m_eles.push_back(al, source); + ASR::ttype_t *fixed_size_type = b.Array({(int64_t) 1}, type_source); + source = EXPR(ASRUtils::make_ArrayConstructor_t_util(al, loc,m_eles.p, + m_eles.n, fixed_size_type, ASR::arraystorageType::ColMajor)); + type_source = ASRUtils::type_get_past_allocatable_pointer(expr_type(source)); + overload_id = -1; + } + + if ( !is_array(type_source) ) { + append_error(diag, "The argument `source` in `spread` must be of type Array", source->base.loc); + return nullptr; + } + if( !is_integer(*type_dim) ) { + append_error(diag, "The argument `dim` in `spread` must be of type Integer", dim->base.loc); + return nullptr; + } + if( !is_integer(*type_ncopies) ) { + append_error(diag, "The argument `ncopies` in `spread` must be of type Integer", ncopies->base.loc); + return nullptr; + } + ASR::dimension_t* source_dims = nullptr; + int source_rank = extract_dimensions_from_ttype(type_source, source_dims); + ASRUtils::require_impl(source_rank > 0, "The argument `source` in `spread` must be of rank > 0", source->base.loc, diag); + if( is_scalar ){ + Vec result_dims; result_dims.reserve(al, 1); + result_dims.push_back(al, b.set_dim(source_dims[0].m_start, ncopies)); + ret_type = ASRUtils::duplicate_type(al, ret_type, &result_dims); + } else { + Vec result_dims; + size_t n_dims = ASRUtils::extract_n_dims_from_ttype(type_source); + result_dims.reserve(al, (int) n_dims + 1); + Vec args_merge; args_merge.reserve(al, 3); + ASRUtils::ASRBuilder b(al, loc); + args_merge.push_back(al, ncopies); + args_merge.push_back(al, b.ArraySize(args[0], b.i32(1), int32)); + args_merge.push_back(al, b.Eq(dim, b.i32(1))); + ASR::expr_t* merge = EXPR(Merge::create_Merge(al, loc, args_merge, diag)); + ASR::dimension_t dim_; + dim_.loc = source->base.loc; + dim_.m_start = b.i32(1); + dim_.m_length = merge; + result_dims.push_back(al, dim_); + for( int it = 0; it < (int) n_dims; it++ ) { + Vec args_merge; args_merge.reserve(al, 3); + args_merge.push_back(al, ncopies); + args_merge.push_back(al, b.ArraySize(args[0], b.i32(it+1), int32)); + args_merge.push_back(al, b.Eq(dim, b.i32(it+2))); + ASR::expr_t* merge = EXPR(Merge::create_Merge(al, loc, args_merge, diag)); + ASR::dimension_t dim; + dim.loc = source->base.loc; + dim.m_start = b.i32(1); + dim.m_length = merge; + result_dims.push_back(al, dim); + } + ret_type = ASRUtils::duplicate_type(al, ret_type, &result_dims); + } + Vec m_args; m_args.reserve(al, 3); + m_args.push_back(al, source); m_args.push_back(al, dim); + m_args.push_back(al, ncopies); + ASR::expr_t *value = nullptr; + if (all_args_evaluated(m_args)) { + value = eval_Spread(al, loc, ret_type, m_args, diag); + } + return make_IntrinsicArrayFunction_t_util(al, loc, + static_cast(IntrinsicArrayFunctions::Spread), + m_args.p, m_args.n, overload_id, ret_type, value); + } + + static inline ASR::expr_t* instantiate_Spread(Allocator &al, + const Location &loc, SymbolTable *scope, + Vec &arg_types, ASR::ttype_t *return_type, + Vec &m_args, int64_t /*overload_id*/) { + declare_basic_variables("_lcompilers_spread"); + fill_func_arg("source", duplicate_type_with_empty_dims(al, arg_types[0])); + fill_func_arg("dim", arg_types[1]); + fill_func_arg("ncopies", arg_types[2]); + // TODO: this logic is incorrect, fix it. + /* + spread(source, dim, ncopies) + if (dim == 1) then + do j = 1, size(source) + ele = source(j) + do k = 1, ncopies + result(i) = ele + i = i + 1 + end do + end do + else if (dim == 2) then + do j = 1, ncopies + do k = 1, size(source) + ele = source(k) + result(i) = ele + i = i + 1 + end do + end do + end if + */ + if( !ASRUtils::is_fixed_size_array(return_type) ) { + int64_t n_dims_return_type = ASRUtils::extract_n_dims_from_ttype(return_type); + bool is_allocatable = ASRUtils::is_allocatable(return_type); + Vec empty_dims; + empty_dims.reserve(al, n_dims_return_type); + for( int idim = 0; idim < n_dims_return_type; idim++ ) { + ASR::dimension_t empty_dim; + empty_dim.loc = loc; + empty_dim.m_start = nullptr; + empty_dim.m_length = nullptr; + empty_dims.push_back(al, empty_dim); + } + return_type = ASRUtils::make_Array_t_util(al, loc, + ASRUtils::extract_type(return_type), empty_dims.p, empty_dims.size()); + if( is_allocatable ) { + return_type = ASRUtils::TYPE(ASRUtils::make_Allocatable_t_util(al, loc, return_type)); + } + } + ASR::expr_t *result = declare("result", return_type, Out); + args.push_back(al, result); + ASR::expr_t *i = declare("i", int32, Local); + ASR::expr_t *j = declare("j", int32, Local); + ASR::expr_t *k = declare("k", int32, Local); + body.push_back(al, b.Assignment(i, b.i32(1))); + body.push_back(al, b.If(b.Eq(args[1], b.i32(1)), { + b.DoLoop(j, b.i32(1), UBound(args[0], 1), { + b.DoLoop(k, b.i32(1), args[2], { + b.Assignment(b.ArrayItem_01(result, {i}), b.ArrayItem_01(args[0], {j})), + b.Assignment(i, b.Add(i, b.i32(1))), + }, nullptr), + }, nullptr), + }, { + b.DoLoop(j, b.i32(1), args[2], { + b.DoLoop(k, b.i32(1), UBound(args[0], 1), { + b.Assignment(b.ArrayItem_01(result, {i}), b.ArrayItem_01(args[0], {k})), + b.Assignment(i, b.Add(i, b.i32(1))), + }, nullptr), + }, nullptr), + })); + + body.push_back(al, b.Return()); + ASR::symbol_t *fn_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, + body, nullptr, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); + scope->add_symbol(fn_name, fn_sym); + return b.Call(fn_sym, m_args, return_type, nullptr); + } + +} // namespace Spread + +namespace Eoshift { + static inline void verify_args(const ASR::IntrinsicArrayFunction_t &x, + diag::Diagnostics &diagnostics) { + ASRUtils::require_impl(x.n_args == 2 || x.n_args == 3 || x.n_args == 4, + "`eoshift` intrinsic accepts atleast 2 and atmost 4 arguments", + x.base.base.loc, diagnostics); + ASRUtils::require_impl(x.m_args[0], "`array` argument of `eoshift` " + "cannot be nullptr", x.base.base.loc, diagnostics); + ASRUtils::require_impl(x.m_args[1], "`shift` argument of `eoshift` " + "cannot be nullptr", x.base.base.loc, diagnostics); + } + + static ASR::expr_t *eval_Eoshift(Allocator &al, const Location &loc, + ASR::ttype_t *type, Vec &args, diag::Diagnostics& /*diag*/) { + ASRBuilder b(al, loc); + if (all_args_evaluated(args) && + extract_n_dims_from_ttype(expr_type(args[0])) == 1) { + ASR::ArrayConstant_t *arr = ASR::down_cast(ASRUtils::expr_value(args[0])); + ASR::ttype_t* arr_type = expr_type(args[0]); + ASR::expr_t *final_boundary = args[2]; + ASR::ttype_t* boundary_type = expr_type(args[2]); + std::vector m_eles; + if (is_integer(*arr_type)) { + for (size_t i = 0; i < (size_t) ASRUtils::get_fixed_size_of_array(arr->m_type); i++) { + int ele = 0; + if(extract_value(ASRUtils::fetch_ArrayConstant_value(al, arr, i), ele)) { + m_eles.push_back(b.i_t(ele, arr_type)); + } + } + } else if (is_real(*arr_type)) { + for (size_t i = 0; i < (size_t) ASRUtils::get_fixed_size_of_array(arr->m_type); i++) { + double ele = 0; + if(extract_value(ASRUtils::fetch_ArrayConstant_value(al, arr, i), ele)) { + m_eles.push_back(b.f_t(ele, arr_type)); + } + } + } else if (is_logical(*arr_type)) { + for (size_t i = 0; i < (size_t) ASRUtils::get_fixed_size_of_array(arr->m_type); i++) { + bool ele = false; + if(extract_value(ASRUtils::fetch_ArrayConstant_value(al, arr, i), ele)) { + m_eles.push_back(b.bool_t(ele, arr_type)); + } + } + } else if (is_character(*arr_type)) { + std::string str = ""; + for (size_t i = 0; i < (size_t) ASRUtils::get_fixed_size_of_array(arr->m_type); i++) { + str = ASR::down_cast(ASRUtils::fetch_ArrayConstant_value(al, arr, i))->m_s; + m_eles.push_back(b.StringConstant(str, arr_type)); + } + int len_str = str.length(); + str = ""; + for(int i = 0; i < len_str; i++){ + str += " "; + } + if(is_logical(*boundary_type)){ + final_boundary = b.StringConstant(str, arr_type); + } + } + int shift = 0; + if (extract_value(expr_value(args[1]), shift)) { + if (shift < 0) { + std::rotate(m_eles.begin(), m_eles.begin() + m_eles.size() + shift, m_eles.end()); + for(int j = 0; j < (-1*shift); j++) { + m_eles[j] = final_boundary; + } + } else { + std::rotate(m_eles.begin(), m_eles.begin() + shift, m_eles.end()); + int i = m_eles.size() - 1; + for(int j = 0; j < shift; j++) { + m_eles[i] = final_boundary; + i--; + } + } + } + return b.ArrayConstant(m_eles, extract_type(type), false); + } else { + return nullptr; + } + } + + static inline ASR::asr_t* create_Eoshift(Allocator& al, const Location& loc, + Vec& args, diag::Diagnostics& diag) { + ASR::expr_t *array = args[0], *shift = args[1], *boundary = args[2], *dim = args[3]; + bool is_type_allocatable = false; + bool is_boundary_present = false; + bool is_dim_present = false; + if (ASRUtils::is_allocatable(array)) { + is_type_allocatable = true; + } + if (boundary) { + is_boundary_present = true; + } + if (dim) { + is_dim_present = true; + } + ASR::ttype_t *type_array = expr_type(array); + ASR::ttype_t *type_shift = expr_type(shift); + ASR::ttype_t *type_boundary = nullptr; + if(is_boundary_present){ + type_boundary = expr_type(boundary); + } + ASR::ttype_t *ret_type = expr_type(array); + if ( !is_array(type_array) ) { + append_error(diag, "The argument `array` in `eoshift` must be of type Array", array->base.loc); + return nullptr; + } + if( !is_integer(*type_shift) ) { + append_error(diag, "The argument `shift` in `eoshift` must be of type Integer", shift->base.loc); + return nullptr; + } + if( is_boundary_present && (!ASRUtils::check_equal_type(type_boundary, type_array))) { + append_error(diag, "'boundary' argument of 'eoshift' intrinsic must be a scalar of same type as array type", boundary->base.loc); + return nullptr; + } + ASR::dimension_t* array_dims = nullptr; + int array_rank = extract_dimensions_from_ttype(type_array, array_dims); + int array_dim = -1; + extract_value(array_dims[0].m_length, array_dim); + ASRUtils::require_impl(array_rank > 0, "The argument `array` in `eoshift` must be of rank > 0", array->base.loc, diag); + ASRBuilder b(al, loc); + Vec result_dims; result_dims.reserve(al, 1); + int overload_id = 2; + if (!is_dim_present) { + result_dims.push_back(al, b.set_dim(array_dims[0].m_start, array_dims[0].m_length)); + ret_type = ASRUtils::duplicate_type(al, ret_type, &result_dims); + } else { + result_dims.push_back(al, b.set_dim(dim, dim)); + ret_type = ASRUtils::duplicate_type(al, ret_type, &result_dims); + } + if (is_type_allocatable) { + ret_type = TYPE(ASRUtils::make_Allocatable_t_util(al, loc, ret_type)); + } + ASR::expr_t *final_boundary = nullptr; + if(is_boundary_present){ + final_boundary = boundary; + } + else{ + ASR::ttype_t *boundary_type = ASRUtils::extract_type(type_array); + if(is_integer(*type_array)) + final_boundary = b.i_t(0, boundary_type); + else if(is_real(*type_array)) + final_boundary = b.f_t(0.0, boundary_type); + else if(is_logical(*type_array)) + final_boundary = b.bool_t(false, boundary_type); + else if(is_character(*type_array)){ + final_boundary = b.StringConstant(" ", boundary_type); + } + } + Vec m_args; m_args.reserve(al, 3); + m_args.push_back(al, array); m_args.push_back(al, shift); m_args.push_back(al, final_boundary); + ASR::expr_t *value = nullptr; + if (all_args_evaluated(m_args)) { + value = eval_Eoshift(al, loc, ret_type, m_args, diag); + } + return make_IntrinsicArrayFunction_t_util(al, loc, + static_cast(IntrinsicArrayFunctions::Eoshift), + m_args.p, m_args.n, overload_id, ret_type, value); + } + + static inline ASR::expr_t* instantiate_Eoshift(Allocator &al, + const Location &loc, SymbolTable *scope, + Vec &arg_types, ASR::ttype_t *return_type, + Vec &m_args, int64_t /*overload_id*/) { + declare_basic_variables("_lcompilers_eoshift"); + fill_func_arg("array", duplicate_type_with_empty_dims(al, arg_types[0])); + fill_func_arg("shift", arg_types[1]); + fill_func_arg("boundary", arg_types[2]); + ASR::ttype_t* return_type_ = return_type; + /* + Eoshift(array, shift, boundary, dim) + int i = 0 + do j = shift, size(array) + result[i] = array[j] + i = i + 1 + end do + do j = 1, shift + result[i] = array[j] + i = i + 1 + end do + + if (shift >= 0) then + i = size(array) - shift + 1 + else + i = 1 + end if + + do j = 1, shift + result(i) = boundary + i = i + 1 + end do + */ + if( !ASRUtils::is_fixed_size_array(return_type) ) { + bool is_allocatable = ASRUtils::is_allocatable(return_type); + Vec empty_dims; + empty_dims.reserve(al, 2); + for( int idim = 0; idim < 2; idim++ ) { + ASR::dimension_t empty_dim; + empty_dim.loc = loc; + empty_dim.m_start = nullptr; + empty_dim.m_length = nullptr; + empty_dims.push_back(al, empty_dim); + } + return_type_ = ASRUtils::make_Array_t_util(al, loc, + ASRUtils::extract_type(return_type_), empty_dims.p, empty_dims.size()); + if( is_allocatable ) { + return_type_ = ASRUtils::TYPE(ASRUtils::make_Allocatable_t_util(al, loc, return_type_)); + } + } + ASR::expr_t *result = declare("result", return_type_, Out); + args.push_back(al, result); + ASR::expr_t *i = declare("i", int32, Local); + ASR::expr_t *j = declare("j", int32, Local); + ASR::expr_t* abs_shift = declare("z", int32, Local); + ASR::expr_t* abs_shift_val = declare("k", int32, Local); + ASR::expr_t* shift_val = declare("shift_val", int32, Local);; + ASR::expr_t* final_boundary = declare("final_boundary", character(2), Local); //TODO: It does not handle character type + ASR::expr_t* boundary = args[2]; + + body.push_back(al, b.Assignment(shift_val, args[1])); + body.push_back(al, b.Assignment(abs_shift, shift_val)); + body.push_back(al, b.Assignment(abs_shift_val, shift_val)); + + body.push_back(al, b.If(b.Lt(args[1], b.i32(0)), { + b.Assignment(shift_val, b.Add(shift_val, UBound(args[0], 1))), + b.Assignment(abs_shift, b.Mul(abs_shift, b.i32(-1))) + }, { + b.Assignment(shift_val, shift_val) + } + )); + body.push_back(al, b.Assignment(i, b.i32(1))); + body.push_back(al, b.DoLoop(j, b.Add(shift_val, b.i32(1)), UBound(args[0], 1), { + b.Assignment(b.ArrayItem_01(result, {i}), b.ArrayItem_01(args[0], {j})), + b.Assignment(i, b.Add(i, b.i32(1))), + }, nullptr)); + body.push_back(al, b.DoLoop(j, LBound(args[0], 1), b.Add(shift_val, b.i32(1)), { + b.Assignment(b.ArrayItem_01(result, {i}), b.ArrayItem_01(args[0], {j})), + b.Assignment(i, b.Add(i, b.i32(1))), + }, nullptr)); + + body.push_back(al, b.If(b.GtE(abs_shift_val, b.i32(0)), { + b.Assignment(i, UBound(args[0], 1)), + b.Assignment(i, b.Sub(i, abs_shift)), + b.Assignment(i, b.Add(i, b.i32(1))) + }, { + b.Assignment(i, b.i32(1)) + } + )); + + if(is_character(*expr_type(b.ArrayItem_01(args[0], {b.i32(1)}))) && is_logical(*expr_type(args[2]))){ + body.push_back(al, b.Assignment(final_boundary, b.StringConstant(" ", expr_type(b.ArrayItem_01(args[0], {b.i32(1)}))))); + body.push_back(al, b.DoLoop(j, b.i32(1), abs_shift, { + b.Assignment(b.ArrayItem_01(result, {i}), final_boundary), + b.Assignment(i, b.Add(i, b.i32(1))), + }, nullptr)); + + } + else{ + body.push_back(al, b.DoLoop(j, b.i32(1), abs_shift, { + b.Assignment(b.ArrayItem_01(result, {i}), boundary), + b.Assignment(i, b.Add(i, b.i32(1))), + }, nullptr)); + } + + body.push_back(al, b.Return()); + ASR::symbol_t *fn_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, + body, nullptr, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); + scope->add_symbol(fn_name, fn_sym); + return b.Call(fn_sym, m_args, return_type, nullptr); + } + +} // namespace Eoshift + + +namespace IanyIall { + + static inline void verify_array(ASR::expr_t* array, ASR::ttype_t* return_type, + const Location& loc, diag::Diagnostics& diagnostics, ASRUtils::IntrinsicArrayFunctions intrinsic_func_id) { + std::string intrinsic_func_name = ASRUtils::get_array_intrinsic_name(static_cast(intrinsic_func_id)); + ASR::ttype_t* array_type = ASRUtils::expr_type(array); + ASRUtils::require_impl(ASRUtils::is_integer(*array_type) && ASRUtils::extract_n_dims_from_ttype(array_type) > 0, + "`array` argument of `" + intrinsic_func_name + "` intrinsic must be an integer array, found: " + ASRUtils::get_type_code(array_type), + loc, diagnostics); + ASRUtils::require_impl(ASRUtils::is_integer(*return_type) && ASRUtils::extract_n_dims_from_ttype(return_type) == 0, + "`" + intrinsic_func_name + "` intrinsic must return a scalar integer output", loc, diagnostics); + } + + static inline void verify_array_dim(ASR::expr_t* array, ASR::expr_t* dim, + ASR::ttype_t* return_type, const Location& loc, diag::Diagnostics& diagnostics, ASRUtils::IntrinsicArrayFunctions intrinsic_func_id) { + std::string intrinsic_func_name = ASRUtils::get_array_intrinsic_name(static_cast(intrinsic_func_id)); + ASR::ttype_t* array_type = ASRUtils::expr_type(array); + ASRUtils::require_impl(ASRUtils::is_integer(*ASRUtils::type_get_past_pointer(array_type)) && ASRUtils::extract_n_dims_from_ttype(array_type) > 0, + "`array` argument of `" + intrinsic_func_name + "` intrinsic must be an integer array, found: " + ASRUtils::get_type_code(array_type), + loc, diagnostics); + + ASRUtils::require_impl(ASR::is_a(*ASRUtils::type_get_past_pointer(ASRUtils::expr_type(dim))), + "`dim` argument of `" + intrinsic_func_name + "` intrinsic must be an integer", loc, diagnostics); + + ASRUtils::require_impl(ASRUtils::is_integer(*return_type) && ASRUtils::extract_n_dims_from_ttype(array_type) == ASRUtils::extract_n_dims_from_ttype(return_type) + 1, + "`" + intrinsic_func_name + "` intrinsic must return an integer output with dimension " + "only 1 less than that of input array", loc, diagnostics); + } + + static inline void verify_array_dim_mask(ASR::expr_t* array, ASR::expr_t* dim, ASR::expr_t* mask, + ASR::ttype_t* return_type, const Location& loc, diag::Diagnostics& diagnostics, ASRUtils::IntrinsicArrayFunctions intrinsic_func_id) { + std::string intrinsic_func_name = ASRUtils::get_array_intrinsic_name(static_cast(intrinsic_func_id)); + ASR::ttype_t* array_type = ASRUtils::expr_type(array); + ASR::ttype_t* mask_type = ASRUtils::expr_type(mask); + ASRUtils::require_impl(ASRUtils::is_integer(*ASRUtils::type_get_past_pointer(array_type)) && ASRUtils::extract_n_dims_from_ttype(array_type) > 0, + "`array` argument of `" + intrinsic_func_name + "` intrinsic must be an integer array, found: " + ASRUtils::get_type_code(array_type), + loc, diagnostics); + + ASRUtils::require_impl(ASR::is_a(*ASRUtils::type_get_past_pointer(ASRUtils::expr_type(dim))), + "`dim` argument of `" + intrinsic_func_name + "` intrinsic must be an integer", loc, diagnostics); + + ASRUtils::require_impl(ASRUtils::is_logical(*ASRUtils::type_get_past_pointer(array_type)) && ASRUtils::extract_n_dims_from_ttype(array_type) == ASRUtils::extract_n_dims_from_ttype(mask_type), + "`mask` argument of `" + intrinsic_func_name + "` intrinsic must be a scalar or array of logical type, found: " + ASRUtils::get_type_code(array_type), + loc, diagnostics); + + ASRUtils::require_impl(ASRUtils::is_integer(*return_type) && ASRUtils::extract_n_dims_from_ttype(array_type) == ASRUtils::extract_n_dims_from_ttype(return_type) + 1, + "`" + intrinsic_func_name + "` intrinsic must return an integer output with dimension " + "only 1 less than that of input array", loc, diagnostics); + } + + static inline void verify_args(const ASR::IntrinsicArrayFunction_t& x, diag::Diagnostics& diagnostics, ASRUtils::IntrinsicArrayFunctions intrinsic_func_id) { + std::string intrinsic_func_name = ASRUtils::get_array_intrinsic_name(static_cast(intrinsic_func_id)); + ASRUtils::require_impl(x.m_args[0] != nullptr, "`array` argument to `" + intrinsic_func_name + "` intrinsic cannot be nullptr", + x.base.base.loc, diagnostics); + switch( x.m_overload_id ) { + case 0: { + verify_array(x.m_args[0], x.m_type, x.base.base.loc, diagnostics, intrinsic_func_id); + break; + } + case 1: { + ASRUtils::require_impl(x.n_args == 2 && x.m_args[1] != nullptr, + "`dim` argument to `" + intrinsic_func_name + "` intrinsic cannot be nullptr", + x.base.base.loc, diagnostics); + verify_array_dim(x.m_args[0], x.m_args[1], x.m_type, x.base.base.loc, diagnostics, intrinsic_func_id); + break; + } + case 2: { + ASRUtils::require_impl(x.n_args == 3 && x.m_args[1] != nullptr && x.m_args[2] != nullptr, + "`dim` and `mask` arguments to `" + intrinsic_func_name + "` intrinsic cannot be nullptr", + x.base.base.loc, diagnostics); + verify_array_dim_mask(x.m_args[0], x.m_args[1], x.m_args[2], x.m_type, x.base.base.loc, diagnostics, intrinsic_func_id); + break; + } + default: { + require_impl(false, "Unrecognised overload id in `" + intrinsic_func_name + "` intrinsic", + x.base.base.loc, diagnostics); + } + } + } + + static inline ASR::expr_t *eval_IanyIall(Allocator & al, + const Location & loc, ASR::ttype_t * t, Vec& args, + int64_t init_int_val, std::function logical_operation) { + ASR::expr_t *array = args[0]; + ASR::expr_t* value = nullptr; + if (array && ASR::is_a(*array)) { + ASR::ArrayConstant_t *arr = ASR::down_cast(array); + int64_t result = init_int_val; + for (size_t i = 0; i < (size_t) ASRUtils::get_fixed_size_of_array(arr->m_type); i++) { + ASR::expr_t *args_value = ASRUtils::fetch_ArrayConstant_value(al, arr, i); + if (args_value && ASR::is_a(*args_value)) { + result = logical_operation(result, ASR::down_cast(args_value)->m_n); + } else { + return nullptr; + } + } + value = ASRUtils::EXPR(ASR::make_IntegerConstant_t(al, + loc, result, t)); + } + return value; + } + + static inline ASR::asr_t* create_IanyIall(Allocator& al, const Location& loc, + Vec& args, diag::Diagnostics& diag, ASRUtils::IntrinsicArrayFunctions intrinsic_func_id, + int64_t init_int_val, std::function logical_operation) { + ASRUtils::ASRBuilder b(al, loc); + std::string intrinsic_func_name = ASRUtils::get_array_intrinsic_name(static_cast(intrinsic_func_id)); + int64_t overload_id = 0; + Vec iany_iall_args; iany_iall_args.reserve(al, 3); + + ASR::expr_t* array = args[0]; + ASR::expr_t* dim = nullptr; + ASR::expr_t* mask = nullptr; + if( args.size() == 2 ) { + dim = args[1]; + } else if ( args.size() == 3 ) { + dim = args[1]; + mask = args[2]; + } + if( ASRUtils::extract_n_dims_from_ttype(ASRUtils::expr_type(array)) == 0 ) { + append_error(diag, "`array` argument of `" + intrinsic_func_name + "` intrinsic must be an integer array", + array->base.loc); + return nullptr; + } + + ASR::expr_t *value = nullptr; + Vec arg_values; arg_values.reserve(al, 3); + arg_values.push_back(al, ASRUtils::expr_value(array)); + if ( dim ) arg_values.push_back(al, ASRUtils::expr_value(dim)); + if ( mask ) arg_values.push_back(al, ASRUtils::expr_value(mask)); + ASR::ttype_t* type = ASRUtils::type_get_past_allocatable( + ASRUtils::type_get_past_pointer(ASRUtils::expr_type(array))); + ASR::ttype_t* return_type = ASRUtils::duplicate_type_without_dims( + al, type, loc); + if( dim ) { + overload_id = 1; + size_t n_dims = ASRUtils::extract_n_dims_from_ttype(ASRUtils::expr_type(array)); + Vec dims; dims.reserve(al, (int) n_dims - 1); + for( int i = 0; i < (int) n_dims - 1; i++ ) { + ASR::dimension_t d; + d.loc = array->base.loc; + d.m_length = nullptr; + d.m_start = nullptr; + dims.push_back(al, d); + } + if( dims.size() > 0 ) { + return_type = ASRUtils::make_Array_t_util(al, loc, + return_type, dims.p, dims.size()); + } + } + if( mask ) { + overload_id = 2; + } + value = eval_IanyIall(al, loc, return_type, arg_values, init_int_val, logical_operation); + iany_iall_args.push_back(al, array); + if( dim ) iany_iall_args.push_back(al, dim); + if ( mask ) iany_iall_args.push_back(al, mask); + + return ASRUtils::make_IntrinsicArrayFunction_t_util(al, loc, + static_cast(intrinsic_func_id), + iany_iall_args.p, iany_iall_args.n, overload_id, return_type, value); + } + + static inline void generate_body_for_scalar_output(Allocator& al, const Location& loc, + ASR::expr_t* array, ASR::expr_t* return_var, SymbolTable* fn_scope, + Vec& fn_body, ASR::expr_t* init_int_val, elemental_operation_func elemental_operation) { + ASRBuilder builder(al, loc); + Vec idx_vars; + Vec doloop_body; + + builder.generate_reduction_intrinsic_stmts_for_scalar_output(loc, + array, fn_scope, fn_body, idx_vars, doloop_body, + [=, &al, &fn_body, &builder] () { + ASR::stmt_t* return_var_init = builder.Assignment(return_var, init_int_val); + fn_body.push_back(al, return_var_init); + }, + [=, &al, &idx_vars, &doloop_body, &builder] () { + ASR::expr_t* array_ref = PassUtils::create_array_ref(array, idx_vars, al); + ASR::expr_t* logical_op = (builder.*elemental_operation)(return_var, array_ref); + ASR::stmt_t* loop_invariant = builder.Assignment(return_var, logical_op); + doloop_body.push_back(al, loop_invariant); + } + ); + } + + static inline void generate_body_for_array_output(Allocator& al, const Location& loc, + ASR::expr_t* array, ASR::expr_t* dim, ASR::expr_t* result, + SymbolTable* fn_scope, Vec& fn_body, + ASR::expr_t* init_int_val, elemental_operation_func elemental_operation) { + ASRBuilder builder(al, loc); + Vec idx_vars, target_idx_vars; + Vec doloop_body; + builder.generate_reduction_intrinsic_stmts_for_array_output( + loc, array, dim, fn_scope, fn_body, + idx_vars, target_idx_vars, doloop_body, + [=, &al, &fn_body, &builder] { + ASR::stmt_t* result_init = builder.Assignment(result, init_int_val); + fn_body.push_back(al, result_init); + }, + [=, &al, &idx_vars, &target_idx_vars, &doloop_body, &result, &builder] () { + ASR::expr_t* result_ref = PassUtils::create_array_ref(result, target_idx_vars, al); + ASR::expr_t* array_ref = PassUtils::create_array_ref(array, idx_vars, al); + ASR::expr_t* logical_op = (builder.*elemental_operation)(result_ref, array_ref); + ASR::stmt_t* loop_invariant = builder.Assignment(result_ref, logical_op); + doloop_body.push_back(al, loop_invariant); + } + ); + } + + static inline ASR::expr_t* instantiate_IanyIall(Allocator &al, const Location &loc, + SymbolTable *scope, Vec& arg_types, ASR::ttype_t *return_type, + Vec& new_args, int64_t overload_id, ASRUtils::IntrinsicArrayFunctions intrinsic_func_id, + ASR::expr_t* initial_value, elemental_operation_func elemental_operation) { + std::string intrinsic_func_name = ASRUtils::get_array_intrinsic_name(static_cast(intrinsic_func_id)); + ASRBuilder builder(al, loc); + ASRBuilder& b = builder; + ASR::ttype_t* arg_type = arg_types[0]; + int kind = ASRUtils::extract_kind_from_ttype_t(arg_type); + int rank = ASRUtils::extract_n_dims_from_ttype(arg_type); + std::string new_name = intrinsic_func_name + "_" + std::to_string(kind) + + "_" + std::to_string(rank) + + "_" + std::to_string(overload_id); + // Check if Function is already defined. + { + std::string new_func_name = new_name; + int i = 1; + while (scope->get_symbol(new_func_name) != nullptr) { + ASR::symbol_t *s = scope->get_symbol(new_func_name); + ASR::Function_t *f = ASR::down_cast(s); + int orig_array_rank = ASRUtils::extract_n_dims_from_ttype( + ASRUtils::expr_type(f->m_args[0])); + bool same_allocatable_type = (ASRUtils::is_allocatable(arg_type) == + ASRUtils::is_allocatable(ASRUtils::expr_type(f->m_args[0]))); + if (same_allocatable_type && ASRUtils::types_equal(ASRUtils::expr_type(f->m_args[0]), + ASRUtils::expr_type(new_args[0].m_value), true) && orig_array_rank == rank) { + return builder.Call(s, new_args, return_type, nullptr); + } else { + new_func_name += std::to_string(i); + i++; + } + } + } + + new_name = scope->get_unique_name(new_name, false); + SymbolTable *fn_symtab = al.make_new(scope); + + Vec args; + int result_dims = 0; + { + args.reserve(al, 1); + ASR::ttype_t* array_type = ASRUtils::duplicate_type_with_empty_dims(al, arg_type); + fill_func_arg("array", array_type); + if( overload_id == 1 ) { + ASR::ttype_t* dim_type = ASRUtils::expr_type(new_args[1].m_value); + LCOMPILERS_ASSERT(ASR::is_a(*dim_type)); + [[maybe_unused]] int kind = ASRUtils::extract_kind_from_ttype_t(dim_type); + LCOMPILERS_ASSERT(kind == 4); + fill_func_arg("dim", dim_type); + + Vec dims; + size_t n_dims = ASRUtils::extract_n_dims_from_ttype(arg_type); + dims.reserve(al, (int) n_dims - 1); + for( int i = 0; i < (int) n_dims - 1; i++ ) { + ASR::dimension_t dim; + dim.loc = new_args[0].m_value->base.loc; + dim.m_length = nullptr; + dim.m_start = nullptr; + dims.push_back(al, dim); + } + result_dims = dims.size(); + if( result_dims > 0 ) { + fill_func_arg("result", return_type); + } + } else if ( overload_id == 2 ) { + ASR::ttype_t* dim_type = ASRUtils::expr_type(new_args[1].m_value); + LCOMPILERS_ASSERT(ASR::is_a(*dim_type)); + [[maybe_unused]] int kind = ASRUtils::extract_kind_from_ttype_t(dim_type); + LCOMPILERS_ASSERT(kind == 4); + fill_func_arg("dim", dim_type); + + Vec dims; + size_t n_dims = ASRUtils::extract_n_dims_from_ttype(arg_type); + dims.reserve(al, (int) n_dims - 1); + for( int i = 0; i < (int) n_dims - 1; i++ ) { + ASR::dimension_t dim; + dim.loc = new_args[0].m_value->base.loc; + dim.m_length = nullptr; + dim.m_start = nullptr; + dims.push_back(al, dim); + } + ASR::ttype_t* mask_type = ASRUtils::expr_type(new_args[2].m_value); + fill_func_arg("mask", mask_type); + result_dims = dims.size(); + if( result_dims > 0 ) { + fill_func_arg("result", return_type); + } + } + } + + ASR::expr_t* return_var = nullptr; + if( result_dims == 0 ) { + return_var = declare(new_name, return_type, ReturnVar); + } + + Vec body; + body.reserve(al, 1); + if( overload_id == 0 || return_var ) { + generate_body_for_scalar_output(al, loc, args[0], return_var, fn_symtab, body, + initial_value, elemental_operation); + } else if( overload_id == 1 ) { + generate_body_for_array_output(al, loc, args[0], args[1], args[2], fn_symtab, body, + initial_value, elemental_operation); + } else { + LCOMPILERS_ASSERT(false); + } + + Vec dep; + dep.reserve(al, 1); + + ASR::symbol_t *new_symbol = nullptr; + if( return_var ) { + new_symbol = make_ASR_Function_t(new_name, fn_symtab, dep, args, + body, return_var, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); + } else { + new_symbol = make_Function_Without_ReturnVar_t( + new_name, fn_symtab, dep, args, + body, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); + } + scope->add_symbol(new_name, new_symbol); + return builder.Call(new_symbol, new_args, return_type, nullptr); + } + +} // namespace IanyIall + +namespace Iany { + + static inline void verify_args(const ASR::IntrinsicArrayFunction_t& x, diag::Diagnostics& diagnostics) { + IanyIall::verify_args(x, diagnostics, ASRUtils::IntrinsicArrayFunctions::Iany); + } + + static inline ASR::expr_t *eval_Iany(Allocator & al, + const Location & loc, ASR::ttype_t *t, Vec& args, + diag::Diagnostics& /*diag*/) { + ASRBuilder b(al, loc); + return IanyIall::eval_IanyIall(al, loc, t, args, 0, std::bit_or()); + } + + static inline ASR::asr_t* create_Iany(Allocator& al, const Location& loc, + Vec& args, diag::Diagnostics& diag) { + return IanyIall::create_IanyIall(al, loc, args, diag, ASRUtils::IntrinsicArrayFunctions::Iany, 0, std::bit_or()); + } + + static inline ASR::expr_t* instantiate_Iany(Allocator &al, + const Location &loc, SymbolTable *scope, Vec& arg_types, + ASR::ttype_t *return_type, Vec& new_args, + int64_t overload_id) { + ASRBuilder b(al, loc); + return IanyIall::instantiate_IanyIall(al, loc, scope, arg_types, return_type, + new_args, overload_id, ASRUtils::IntrinsicArrayFunctions::Iany, + b.i_t(0, return_type), &ASRBuilder::Or); + } + +} // namespace Iany + +namespace Iall { + + static inline void verify_args(const ASR::IntrinsicArrayFunction_t& x, diag::Diagnostics& diagnostics) { + IanyIall::verify_args(x, diagnostics, ASRUtils::IntrinsicArrayFunctions::Iall); + } + + static inline ASR::expr_t *eval_Iall(Allocator & al, + const Location & loc, ASR::ttype_t *t, Vec& args, + diag::Diagnostics& /*diag*/) { + return IanyIall::eval_IanyIall(al, loc, t, args, 1, std::bit_and()); + } + + static inline ASR::asr_t* create_Iall(Allocator& al, const Location& loc, + Vec& args, diag::Diagnostics& diag) { + return IanyIall::create_IanyIall(al, loc, args, diag, ASRUtils::IntrinsicArrayFunctions::Iall, 1, std::bit_and()); + } + + static inline ASR::expr_t* instantiate_Iall(Allocator &al, + const Location &loc, SymbolTable *scope, Vec& arg_types, + ASR::ttype_t *return_type, Vec& new_args, + int64_t overload_id) { + ASRBuilder b(al, loc); + return IanyIall::instantiate_IanyIall(al, loc, scope, arg_types, return_type, + new_args, overload_id, ASRUtils::IntrinsicArrayFunctions::Iall, + b.i_t(1, return_type), &ASRBuilder::And); + } + +} // namespace Iall + +namespace AnyAll { + static inline void verify_array(ASR::expr_t* array, ASR::ttype_t* return_type, - const Location& loc, diag::Diagnostics& diagnostics) { + const Location& loc, diag::Diagnostics& diagnostics, ASRUtils::IntrinsicArrayFunctions intrinsic_func_id) { + std::string intrinsic_func_name = ASRUtils::get_array_intrinsic_name(static_cast(intrinsic_func_id)); ASR::ttype_t* array_type = ASRUtils::expr_type(array); - ASRUtils::require_impl(ASRUtils::is_logical(*array_type), - "Input to Any intrinsic must be of logical type, found: " + ASRUtils::get_type_code(array_type), - loc, diagnostics); - int array_n_dims = ASRUtils::extract_n_dims_from_ttype(array_type); - ASRUtils::require_impl(array_n_dims > 0, "Input to Any intrinsic must always be an array", + ASRUtils::require_impl(ASRUtils::is_logical(*array_type) && ASRUtils::extract_n_dims_from_ttype(array_type) > 0, + "`mask` argument of `" + intrinsic_func_name + "` intrinsic must be a logical array, found: " + ASRUtils::get_type_code(array_type), loc, diagnostics); - ASRUtils::require_impl(ASRUtils::is_logical(*return_type), - "Any intrinsic must return a logical output", loc, diagnostics); - int return_n_dims = ASRUtils::extract_n_dims_from_ttype(return_type); - ASRUtils::require_impl(return_n_dims == 0, - "Any intrinsic output for array only input should be a scalar", - loc, diagnostics); + + ASRUtils::require_impl(ASRUtils::is_logical(*return_type) && ASRUtils::extract_n_dims_from_ttype(return_type) == 0, + "`" + intrinsic_func_name + "` intrinsic must return a scalar logical output", loc, diagnostics); } static inline void verify_array_dim(ASR::expr_t* array, ASR::expr_t* dim, - ASR::ttype_t* return_type, const Location& loc, diag::Diagnostics& diagnostics) { + ASR::ttype_t* return_type, const Location& loc, diag::Diagnostics& diagnostics, ASRUtils::IntrinsicArrayFunctions intrinsic_func_id) { + std::string intrinsic_func_name = ASRUtils::get_array_intrinsic_name(static_cast(intrinsic_func_id)); ASR::ttype_t* array_type = ASRUtils::expr_type(array); - ASRUtils::require_impl(ASRUtils::is_logical(*ASRUtils::type_get_past_pointer(array_type)), - "Input to Any intrinsic must be of logical type, found: " + ASRUtils::get_type_code(array_type), - loc, diagnostics); - int array_n_dims = ASRUtils::extract_n_dims_from_ttype(array_type); - ASRUtils::require_impl(array_n_dims > 0, "Input to Any intrinsic must always be an array", + ASRUtils::require_impl(ASRUtils::is_logical(*ASRUtils::type_get_past_pointer(array_type)) && ASRUtils::extract_n_dims_from_ttype(array_type) > 0, + "`mask` argument of `" + intrinsic_func_name + "` intrinsic must be a logical array, found: " + ASRUtils::get_type_code(array_type), loc, diagnostics); ASRUtils::require_impl(ASR::is_a(*ASRUtils::type_get_past_pointer(ASRUtils::expr_type(dim))), - "dim argument must be an integer", loc, diagnostics); - - ASRUtils::require_impl(ASRUtils::is_logical(*return_type), - "Any intrinsic must return a logical output", loc, diagnostics); - int return_n_dims = ASRUtils::extract_n_dims_from_ttype(return_type); - ASRUtils::require_impl(array_n_dims == return_n_dims + 1, - "Any intrinsic output must return a logical array with dimension " - "only 1 less than that of input array", - loc, diagnostics); + "`dim` argument of `" + intrinsic_func_name + "` intrinsic must be an integer", loc, diagnostics); + + ASRUtils::require_impl(ASRUtils::is_logical(*return_type) && ASRUtils::extract_n_dims_from_ttype(array_type) == ASRUtils::extract_n_dims_from_ttype(return_type) + 1, + "`" + intrinsic_func_name + "` intrinsic must return a logical output with dimension " + "only 1 less than that of input array", loc, diagnostics); } - static inline void verify_args(const ASR::IntrinsicArrayFunction_t& x, diag::Diagnostics& diagnostics) { - ASRUtils::require_impl(x.n_args >= 1, "Any intrinsic must accept at least one argument", - x.base.base.loc, diagnostics); - ASRUtils::require_impl(x.m_args[0] != nullptr, "Array argument to any intrinsic cannot be nullptr", + static inline void verify_args(const ASR::IntrinsicArrayFunction_t& x, diag::Diagnostics& diagnostics, ASRUtils::IntrinsicArrayFunctions intrinsic_func_id) { + std::string intrinsic_func_name = ASRUtils::get_array_intrinsic_name(static_cast(intrinsic_func_id)); + ASRUtils::require_impl(x.m_args[0] != nullptr, "`mask` argument to `" + intrinsic_func_name + "` intrinsic cannot be nullptr", x.base.base.loc, diagnostics); switch( x.m_overload_id ) { case 0: { - verify_array(x.m_args[0], x.m_type, x.base.base.loc, diagnostics); + verify_array(x.m_args[0], x.m_type, x.base.base.loc, diagnostics, intrinsic_func_id); break; } case 1: { ASRUtils::require_impl(x.n_args == 2 && x.m_args[1] != nullptr, - "dim argument to any intrinsic cannot be nullptr", + "`dim` argument to `" + intrinsic_func_name + "` intrinsic cannot be nullptr", x.base.base.loc, diagnostics); - verify_array_dim(x.m_args[0], x.m_args[1], x.m_type, x.base.base.loc, diagnostics); + verify_array_dim(x.m_args[0], x.m_args[1], x.m_type, x.base.base.loc, diagnostics, intrinsic_func_id); break; } default: { - require_impl(false, "Unrecognised overload id in Any intrinsic", + require_impl(false, "Unrecognised overload id in `" + intrinsic_func_name + "` intrinsic", x.base.base.loc, diagnostics); } } } - static inline ASR::expr_t *eval_Any(Allocator & /*al*/, - const Location & /*loc*/, ASR::ttype_t */*t*/, Vec& /*args*/, - diag::Diagnostics& /*diag*/) { - return nullptr; + static inline ASR::expr_t *eval_AnyAll(Allocator & al, + const Location & loc, ASR::ttype_t * /*t*/, Vec& args, + bool init_logical_val, std::function logical_operation) { + ASR::expr_t *mask = args[0]; + ASR::expr_t* value = nullptr; + ASR::ttype_t *type = ASRUtils::TYPE(ASR::make_Logical_t(al, loc, 4)); + if (mask && ASR::is_a(*mask)) { + ASR::ArrayConstant_t *array = ASR::down_cast(mask); + bool result = init_logical_val; + for (size_t i = 0; i < (size_t) ASRUtils::get_fixed_size_of_array(array->m_type); i++) { + ASR::expr_t *args_value = ASRUtils::fetch_ArrayConstant_value(al, array, i); + if (args_value && ASR::is_a(*args_value)) { + result = logical_operation(result, ASR::down_cast(args_value)->m_value); + } else { + return nullptr; + } + } + value = ASRUtils::EXPR(ASR::make_LogicalConstant_t(al, + loc, result, type)); + } + return value; } - static inline ASR::asr_t* create_Any( - Allocator& al, const Location& loc, Vec& args, - diag::Diagnostics& diag) { + static inline ASR::asr_t* create_AnyAll(Allocator& al, const Location& loc, + Vec& args, diag::Diagnostics& diag, ASRUtils::IntrinsicArrayFunctions intrinsic_func_id, + bool init_logical_val, std::function logical_operation) { + std::string intrinsic_func_name = ASRUtils::get_array_intrinsic_name(static_cast(intrinsic_func_id)); int64_t overload_id = 0; - Vec any_args; - any_args.reserve(al, 2); + Vec any_all_args; any_all_args.reserve(al, 2); - ASR::expr_t* array = args[0]; - ASR::expr_t* axis = nullptr; + ASR::expr_t* mask = args[0]; + ASR::expr_t* dim = nullptr; if( args.size() == 2 ) { - axis = args[1]; + dim = args[1]; } - if( ASRUtils::extract_n_dims_from_ttype(ASRUtils::expr_type(array)) == 0 ) { - append_error(diag, "mask argument to any must be an array and must not be a scalar", - array->base.loc); + if( ASRUtils::extract_n_dims_from_ttype(ASRUtils::expr_type(mask)) == 0 ) { + append_error(diag, "`mask` argument of `" + intrinsic_func_name + "` intrinsic must be a logical array", + mask->base.loc); return nullptr; } - // TODO: Add a check for range of values axis can take - // if axis is available at compile time - ASR::expr_t *value = nullptr; - Vec arg_values; - arg_values.reserve(al, 2); - ASR::expr_t *array_value = ASRUtils::expr_value(array); - arg_values.push_back(al, array_value); - if( axis ) { - ASR::expr_t *axis_value = ASRUtils::expr_value(axis); - arg_values.push_back(al, axis_value); - } + Vec arg_values; arg_values.reserve(al, 2); + arg_values.push_back(al, ASRUtils::expr_value(mask)); + if( dim ) arg_values.push_back(al, ASRUtils::expr_value(dim)); - ASR::ttype_t* logical_return_type = nullptr; - if( axis == nullptr ) { - overload_id = 0; - logical_return_type = ASRUtils::TYPE(ASR::make_Logical_t( - al, loc, 4)); - } else { + ASR::ttype_t* logical_return_type = logical; + if( dim ) { overload_id = 1; - Vec dims; - size_t n_dims = ASRUtils::extract_n_dims_from_ttype(ASRUtils::expr_type(array)); - dims.reserve(al, (int) n_dims - 1); + size_t n_dims = ASRUtils::extract_n_dims_from_ttype(ASRUtils::expr_type(mask)); + Vec dims; dims.reserve(al, (int) n_dims - 1); for( int i = 0; i < (int) n_dims - 1; i++ ) { - ASR::dimension_t dim; - dim.loc = array->base.loc; - dim.m_length = nullptr; - dim.m_start = nullptr; - dims.push_back(al, dim); + ASR::dimension_t d; + d.loc = mask->base.loc; + d.m_length = nullptr; + d.m_start = nullptr; + dims.push_back(al, d); } if( dims.size() > 0 ) { logical_return_type = ASRUtils::make_Array_t_util(al, loc, - ASRUtils::TYPE(ASR::make_Logical_t(al, loc, 4)), dims.p, dims.size()); - } else { - logical_return_type = ASRUtils::TYPE(ASR::make_Logical_t(al, loc, 4)); + logical, dims.p, dims.size()); } } - value = eval_Any(al, loc, logical_return_type, arg_values, diag); - any_args.push_back(al, array); - if( axis ) { - any_args.push_back(al, axis); - } + value = eval_AnyAll(al, loc, logical_return_type, arg_values, init_logical_val, logical_operation); + any_all_args.push_back(al, mask); + if( dim ) any_all_args.push_back(al, dim); return ASRUtils::make_IntrinsicArrayFunction_t_util(al, loc, - static_cast(ASRUtils::IntrinsicArrayFunctions::Any), - any_args.p, any_args.n, overload_id, logical_return_type, value); + static_cast(intrinsic_func_id), + any_all_args.p, any_all_args.n, overload_id, logical_return_type, value); } static inline void generate_body_for_scalar_output(Allocator& al, const Location& loc, ASR::expr_t* array, ASR::expr_t* return_var, SymbolTable* fn_scope, - Vec& fn_body) { + Vec& fn_body, ASR::expr_t* init_logical_val, elemental_operation_func elemental_operation) { ASRBuilder builder(al, loc); Vec idx_vars; Vec doloop_body; + builder.generate_reduction_intrinsic_stmts_for_scalar_output(loc, array, fn_scope, fn_body, idx_vars, doloop_body, [=, &al, &fn_body, &builder] () { - ASR::expr_t* logical_false = make_ConstantWithKind( - make_LogicalConstant_t, make_Logical_t, false, 4, loc); - ASR::stmt_t* return_var_init = builder.Assignment(return_var, logical_false); + ASR::stmt_t* return_var_init = builder.Assignment(return_var, init_logical_val); fn_body.push_back(al, return_var_init); }, [=, &al, &idx_vars, &doloop_body, &builder] () { ASR::expr_t* array_ref = PassUtils::create_array_ref(array, idx_vars, al); - ASR::expr_t* logical_or = builder.LogicalOr(return_var, array_ref, loc); - ASR::stmt_t* loop_invariant = builder.Assignment(return_var, logical_or); + ASR::expr_t* logical_op = (builder.*elemental_operation)(return_var, array_ref); + ASR::stmt_t* loop_invariant = builder.Assignment(return_var, logical_op); doloop_body.push_back(al, loop_invariant); } ); @@ -1230,7 +2896,8 @@ namespace Any { static inline void generate_body_for_array_output(Allocator& al, const Location& loc, ASR::expr_t* array, ASR::expr_t* dim, ASR::expr_t* result, - SymbolTable* fn_scope, Vec& fn_body) { + SymbolTable* fn_scope, Vec& fn_body, + ASR::expr_t* init_logical_val, elemental_operation_func elemental_operation) { ASRBuilder builder(al, loc); Vec idx_vars, target_idx_vars; Vec doloop_body; @@ -1238,29 +2905,30 @@ namespace Any { loc, array, dim, fn_scope, fn_body, idx_vars, target_idx_vars, doloop_body, [=, &al, &fn_body, &builder] { - ASR::expr_t* logical_false = make_ConstantWithKind( - make_LogicalConstant_t, make_Logical_t, false, 4, loc); - ASR::stmt_t* result_init = builder.Assignment(result, logical_false); + ASR::stmt_t* result_init = builder.Assignment(result, init_logical_val); fn_body.push_back(al, result_init); }, [=, &al, &idx_vars, &target_idx_vars, &doloop_body, &result, &builder] () { ASR::expr_t* result_ref = PassUtils::create_array_ref(result, target_idx_vars, al); ASR::expr_t* array_ref = PassUtils::create_array_ref(array, idx_vars, al); - ASR::expr_t* logical_or = builder.ElementalOr(result_ref, array_ref, loc); - ASR::stmt_t* loop_invariant = builder.Assignment(result_ref, logical_or); + ASR::expr_t* logical_op = (builder.*elemental_operation)(result_ref, array_ref); + ASR::stmt_t* loop_invariant = builder.Assignment(result_ref, logical_op); doloop_body.push_back(al, loop_invariant); - }); + } + ); } - static inline ASR::expr_t* instantiate_Any(Allocator &al, const Location &loc, - SymbolTable *scope, Vec& arg_types, ASR::ttype_t *logical_return_type, - Vec& new_args, int64_t overload_id) { + static inline ASR::expr_t* instantiate_AnyAll(Allocator &al, const Location &loc, + SymbolTable *scope, Vec& arg_types, ASR::ttype_t *logical_return_type, + Vec& new_args, int64_t overload_id, ASRUtils::IntrinsicArrayFunctions intrinsic_func_id, + ASR::expr_t* initial_value, elemental_operation_func elemental_operation) { + std::string intrinsic_func_name = ASRUtils::get_array_intrinsic_name(static_cast(intrinsic_func_id)); ASRBuilder builder(al, loc); ASRBuilder& b = builder; ASR::ttype_t* arg_type = arg_types[0]; int kind = ASRUtils::extract_kind_from_ttype_t(arg_type); int rank = ASRUtils::extract_n_dims_from_ttype(arg_type); - std::string new_name = "any_" + std::to_string(kind) + + std::string new_name = intrinsic_func_name + "_" + std::to_string(kind) + "_" + std::to_string(rank) + "_" + std::to_string(overload_id); // Check if Function is already defined. @@ -1272,8 +2940,10 @@ namespace Any { ASR::Function_t *f = ASR::down_cast(s); int orig_array_rank = ASRUtils::extract_n_dims_from_ttype( ASRUtils::expr_type(f->m_args[0])); - if (ASRUtils::types_equal(ASRUtils::expr_type(f->m_args[0]), - arg_type) && orig_array_rank == rank) { + bool same_allocatable_type = (ASRUtils::is_allocatable(arg_type) == + ASRUtils::is_allocatable(ASRUtils::expr_type(f->m_args[0]))); + if (same_allocatable_type && ASRUtils::types_equal(ASRUtils::expr_type(f->m_args[0]), + ASRUtils::expr_type(new_args[0].m_value), true) && orig_array_rank == rank) { return builder.Call(s, new_args, logical_return_type, nullptr); } else { new_func_name += std::to_string(i); @@ -1310,7 +2980,7 @@ namespace Any { } result_dims = dims.size(); if( result_dims > 0 ) { - fill_func_arg("result", logical_return_type); + fill_func_arg_sub("result", logical_return_type, Out); } } } @@ -1323,16 +2993,17 @@ namespace Any { Vec body; body.reserve(al, 1); if( overload_id == 0 || return_var ) { - generate_body_for_scalar_output(al, loc, args[0], return_var, fn_symtab, body); + generate_body_for_scalar_output(al, loc, args[0], return_var, fn_symtab, body, + initial_value, elemental_operation); } else if( overload_id == 1 ) { - generate_body_for_array_output(al, loc, args[0], args[1], args[2], fn_symtab, body); + generate_body_for_array_output(al, loc, args[0], args[1], args[2], fn_symtab, body, + initial_value, elemental_operation); } else { LCOMPILERS_ASSERT(false); } Vec dep; dep.reserve(al, 1); - // TODO: fill dependencies ASR::symbol_t *new_symbol = nullptr; if( return_var ) { @@ -1347,8 +3018,64 @@ namespace Any { return builder.Call(new_symbol, new_args, logical_return_type, nullptr); } +} // namespace AnyAll + +namespace Any { + + static inline void verify_args(const ASR::IntrinsicArrayFunction_t& x, diag::Diagnostics& diagnostics) { + AnyAll::verify_args(x, diagnostics, ASRUtils::IntrinsicArrayFunctions::Any); + } + + static inline ASR::expr_t *eval_Any(Allocator & al, + const Location & loc, ASR::ttype_t *, Vec& args, + diag::Diagnostics& /*diag*/) { + return AnyAll::eval_AnyAll(al, loc, nullptr, args, false, std::logical_or()); + } + + static inline ASR::asr_t* create_Any(Allocator& al, const Location& loc, + Vec& args, diag::Diagnostics& diag) { + return AnyAll::create_AnyAll(al, loc, args, diag, ASRUtils::IntrinsicArrayFunctions::Any, false, std::logical_or()); + } + + static inline ASR::expr_t* instantiate_Any(Allocator &al, + const Location &loc, SymbolTable *scope, Vec& arg_types, + ASR::ttype_t *return_type, Vec& new_args, + int64_t overload_id) { + return AnyAll::instantiate_AnyAll(al, loc, scope, arg_types, return_type, + new_args, overload_id, ASRUtils::IntrinsicArrayFunctions::Any, + make_ConstantWithKind(make_LogicalConstant_t, make_Logical_t, false, 4, loc), &ASRBuilder::Or); + } + } // namespace Any +namespace All { + + static inline void verify_args(const ASR::IntrinsicArrayFunction_t& x, diag::Diagnostics& diagnostics) { + AnyAll::verify_args(x, diagnostics, ASRUtils::IntrinsicArrayFunctions::All); + } + + static inline ASR::expr_t *eval_All(Allocator & al, + const Location & loc, ASR::ttype_t *, Vec& args, + diag::Diagnostics& /*diag*/) { + return AnyAll::eval_AnyAll(al, loc, nullptr, args, true, std::logical_and()); + } + + static inline ASR::asr_t* create_All(Allocator& al, const Location& loc, + Vec& args, diag::Diagnostics& diag) { + return AnyAll::create_AnyAll(al, loc, args, diag, ASRUtils::IntrinsicArrayFunctions::All, true, std::logical_and()); + } + + static inline ASR::expr_t* instantiate_All(Allocator &al, + const Location &loc, SymbolTable *scope, Vec& arg_types, + ASR::ttype_t *return_type, Vec& new_args, + int64_t overload_id) { + return AnyAll::instantiate_AnyAll(al, loc, scope, arg_types, return_type, + new_args, overload_id, ASRUtils::IntrinsicArrayFunctions::All, + make_ConstantWithKind(make_LogicalConstant_t, make_Logical_t, true, 4, loc), &ASRBuilder::And); + } + +} // namespace All + namespace Sum { static inline void verify_args(const ASR::IntrinsicArrayFunction_t& x, @@ -1357,15 +3084,24 @@ namespace Sum { &ArrIntrinsic::verify_array_int_real_cmplx); } - static inline ASR::expr_t *eval_Sum(Allocator & /*al*/, - const Location & /*loc*/, ASR::ttype_t *, Vec& /*args*/, - diag::Diagnostics& /*diag*/) { - return nullptr; + static inline ASR::expr_t *eval_Sum(Allocator & al, + const Location & loc, ASR::ttype_t *t, Vec& args, + diag::Diagnostics& diag) { + return ArrIntrinsic::eval_ArrIntrinsic(al, loc, t, args, diag, + IntrinsicArrayFunctions::Sum); } static inline ASR::asr_t* create_Sum(Allocator& al, const Location& loc, - Vec& args, - diag::Diagnostics& diag) { + Vec& args, diag::Diagnostics& diag) { + ASR::ttype_t* array_type = expr_type(args[0]); + if (!is_integer(*array_type) && !is_real(*array_type) && !is_complex(*array_type)) { + diag.add(diag::Diagnostic("Input to `Sum` is expected to be numeric, but got " + + type_to_str_fortran(array_type), + diag::Level::Error, + diag::Stage::Semantic, + {diag::Label("must be integer, real or complex type", { args[0]->base.loc })})); + return nullptr; + } return ArrIntrinsic::create_ArrIntrinsic(al, loc, args, diag, IntrinsicArrayFunctions::Sum); } @@ -1376,7 +3112,7 @@ namespace Sum { int64_t overload_id) { return ArrIntrinsic::instantiate_ArrIntrinsic(al, loc, scope, arg_types, return_type, new_args, overload_id, IntrinsicArrayFunctions::Sum, - &get_constant_zero_with_given_type, &ASRBuilder::ElementalAdd); + &get_constant_zero_with_given_type, &ASRBuilder::Add); } } // namespace Sum @@ -1389,15 +3125,24 @@ namespace Product { &ArrIntrinsic::verify_array_int_real_cmplx); } - static inline ASR::expr_t *eval_Product(Allocator & /*al*/, - const Location & /*loc*/, ASR::ttype_t *, Vec& /*args*/, - diag::Diagnostics& /*diag*/) { - return nullptr; + static inline ASR::expr_t *eval_Product(Allocator & al, + const Location & loc, ASR::ttype_t *t, Vec& args, + diag::Diagnostics& diag) { + return ArrIntrinsic::eval_ArrIntrinsic(al, loc, t, args, diag, + IntrinsicArrayFunctions::Product); } static inline ASR::asr_t* create_Product(Allocator& al, const Location& loc, - Vec& args, - diag::Diagnostics& diag) { + Vec& args, diag::Diagnostics& diag) { + ASR::ttype_t* array_type = expr_type(args[0]); + if (!is_integer(*array_type) && !is_real(*array_type) && !is_complex(*array_type)) { + diag.add(diag::Diagnostic("Input to `Product` is expected to be numeric, but got " + + type_to_str_fortran(array_type), + diag::Level::Error, + diag::Stage::Semantic, + {diag::Label("must be integer, real or complex type", { args[0]->base.loc })})); + return nullptr; + } return ArrIntrinsic::create_ArrIntrinsic(al, loc, args, diag, IntrinsicArrayFunctions::Product); } @@ -1408,11 +3153,52 @@ namespace Product { int64_t overload_id) { return ArrIntrinsic::instantiate_ArrIntrinsic(al, loc, scope, arg_types, return_type, new_args, overload_id, IntrinsicArrayFunctions::Product, - &get_constant_one_with_given_type, &ASRBuilder::ElementalMul); + &get_constant_one_with_given_type, &ASRBuilder::Mul); } } // namespace Product +namespace Iparity { + + static inline void verify_args(const ASR::IntrinsicArrayFunction_t& x, + diag::Diagnostics& diagnostics) { + ArrIntrinsic::verify_args(x, diagnostics, IntrinsicArrayFunctions::Iparity, + &ArrIntrinsic::verify_array_int_real_cmplx); + } + + static inline ASR::expr_t *eval_Iparity(Allocator & al, + const Location & loc, ASR::ttype_t *t, Vec& args, + diag::Diagnostics& diag) { + return ArrIntrinsic::eval_ArrIntrinsic(al, loc, t, args, diag, + IntrinsicArrayFunctions::Iparity); + } + + static inline ASR::asr_t* create_Iparity(Allocator& al, const Location& loc, + Vec& args, diag::Diagnostics& diag) { + ASR::ttype_t* array_type = expr_type(args[0]); + if (!is_integer(*array_type)) { + diag.add(diag::Diagnostic("Input to `Iparity` is expected to be an integer, but got " + + type_to_str_fortran(array_type), + diag::Level::Error, + diag::Stage::Semantic, + {diag::Label("must be of integer type", { args[0]->base.loc })})); + return nullptr; + } + return ArrIntrinsic::create_ArrIntrinsic(al, loc, args, diag, + IntrinsicArrayFunctions::Iparity); + } + + static inline ASR::expr_t* instantiate_Iparity(Allocator &al, + const Location &loc, SymbolTable *scope, Vec& arg_types, + ASR::ttype_t *return_type, Vec& new_args, + int64_t overload_id) { + return ArrIntrinsic::instantiate_ArrIntrinsic(al, loc, scope, arg_types, + return_type, new_args, overload_id, IntrinsicArrayFunctions::Iparity, + &get_constant_zero_with_given_type, &ASRBuilder::Xor); + } + +} // namespace Iparity + namespace MaxVal { static inline void verify_args(const ASR::IntrinsicArrayFunction_t& x, @@ -1421,15 +3207,25 @@ namespace MaxVal { &ArrIntrinsic::verify_array_int_real); } - static inline ASR::expr_t *eval_MaxVal(Allocator & /*al*/, - const Location & /*loc*/, ASR::ttype_t *, Vec& /*args*/, - diag::Diagnostics& /*diag*/) { - return nullptr; + static inline ASR::expr_t *eval_MaxVal(Allocator & al, + const Location & loc, ASR::ttype_t *t, Vec& args, + diag::Diagnostics& diag) { + return ArrIntrinsic::eval_ArrIntrinsic(al, loc, t, args, diag, + IntrinsicArrayFunctions::MaxVal); } static inline ASR::asr_t* create_MaxVal(Allocator& al, const Location& loc, Vec& args, diag::Diagnostics& diag) { + ASR::ttype_t* array_type = expr_type(args[0]); + if (!is_integer(*array_type) && !is_real(*array_type) && !is_character(*array_type)) { + diag.add(diag::Diagnostic("Input to `MaxVal` is expected to be of integer, real or character type, but got " + + type_to_str_fortran(array_type), + diag::Level::Error, + diag::Stage::Semantic, + {diag::Label("must be integer, real or character type", { args[0]->base.loc })})); + return nullptr; + } return ArrIntrinsic::create_ArrIntrinsic(al, loc, args, diag, IntrinsicArrayFunctions::MaxVal); } @@ -1440,7 +3236,7 @@ namespace MaxVal { int64_t overload_id) { return ArrIntrinsic::instantiate_ArrIntrinsic(al, loc, scope, arg_types, return_type, new_args, overload_id, IntrinsicArrayFunctions::MaxVal, - &get_minimum_value_with_given_type, &ASRBuilder::ElementalMax); + &get_minimum_value_with_given_type, &ASRBuilder::Max); } } // namespace MaxVal @@ -1452,23 +3248,425 @@ namespace MaxLoc { ArrIntrinsic::verify_MaxMinLoc_args(x, diagnostics); } - static inline ASR::asr_t* create_MaxLoc(Allocator& al, const Location& loc, - Vec& args, - diag::Diagnostics& diag) { - return ArrIntrinsic::create_MaxMinLoc(al, loc, args, - static_cast(IntrinsicArrayFunctions::MaxLoc), diag); + static inline ASR::asr_t* create_MaxLoc(Allocator& al, const Location& loc, + Vec& args, diag::Diagnostics& diag) { + return ArrIntrinsic::create_MaxMinLoc(al, loc, args, + IntrinsicArrayFunctions::MaxLoc, diag); + } + + static inline ASR::expr_t *instantiate_MaxLoc(Allocator &al, + const Location &loc, SymbolTable *scope, + Vec& arg_types, ASR::ttype_t *return_type, + Vec& m_args, int64_t overload_id) { + return ArrIntrinsic::instantiate_MaxMinLoc(al, loc, scope, + IntrinsicArrayFunctions::MaxLoc, arg_types, return_type, + m_args, overload_id); + } + +} // namespace MaxLoc + +namespace MinLoc { + + static inline void verify_args(const ASR::IntrinsicArrayFunction_t& x, + diag::Diagnostics& diagnostics) { + ArrIntrinsic::verify_MaxMinLoc_args(x, diagnostics); + } + + static inline ASR::asr_t* create_MinLoc(Allocator& al, const Location& loc, + Vec& args, diag::Diagnostics& diag) { + return ArrIntrinsic::create_MaxMinLoc(al, loc, args, + IntrinsicArrayFunctions::MinLoc, diag); + } + + static inline ASR::expr_t *instantiate_MinLoc(Allocator &al, + const Location &loc, SymbolTable *scope, + Vec& arg_types, ASR::ttype_t *return_type, + Vec& m_args, int64_t overload_id) { + return ArrIntrinsic::instantiate_MaxMinLoc(al, loc, scope, + IntrinsicArrayFunctions::MinLoc, arg_types, return_type, + m_args, overload_id); + } + +} // namespace MinLoc + +namespace FindLoc { + + static inline void verify_args(const ASR::IntrinsicArrayFunction_t& x, + diag::Diagnostics& diagnostics) { + require_impl(x.n_args >= 2 && x.n_args <= 6, "`findloc` intrinsic " + "takes at least two arguments", x.base.base.loc, diagnostics); + require_impl(x.m_args[0] != nullptr, "`array` argument of `findloc` " + "intrinsic cannot be nullptr", x.base.base.loc, diagnostics); + require_impl(x.m_args[1] != nullptr, "`value` argument of `findloc` " + "intrinsic cannot be nullptr", x.base.base.loc, diagnostics); + } + + static inline ASR::expr_t *eval_FindLoc(Allocator &al, const Location &loc, + ASR::ttype_t *type, Vec &args) { + ASRBuilder b(al, loc); + ASR::expr_t* array = args[0]; + ASR::expr_t* value = args[1]; + ASR::expr_t* dim = args[2]; + ASR::expr_t* mask = args[3]; + ASR::expr_t* back = args[5]; + if (!array) return nullptr; + if (!value) return nullptr; + if (extract_n_dims_from_ttype(expr_type(array)) == 1) { + int arr_size = 0; + ASR::expr_t* array_value = ASRUtils::expr_value(array); + ASR::expr_t* value_value = ASRUtils::expr_value(value); + ASR::ArrayConstant_t *array_value_constant = nullptr; + if (array_value && value_value && + ASR::is_a(*array_value) + ) { + array_value_constant = ASR::down_cast(array_value); + arr_size = ASRUtils::get_fixed_size_of_array(array_value_constant->m_type); + } else { + return nullptr; + } + ASR::expr_t* mask_value = ASRUtils::expr_value(mask); + ASR::ArrayConstant_t *mask_value_constant = nullptr; + if (mask && ASR::is_a(*mask)) { + mask_value_constant = ASR::down_cast(mask_value); + } else if (mask && ASR::is_a(*mask)) { + bool mask_val = ASR::down_cast(mask_value)->m_value; + if (mask_val == false) return b.i_t(0, type); + mask_value_constant = ASR::down_cast(b.ArrayConstant({b.bool_t(mask_val, logical)}, logical, false)); + } else { + std::vector mask_data; + for (int i = 0; i < arr_size; i++) { + mask_data.push_back(b.bool_t(true, logical)); + } + mask_value_constant = ASR::down_cast(b.ArrayConstant(mask_data, logical, false)); + } + ASR::expr_t* back_value = ASRUtils::expr_value(back); + ASR::LogicalConstant_t *back_value_constant = ASR::down_cast(back_value); + // index "-1" indicates that the element is not found + int element_idx = -1; + if (is_character(*expr_type(array))) { + std::string ele = ASR::down_cast(value_value)->m_s; + for (int i = 0; i < arr_size; i++) { + if (((bool*)mask_value_constant->m_data)[i] != 0) { + std::string ele2 = ASR::down_cast(ASRUtils::fetch_ArrayConstant_value(al, array_value_constant, i))->m_s; + if (ele.compare(ele2) == 0) { + element_idx = i; + if (!(back_value_constant && back_value_constant->m_value)) break; + } + } + } + } else if (is_complex(*expr_type(array))) { + double re, im; + re = ASR::down_cast(value_value)->m_re; + im = ASR::down_cast(value_value)->m_im; + for (int i = 0; i < arr_size; i++) { + if (((bool*)mask_value_constant->m_data)[i] != 0) { + double re2 = ASR::down_cast(ASRUtils::fetch_ArrayConstant_value(al, array_value_constant, i))->m_re; + double im2 = ASR::down_cast(ASRUtils::fetch_ArrayConstant_value(al, array_value_constant, i))->m_im; + if (re == re2 && im == im2) { + element_idx = i; + if (!(back_value_constant && back_value_constant->m_value)) break; + } + } + } + } else { + double ele = 0; + if (is_integer(*ASRUtils::expr_type(value_value))) { + ele = ASR::down_cast(value_value)->m_n; + } else if (is_real(*ASRUtils::expr_type(value))) { + ele = ASR::down_cast(value_value)->m_r; + } else if (is_logical(*ASRUtils::expr_type(value))) { + ele = ASR::down_cast(value_value)->m_value; + } + for (int i = 0; i < arr_size; i++) { + if (((bool*)mask_value_constant->m_data)[i] != 0) { + double ele2 = 0; + if (extract_value(ASRUtils::fetch_ArrayConstant_value(al, array_value_constant, i), ele2)) { + if (ele == ele2) { + element_idx = i; + if (!(back_value_constant && back_value_constant->m_value)) break; + } + } + } + } + } + if (ASR::down_cast(dim) -> m_n != -1) { + return b.i_t(element_idx + 1, type); + } + return b.ArrayConstant({b.i32(element_idx + 1)}, extract_type(type), false); + } else { + return nullptr; + } + } + + static inline ASR::asr_t* create_FindLoc(Allocator& al, const Location& loc, + Vec& args, diag::Diagnostics& diag) { + int64_t array_value_id = 0, array_value_mask = 1, array_value_dim = 2, array_value_dim_mask = 3; + int64_t overload_id = array_value_id; + ASRUtils::ASRBuilder b(al, loc); + ASR::expr_t* array = nullptr; + ASR::expr_t* value = nullptr; + if (extract_kind_from_ttype_t(expr_type(args[0])) != extract_kind_from_ttype_t(expr_type(args[1]))){ + Vec args_; + args_.reserve(al, 2); + args_.push_back(al, args[0]); + args_.push_back(al, args[1]); + promote_arguments_kinds(al, loc, args_, diag); + array = args_[0]; + value = args_[1]; + } + else { + array = args[0]; + value = args[1]; + } + ASR::ttype_t *array_type = expr_type(array); + ASR::ttype_t *value_type = expr_type(value); + if (is_real(*array_type) && is_integer(*value_type)){ + if (ASR::is_a(*value)){ + ASR::IntegerConstant_t *value_int = ASR::down_cast(value); + value = EXPR(ASR::make_RealConstant_t(al, loc, value_int->m_n, + ASRUtils::TYPE(ASR::make_Real_t(al, loc, extract_kind_from_ttype_t(value_type))))); + } else{ + value = EXPR(ASR::make_Cast_t(al, loc, value, ASR::cast_kindType::IntegerToReal, + ASRUtils::TYPE(ASR::make_Real_t(al, loc, extract_kind_from_ttype_t(value_type))), nullptr )); + } + } else if (is_integer(*array_type) && is_real(*value_type)){ + if (ASR::is_a(*value)){ + ASR::RealConstant_t *value_int = ASR::down_cast(value); + value = EXPR(ASR::make_IntegerConstant_t(al, loc, value_int->m_r, + ASRUtils::TYPE(ASR::make_Integer_t(al, loc, extract_kind_from_ttype_t(value_type))))); + } else{ + value = EXPR(ASR::make_Cast_t(al, loc, value, ASR::cast_kindType::RealToInteger, + ASRUtils::TYPE(ASR::make_Integer_t(al, loc, extract_kind_from_ttype_t(value_type))), nullptr )); + } + } + if (!is_array(array_type) && !is_integer(*array_type) && !is_real(*array_type) && !is_character(*array_type) && !is_logical(*array_type) && !is_complex(*array_type)) { + append_error(diag, "`array` argument of `findloc` must be an array of integer, " + "real, logical, character or complex type", loc); + return nullptr; + } + if (is_array(value_type) || ( !is_integer(*value_type) && !is_real(*value_type) && !is_character(*value_type) && !is_logical(*value_type) && !is_complex(*array_type))) { + append_error(diag, "`value` argument of `findloc` must be a scalar of integer, " + "real, logical, character or complex type", loc); + return nullptr; + } + ASR::ttype_t *return_type = nullptr; + Vec m_args; m_args.reserve(al, 6); + m_args.push_back(al, array); + m_args.push_back(al, value); + Vec result_dims; result_dims.reserve(al, 1); + ASR::dimension_t *m_dims; + int n_dims = extract_dimensions_from_ttype(array_type, m_dims); + int dim = 0, kind = 4; // default kind + ASR::expr_t *dim_expr = nullptr; + ASR::expr_t *mask_expr = nullptr; + + // Checking for type findLoc(Array, value, mask) + if( args[2] && !args[3] && is_logical(*expr_type(args[2])) ){ + dim_expr = nullptr; + mask_expr = args[2]; + } + else { + dim_expr = args[2]; + mask_expr = args[3]; + } + + if (dim_expr) { + if ( !ASR::is_a(*expr_type(dim_expr)) ) { + dim = ASR::down_cast(dim_expr) -> m_n; + append_error(diag, "`dim` should be a scalar integer type", dim_expr->base.loc); + return nullptr; + } else if (!extract_value(expr_value(dim_expr), dim)) { + append_error(diag, "Runtime values for `dim` argument is not supported yet", dim_expr->base.loc); + return nullptr; + } + if ( dim < 1 || dim > n_dims ) { + append_error(diag, "`dim` argument of `findloc` is out of " + "array index range", dim_expr->base.loc); + return nullptr; + } + if ( n_dims == 1 ) { + return_type = TYPE(ASR::make_Integer_t(al, loc, kind)); // 1D + } else { + for ( int i = 1; i <= n_dims; i++ ) { + if ( i == dim ) { + continue; + } + ASR::dimension_t tmp_dim; + tmp_dim.loc = args[0]->base.loc; + tmp_dim.m_start = m_dims[i - 1].m_start; + tmp_dim.m_length = m_dims[i - 1].m_length; + result_dims.push_back(al, tmp_dim); + } + } + m_args.push_back(al, dim_expr); + } else { + ASR::dimension_t tmp_dim; + tmp_dim.loc = args[0]->base.loc; + tmp_dim.m_start = b.i32(1); + tmp_dim.m_length = b.i32(n_dims); + result_dims.push_back(al, tmp_dim); + m_args.push_back(al, b.i32(-1)); + } + if (mask_expr) { + if (!is_logical(*expr_type(mask_expr))) { + append_error(diag, "`mask` argument of `findloc` must be logical", mask_expr->base.loc); + return nullptr; + } + m_args.push_back(al, mask_expr); + } else { + m_args.push_back(al, b.ArrayConstant({b.bool_t(1, logical)}, logical, true)); + } + if (args[4]) { + if (!extract_value(expr_value(args[4]), kind)) { + append_error(diag, "Runtime value for `kind` argument is not supported yet", args[4]->base.loc); + return nullptr; + } + int kind = ASR::down_cast(ASRUtils::expr_value(args[4]))->m_n; + ASRUtils::set_kind_to_ttype_t(return_type, kind); + m_args.push_back(al, args[4]); + } else { + m_args.push_back(al, b.i32(4)); + } + if (args[5]) { + if (!ASR::is_a(*expr_type(args[5]))) { + append_error(diag, "`back` argument of `findloc` must be a logical scalar", args[5]->base.loc); + return nullptr; + } + m_args.push_back(al, args[5]); + } else { + m_args.push_back(al, b.bool_t(false, logical)); + } + + if (dim_expr) { + overload_id = array_value_dim; + } + if (mask_expr) { + overload_id = array_value_mask; + } + if (dim_expr && mask_expr) { + overload_id = array_value_dim_mask; + } + if ( !return_type ) { + return_type = duplicate_type(al, TYPE( + ASR::make_Integer_t(al, loc, kind)), &result_dims); + } + ASR::expr_t *m_value = nullptr; + m_value = eval_FindLoc(al, loc, return_type, m_args); + return make_IntrinsicArrayFunction_t_util(al, loc, + static_cast(IntrinsicArrayFunctions::FindLoc), + m_args.p, m_args.n, overload_id, return_type, m_value); } - static inline ASR::expr_t *instantiate_MaxLoc(Allocator &al, + static inline ASR::expr_t *instantiate_FindLoc(Allocator &al, const Location &loc, SymbolTable *scope, Vec& arg_types, ASR::ttype_t *return_type, Vec& m_args, int64_t overload_id) { - return ArrIntrinsic::instantiate_MaxMinLoc(al, loc, scope, - static_cast(IntrinsicArrayFunctions::MaxLoc), arg_types, return_type, - m_args, overload_id); + declare_basic_variables("_lcompilers_findloc") + /* + *findloc(array, value, dim, mask, kind, back) + * index = 0; + * do i = 1, size(arr)) + * if (arr[i] == value) then + * index = i; + * end if + * end do + */ + ASR::ttype_t* array_type = ASRUtils::duplicate_type_with_empty_dims(al, arg_types[0]); + ASR::ttype_t* mask_type = ASRUtils::duplicate_type_with_empty_dims(al, arg_types[3]); + fill_func_arg("array", array_type); + fill_func_arg("value", arg_types[1]); + fill_func_arg("dim", arg_types[2]); + fill_func_arg("mask", mask_type); + fill_func_arg("kind", arg_types[4]); + fill_func_arg("back", arg_types[5]); + ASR::expr_t* result = nullptr; + result = declare("result", ASRUtils::duplicate_type_with_empty_dims( + al, return_type, ASR::array_physical_typeType::DescriptorArray, true), Out); + args.push_back(al, result); + ASR::ttype_t *type = ASRUtils::extract_type(return_type); + ASR::expr_t *i = declare("i", type, Local); + ASR::expr_t *j = declare("j", type, Local); + ASR::expr_t *found_value = declare("found_value", logical, Local); + ASR::expr_t *array = args[0]; + ASR::expr_t *value = args[1]; + ASR::expr_t* dim = args[2]; + ASR::expr_t *mask = args[3]; + ASR::expr_t *back = args[5]; + if (overload_id == 1) { + ASR::expr_t *mask_new = nullptr; + if( ASRUtils::is_array(ASRUtils::expr_type(mask)) ){ + mask_new = ArrayItem_02(mask, i); + } + else{ + mask_new = mask; + } + body.push_back(al, b.Assignment(result, b.i_t(0, ASRUtils::type_get_past_array(return_type)))); + body.push_back(al, b.DoLoop(i, b.i_t(1, type), UBound(array, 1), { + b.If(b.And(b.Eq(ArrayItem_02(array, i), value), b.Eq(mask_new, b.bool_t(1, logical))), { + b.Assignment(result, i), + b.If(b.NotEq(back, b.bool_t(1, logical)), { + b.Return() + }, {}) + }, {}) + })); + } else { + int array_rank = ASRUtils::extract_n_dims_from_ttype(array_type); + ASR::ttype_t* ret_type = ASRUtils::type_get_past_array(return_type); + if (array_rank == 1) { + body.push_back(al, b.Assignment(result, b.i_t(0, ret_type))); + body.push_back(al, b.DoLoop(i, b.i_t(1, type), UBound(array, 1), { + b.If(b.Eq(ArrayItem_02(array, i), value), { + b.Assignment(result, i), + b.If(b.NotEq(back, b.bool_t(1, logical)), { + b.Return() + }, {}) + }, {}) + })); + } else if (array_rank == 2) { + Vec idx_vars_ij; idx_vars_ij.reserve(al, 2); + Vec idx_vars_ji; idx_vars_ji.reserve(al, 2); + idx_vars_ij.push_back(al, i); idx_vars_ij.push_back(al, j); + idx_vars_ji.push_back(al, j); idx_vars_ji.push_back(al, i); + body.push_back(al, b.Assignment(result, b.i_t(0, ret_type))); + body.push_back(al, b.If(b.Eq(dim, b.i_t(1, ret_type)), { + b.DoLoop(i, b.i_t(1, ret_type), UBound(array, 2), { + b.Assignment(found_value, b.bool_t(0, logical)), + b.DoLoop(j, b.i_t(1, ret_type), UBound(array, 1), { + b.If(b.Eq(ArrayItem_02(array, idx_vars_ji), value), { + b.Assignment(b.ArrayItem_01(result, {i}), j), + b.Assignment(found_value, b.bool_t(1, logical)), + }, {}), + b.If(b.And(found_value, b.Not(back)), { + b.Exit() + }, {}) + }) + }) + }, { + b.DoLoop(i, b.i_t(1, ret_type), UBound(array, 1), { + b.Assignment(found_value, b.bool_t(0, logical)), + b.DoLoop(j, b.i_t(1, ret_type), UBound(array, 2), { + b.If(b.Eq(ArrayItem_02(array, idx_vars_ij), value), { + b.Assignment(b.ArrayItem_01(result, {i}), j), + b.Assignment(found_value, b.bool_t(1, logical)), + }, {}), + b.If(b.And(found_value, b.Not(back)), { + b.Exit() + }, {}) + }) + }) + })); + } } -} // namespace MaxLoc + body.push_back(al, b.Return()); + ASR::expr_t* return_var = nullptr; + ASR::symbol_t *fn_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, + body, return_var, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); + scope->add_symbol(fn_name, fn_sym); + return b.Call(fn_sym, m_args, return_type, nullptr); +} + +} // namespace Findloc namespace MinVal { @@ -1478,15 +3676,25 @@ namespace MinVal { &ArrIntrinsic::verify_array_int_real); } - static inline ASR::expr_t *eval_MinVal(Allocator & /*al*/, - const Location & /*loc*/, ASR::ttype_t *, Vec& /*args*/, - diag::Diagnostics& /*diag*/) { - return nullptr; + static inline ASR::expr_t *eval_MinVal(Allocator & al, + const Location & loc, ASR::ttype_t *t, Vec& args, + diag::Diagnostics& diag) { + return ArrIntrinsic::eval_ArrIntrinsic(al, loc, t, args, diag, + IntrinsicArrayFunctions::MinVal); } static inline ASR::asr_t* create_MinVal(Allocator& al, const Location& loc, Vec& args, diag::Diagnostics& diag) { + ASR::ttype_t* array_type = expr_type(args[0]); + if (!is_integer(*array_type) && !is_real(*array_type) && !is_character(*array_type)) { + diag.add(diag::Diagnostic("Input to `MinVal` is expected to be of integer, real or character type, but got " + + type_to_str_fortran(array_type), + diag::Level::Error, + diag::Stage::Semantic, + {diag::Label("must be integer, real or character type", { args[0]->base.loc })})); + return nullptr; + } return ArrIntrinsic::create_ArrIntrinsic(al, loc, args, diag, IntrinsicArrayFunctions::MinVal); } @@ -1497,41 +3705,16 @@ namespace MinVal { int64_t overload_id) { return ArrIntrinsic::instantiate_ArrIntrinsic(al, loc, scope, arg_types, return_type, new_args, overload_id, IntrinsicArrayFunctions::MinVal, - &get_maximum_value_with_given_type, &ASRBuilder::ElementalMin); + &get_maximum_value_with_given_type, &ASRBuilder::Min); } } // namespace MinVal -namespace MinLoc { - - static inline void verify_args(const ASR::IntrinsicArrayFunction_t& x, - diag::Diagnostics& diagnostics) { - ArrIntrinsic::verify_MaxMinLoc_args(x, diagnostics); - } - - static inline ASR::asr_t* create_MinLoc(Allocator& al, const Location& loc, - Vec& args, - diag::Diagnostics& diag) { - return ArrIntrinsic::create_MaxMinLoc(al, loc, args, - static_cast(IntrinsicArrayFunctions::MinLoc), diag); - } - - static inline ASR::expr_t *instantiate_MinLoc(Allocator &al, - const Location &loc, SymbolTable *scope, - Vec& arg_types, ASR::ttype_t *return_type, - Vec& m_args, int64_t overload_id) { - return ArrIntrinsic::instantiate_MaxMinLoc(al, loc, scope, - static_cast(IntrinsicArrayFunctions::MinLoc), arg_types, return_type, - m_args, overload_id); - } - -} // namespace MinLoc - namespace MatMul { static inline void verify_args(const ASR::IntrinsicArrayFunction_t &x, diag::Diagnostics& diagnostics) { - require_impl(x.n_args == 2, "`matmul` intrinsic accepts exactly" + require_impl(x.n_args == 2, "`matmul` intrinsic accepts exactly " "two arguments", x.base.base.loc, diagnostics); require_impl(x.m_args[0], "`matrix_a` argument of `matmul` intrinsic " "cannot be nullptr", x.base.base.loc, diagnostics); @@ -1666,7 +3849,7 @@ namespace MatMul { } ret_type = ASRUtils::duplicate_type(al, ret_type, &result_dims); if (is_type_allocatable) { - ret_type = TYPE(ASR::make_Allocatable_t(al, loc, ret_type)); + ret_type = TYPE(ASRUtils::make_Allocatable_t_util(al, loc, ret_type)); } ASR::expr_t *value = eval_MatMul(al, loc, ret_type, args, diag); return make_IntrinsicArrayFunction_t_util(al, loc, @@ -1707,7 +3890,7 @@ namespace MatMul { return_type_ = ASRUtils::make_Array_t_util(al, loc, ASRUtils::extract_type(return_type_), empty_dims.p, empty_dims.size()); if( is_allocatable ) { - return_type_ = ASRUtils::TYPE(ASR::make_Allocatable_t(al, loc, return_type_)); + return_type_ = ASRUtils::TYPE(ASRUtils::make_Allocatable_t_util(al, loc, return_type_)); } } ASR::expr_t *result = declare("result", return_type_, Out); @@ -1721,7 +3904,7 @@ namespace MatMul { extract_dimensions_from_ttype(arg_types[1], matrix_b_dims); ASR::expr_t *res_ref, *a_ref, *b_ref, *a_lbound, *b_lbound; ASR::expr_t *dim_mismatch_check, *a_ubound, *b_ubound; - dim_mismatch_check = b.iEq(UBound(args[0], 2), UBound(args[1], 1)); + dim_mismatch_check = b.Eq(UBound(args[0], 2), UBound(args[1], 1)); a_lbound = LBound(args[0], 1); a_ubound = UBound(args[0], 1); b_lbound = LBound(args[1], 2); b_ubound = UBound(args[1], 2); std::string assert_msg = "'MatMul' intrinsic dimension mismatch: " @@ -1734,7 +3917,7 @@ namespace MatMul { b_ref = b.ArrayItem_01(args[1], {k, j}); a_ubound = a_lbound; alloc_dims.push_back(al, b.set_dim(LBound(args[1], 2), UBound(args[1], 2))); - dim_mismatch_check = b.iEq(UBound(args[0], 1), UBound(args[1], 1)); + dim_mismatch_check = b.Eq(UBound(args[0], 1), UBound(args[1], 1)); assert_msg += "`matrix_a(k)` and `matrix_b(k, j)`"; } else if ( overload_id == 2 ) { // r(i) = r(i) + a(i, k) * b(k) @@ -1761,96 +3944,300 @@ namespace MatMul { character(assert_msg.size())))))); ASR::expr_t *mul_value; if (is_real(*expr_type(a_ref)) && is_integer(*expr_type(b_ref))) { - mul_value = b.Mul(a_ref, b.i2r(b_ref, expr_type(a_ref))); + mul_value = b.Mul(a_ref, b.i2r_t(b_ref, expr_type(a_ref))); } else if (is_real(*expr_type(b_ref)) && is_integer(*expr_type(a_ref))) { - mul_value = b.Mul(b.i2r(a_ref, expr_type(b_ref)), b_ref); + mul_value = b.Mul(b.i2r_t(a_ref, expr_type(b_ref)), b_ref); } else if (is_real(*expr_type(a_ref)) && is_complex(*expr_type(b_ref))){ - mul_value = b.Mul(EXPR(ASR::make_ComplexConstructor_t(al, loc, a_ref, b.f(0, expr_type(a_ref)), expr_type(b_ref), nullptr)), b_ref); + mul_value = b.Mul(EXPR(ASR::make_ComplexConstructor_t(al, loc, a_ref, b.f_t(0, expr_type(a_ref)), expr_type(b_ref), nullptr)), b_ref); } else if (is_complex(*expr_type(a_ref)) && is_real(*expr_type(b_ref))){ - mul_value = b.Mul(a_ref, EXPR(ASR::make_ComplexConstructor_t(al, loc, b_ref, b.f(0, expr_type(b_ref)), expr_type(a_ref), nullptr))); + mul_value = b.Mul(a_ref, EXPR(ASR::make_ComplexConstructor_t(al, loc, b_ref, b.f_t(0, expr_type(b_ref)), expr_type(a_ref), nullptr))); } else if (is_integer(*expr_type(a_ref)) && is_complex(*expr_type(b_ref))) { int kind = ASRUtils::extract_kind_from_ttype_t(expr_type(b_ref)); ASR::ttype_t* real_type = TYPE(ASR::make_Real_t(al, loc, kind)); - mul_value = b.Mul(EXPR(ASR::make_ComplexConstructor_t(al, loc, b.i2r(a_ref, real_type), b.f(0, real_type), expr_type(b_ref), nullptr)), b_ref); + mul_value = b.Mul(EXPR(ASR::make_ComplexConstructor_t(al, loc, b.i2r_t(a_ref, real_type), b.f_t(0, real_type), expr_type(b_ref), nullptr)), b_ref); } else if (is_complex(*expr_type(a_ref)) && is_integer(*expr_type(b_ref))) { int kind = ASRUtils::extract_kind_from_ttype_t(expr_type(a_ref)); ASR::ttype_t* real_type = TYPE(ASR::make_Real_t(al, loc, kind)); - mul_value = b.Mul(a_ref, EXPR(ASR::make_ComplexConstructor_t(al, loc, b.i2r(b_ref, real_type), b.f(0, real_type), expr_type(a_ref), nullptr))); + mul_value = b.Mul(a_ref, EXPR(ASR::make_ComplexConstructor_t(al, loc, b.i2r_t(b_ref, real_type), b.f_t(0, real_type), expr_type(a_ref), nullptr))); } else { mul_value = b.Mul(a_ref, b_ref); } - body.push_back(al, b.DoLoop(i, a_lbound, a_ubound, { - b.DoLoop(j, b_lbound, b_ubound, { - b.Assign_Constant(res_ref, 0), - b.DoLoop(k, LBound(args[1], 1), UBound(args[1], 1), { - b.Assignment(res_ref, b.Add(res_ref, mul_value)) - }), - }) - })); - body.push_back(al, Return()); - ASR::symbol_t *fn_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, - body, nullptr, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); - scope->add_symbol(fn_name, fn_sym); - return b.Call(fn_sym, m_args, return_type, nullptr); + body.push_back(al, b.DoLoop(i, a_lbound, a_ubound, { + b.DoLoop(j, b_lbound, b_ubound, { + b.Assign_Constant(res_ref, 0), + b.DoLoop(k, LBound(args[1], 1), UBound(args[1], 1), { + b.Assignment(res_ref, b.Add(res_ref, mul_value)) + }), + }) + })); + body.push_back(al, b.Return()); + ASR::symbol_t *fn_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, + body, nullptr, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); + scope->add_symbol(fn_name, fn_sym); + return b.Call(fn_sym, m_args, return_type, nullptr); + } + +} // namespace MatMul + +namespace Count { + + static inline void verify_args(const ASR::IntrinsicArrayFunction_t &x, + diag::Diagnostics& diagnostics) { + require_impl(x.n_args == 1 || x.n_args == 2 || x.n_args == 3, "`count` intrinsic accepts " + "one, two or three arguments", x.base.base.loc, diagnostics); + require_impl(x.m_args[0], "`mask` argument of `count` intrinsic " + "cannot be nullptr", x.base.base.loc, diagnostics); + } + + static inline ASR::expr_t *eval_Count(Allocator &al, + const Location &loc, ASR::ttype_t *return_type, Vec& args, diag::Diagnostics& /*diag*/) { + ASR::expr_t* mask = args[0]; + if (mask && ASR::is_a(*mask)) { + ASR::ArrayConstant_t *mask_array = ASR::down_cast(mask); + size_t size = ASRUtils::get_fixed_size_of_array(mask_array->m_type); + int64_t count = 0; + for (size_t i = 0; i < size; i++) { + count += int(((bool*)(mask_array->m_data))[i]); + } + return ASRUtils::EXPR(ASR::make_IntegerConstant_t(al, loc, count, return_type)); + } + return nullptr; + } + + static inline ASR::asr_t* create_Count(Allocator& al, const Location& loc, + Vec& args, diag::Diagnostics& diag) { + int64_t id_mask = 0, id_mask_dim = 1; + int64_t overload_id = id_mask; + if (!is_array(expr_type(args[0])) || !is_logical(*expr_type(args[0]))){ + append_error(diag, "`mask` argument to `count` intrinsic must be a logical array", + args[0]->base.loc); + return nullptr; + } + ASR::expr_t *mask = args[0], *dim_ = nullptr, *kind = nullptr; + + if (args.size() == 2) { + dim_ = args[1]; + } else if (args.size() == 3) { + dim_ = args[1]; + kind = args[2]; + } + ASR::dimension_t* array_dims = nullptr; + int array_rank = extract_dimensions_from_ttype(ASRUtils::expr_type(args[0]), array_dims); + + ASR::ttype_t* mask_type = ASRUtils::expr_type(mask); + if ( dim_ != nullptr ) { + size_t dim_rank = ASRUtils::extract_n_dims_from_ttype(ASRUtils::expr_type(dim_)); + if (dim_rank != 0) { + append_error(diag, "dim argument to count must be a scalar and must not be an array", + dim_->base.loc); + return nullptr; + } + overload_id = id_mask_dim; + } + if (array_rank == 1) { + overload_id = id_mask; + } + if ( kind != nullptr) { + size_t kind_rank = ASRUtils::extract_n_dims_from_ttype(ASRUtils::expr_type(kind)); + if (kind_rank != 0) { + append_error(diag, "kind argument to count must be a scalar and must not be an array", + kind->base.loc); + return nullptr; + } + } + ASR::expr_t *value = nullptr; + Vec arg_values; arg_values.reserve(al, 2); + ASR::expr_t *mask_value = ASRUtils::expr_value(mask); + arg_values.push_back(al, mask_value); + if( mask ) { + ASR::expr_t *mask_value = ASRUtils::expr_value(mask); + arg_values.push_back(al, mask_value); + } + + ASR::ttype_t* return_type = nullptr; + if( overload_id == id_mask ) { + return_type = int32; + } else if( overload_id == id_mask_dim ) { + Vec dims; + size_t n_dims = ASRUtils::extract_n_dims_from_ttype(mask_type); + dims.reserve(al, (int) n_dims - 1); + for( int i = 0; i < (int) n_dims - 1; i++ ) { + ASR::dimension_t dim; + dim.loc = mask->base.loc; + dim.m_length = nullptr; + dim.m_start = nullptr; + dims.push_back(al, dim); + } + return_type = ASRUtils::make_Array_t_util(al, loc, + int32, dims.p, dims.n, ASR::abiType::Source, + false); + } + if ( kind ) { + int kind_value = ASR::down_cast(ASRUtils::expr_value(kind))->m_n; + return_type = TYPE(ASR::make_Integer_t(al, loc, kind_value)); + } + value = eval_Count(al, loc, return_type, arg_values, diag); + + Vec arr_intrinsic_args; arr_intrinsic_args.reserve(al, 2); + arr_intrinsic_args.push_back(al, mask); + if( dim_ && array_rank != 1 ) { + arr_intrinsic_args.push_back(al, dim_); + } + return make_IntrinsicArrayFunction_t_util(al, loc, + static_cast(IntrinsicArrayFunctions::Count), + arr_intrinsic_args.p, arr_intrinsic_args.n, overload_id, return_type, value); + } + + static inline ASR::expr_t *instantiate_Count(Allocator &al, + const Location &loc, SymbolTable *scope, + Vec &arg_types, ASR::ttype_t *return_type, + Vec &m_args, int64_t overload_id) { + declare_basic_variables("_lcompilers_count"); + fill_func_arg("mask", duplicate_type_with_empty_dims(al, arg_types[0])); + if (overload_id == 0) { + ASR::expr_t *result = declare("result", return_type, ReturnVar); + /* + for array of rank 2, the following code is generated: + result = 0 + do i = lbound(mask, 2), ubound(mask, 2) + do j = lbound(mask, 1), ubound(mask, 1) + if (mask(j, i)) then + result = result + 1 + end if + end do + end do + */ + ASR::dimension_t* array_dims = nullptr; + int array_rank = extract_dimensions_from_ttype(arg_types[0], array_dims); + std::vector do_loop_variables; + for (int i = 0; i < array_rank; i++) { + do_loop_variables.push_back(declare("i_" + std::to_string(i), int32, Local)); + } + body.push_back(al, b.Assignment(result, b.i_t(0, return_type))); + ASR::stmt_t* do_loop = PassUtils::create_do_loop_helper_count(al, loc, do_loop_variables, args[0], result, array_rank); + body.push_back(al, do_loop); + body.push_back(al, b.Return()); + ASR::symbol_t *fn_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, + body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); + scope->add_symbol(fn_name, fn_sym); + return b.Call(fn_sym, m_args, return_type, nullptr); + } else { + fill_func_arg("dim", duplicate_type_with_empty_dims(al, arg_types[1])); + ASR::expr_t *result = declare("result", return_type, Out); + args.push_back(al, result); + /* + for array of rank 3, the following code is generated: + dim == 2 + do i = 1, ubound(mask, 1) + do k = 1, ubound(mask, 3) + c = 0 + do j = 1, ubound(mask, 2) + if (mask(i, j, k)) then + c = c + 1 + end if + end do + res(i, k) = c + end do + end do + */ + int dim = ASR::down_cast(m_args[1].m_value)->m_n; + ASR::dimension_t* array_dims = nullptr; + int array_rank = extract_dimensions_from_ttype(arg_types[0], array_dims); + std::vector res_idx; + for (int i = 0; i < array_rank - 1; i++) { + res_idx.push_back(declare("i_" + std::to_string(i), int32, Local)); + } + ASR::expr_t* j = declare("j", int32, Local); + ASR::expr_t* c = declare("c", int32, Local); + + std::vector idx; bool dim_found = false; + for (int i = 0; i < array_rank; i++) { + if (i == dim - 1) { + idx.push_back(j); + dim_found = true; + } else { + dim_found ? idx.push_back(res_idx[i-1]): + idx.push_back(res_idx[i]); + } + } + ASR::stmt_t* inner_most_do_loop = b.DoLoop(j, LBound(args[0], dim), UBound(args[0], dim), { + b.If(b.ArrayItem_01(args[0], idx), { + b.Assignment(c, b.Add(c, b.i32(1))), + }, {}) + }); + ASR::stmt_t* do_loop = PassUtils::create_do_loop_helper_count_dim(al, loc, + idx, res_idx, inner_most_do_loop, c, args[0], result, 0, dim); + body.push_back(al, do_loop); + body.push_back(al, b.Return()); + ASR::symbol_t *fn_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, + body, nullptr, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); + scope->add_symbol(fn_name, fn_sym); + return b.Call(fn_sym, m_args, return_type, nullptr); + } } -} // namespace MatMul +} // namespace Count -namespace Count { +namespace Parity { static inline void verify_args(const ASR::IntrinsicArrayFunction_t &x, diag::Diagnostics& diagnostics) { - require_impl(x.n_args == 1 || x.n_args == 2 || x.n_args == 3, "`count` intrinsic accepts " - "one, two or three arguments", x.base.base.loc, diagnostics); - require_impl(x.m_args[0], "`mask` argument of `count` intrinsic " + require_impl(x.n_args == 1 || x.n_args == 2, "`parity` intrinsic accepts " + "atmost two arguments", x.base.base.loc, diagnostics); + require_impl(x.m_args[0], "`mask` argument of `parity` intrinsic " "cannot be nullptr", x.base.base.loc, diagnostics); } - static inline ASR::expr_t *eval_Count(Allocator &/*al*/, - const Location &/*loc*/, ASR::ttype_t */*return_type*/, Vec& /*args*/, diag::Diagnostics& /*diag*/) { - // TODO + static inline ASR::expr_t *eval_Parity(Allocator &al, + const Location &loc, ASR::ttype_t *return_type, Vec& args, diag::Diagnostics& /*diag*/) { + ASR::expr_t* mask = args[0]; + if (mask && ASR::is_a(*mask)) { + ASR::ArrayConstant_t *mask_array = ASR::down_cast(mask); + size_t size = ASRUtils::get_fixed_size_of_array(mask_array->m_type); + bool parity = false; + for (size_t i = 0; i < size; i++) { + parity ^= ((bool*)(mask_array->m_data))[i]; + } + return ASRUtils::EXPR(ASR::make_LogicalConstant_t(al, loc, parity, return_type)); + } return nullptr; } - static inline ASR::asr_t* create_Count(Allocator& al, const Location& loc, - Vec& args, - diag::Diagnostics& diag) { + static inline ASR::asr_t* create_Parity(Allocator& al, const Location& loc, + Vec& args, diag::Diagnostics& diag) { int64_t id_mask = 0, id_mask_dim = 1; int64_t overload_id = id_mask; - ASR::expr_t *mask = args[0], *dim_ = nullptr, *kind = nullptr; + ASR::expr_t *mask = args[0], *dim_ = nullptr; if (args.size() == 2) { dim_ = args[1]; - } else if (args.size() == 3) { - dim_ = args[1]; - kind = args[2]; } ASR::dimension_t* array_dims = nullptr; int array_rank = extract_dimensions_from_ttype(ASRUtils::expr_type(args[0]), array_dims); ASR::ttype_t* mask_type = ASRUtils::expr_type(mask); + + if (!ASRUtils::is_logical(*mask_type)) { + diag.add(diag::Diagnostic("The `mask` argument to `parity` must be logical, but got " + + ASRUtils::type_to_str_fortran(mask_type), + diag::Level::Error, + diag::Stage::Semantic, + {diag::Label("must be logical type", { mask->base.loc })})); + return nullptr; + } if ( dim_ != nullptr ) { size_t dim_rank = ASRUtils::extract_n_dims_from_ttype(ASRUtils::expr_type(dim_)); if (dim_rank != 0) { - append_error(diag, "dim argument to count must be a scalar and must not be an array", + append_error(diag, "dim argument to `parity` must be a scalar and must not be an array", dim_->base.loc); return nullptr; } - overload_id = id_mask_dim; } if (array_rank == 1) { overload_id = id_mask; } - if ( kind != nullptr) { - size_t kind_rank = ASRUtils::extract_n_dims_from_ttype(ASRUtils::expr_type(kind)); - if (kind_rank != 0) { - append_error(diag, "kind argument to count must be a scalar and must not be an array", - kind->base.loc); - return nullptr; - } - } ASR::expr_t *value = nullptr; Vec arg_values; arg_values.reserve(al, 2); ASR::expr_t *mask_value = ASRUtils::expr_value(mask); @@ -1862,7 +4249,7 @@ namespace Count { ASR::ttype_t* return_type = nullptr; if( overload_id == id_mask ) { - return_type = int32; + return_type = logical; } else if( overload_id == id_mask_dim ) { Vec dims; size_t n_dims = ASRUtils::extract_n_dims_from_ttype(mask_type); @@ -1875,40 +4262,36 @@ namespace Count { dims.push_back(al, dim); } return_type = ASRUtils::make_Array_t_util(al, loc, - int32, dims.p, dims.n, ASR::abiType::Source, + logical, dims.p, dims.n, ASR::abiType::Source, false); - } else if ( kind ) { - int kind_value = ASR::down_cast(ASRUtils::expr_value(kind))->m_n; - return_type = TYPE(ASR::make_Integer_t(al, loc, kind_value)); } - // value = eval_Count(al, loc, return_type, arg_values, diag); - value = nullptr; + value = eval_Parity(al, loc, return_type, arg_values, diag); - Vec arr_intrinsic_args; arr_intrinsic_args.reserve(al, 1); + Vec arr_intrinsic_args; arr_intrinsic_args.reserve(al, 2); arr_intrinsic_args.push_back(al, mask); if( dim_ && array_rank != 1 ) { arr_intrinsic_args.push_back(al, dim_); } return make_IntrinsicArrayFunction_t_util(al, loc, - static_cast(IntrinsicArrayFunctions::Count), + static_cast(IntrinsicArrayFunctions::Parity), arr_intrinsic_args.p, arr_intrinsic_args.n, overload_id, return_type, value); } - static inline ASR::expr_t *instantiate_Count(Allocator &al, + static inline ASR::expr_t *instantiate_Parity(Allocator &al, const Location &loc, SymbolTable *scope, Vec &arg_types, ASR::ttype_t *return_type, Vec &m_args, int64_t overload_id) { - declare_basic_variables("_lcompilers_count"); + declare_basic_variables("_lcompilers_parity"); fill_func_arg("mask", duplicate_type_with_empty_dims(al, arg_types[0])); if (overload_id == 0) { ASR::expr_t *result = declare("result", return_type, ReturnVar); /* for array of rank 2, the following code is generated: - result = 0 + result = false do i = lbound(mask, 2), ubound(mask, 2) do j = lbound(mask, 1), ubound(mask, 1) if (mask(j, i)) then - result = result + 1 + result = result | mask(j, i) end if end do end do @@ -1919,10 +4302,10 @@ namespace Count { for (int i = 0; i < array_rank; i++) { do_loop_variables.push_back(declare("i_" + std::to_string(i), int32, Local)); } - body.push_back(al, b.Assignment(result, b.i(0, return_type))); - ASR::stmt_t* do_loop = PassUtils::create_do_loop_helper_count(al, loc, do_loop_variables, args[0], result, array_rank); + body.push_back(al, b.Assignment(result, b.bool_t(0, return_type))); + ASR::stmt_t* do_loop = PassUtils::create_do_loop_helper_parity(al, loc, do_loop_variables, args[0], result, array_rank); body.push_back(al, do_loop); - body.push_back(al, Return()); + body.push_back(al, b.Return()); ASR::symbol_t *fn_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); scope->add_symbol(fn_name, fn_sym); @@ -1938,8 +4321,7 @@ namespace Count { do k = 1, ubound(mask, 3) c = 0 do j = 1, ubound(mask, 2) - if (mask(i, j, k)) then - c = c + 1 + c = c | mask(i, j, k) end if end do res(i, k) = c @@ -1954,7 +4336,7 @@ namespace Count { res_idx.push_back(declare("i_" + std::to_string(i), int32, Local)); } ASR::expr_t* j = declare("j", int32, Local); - ASR::expr_t* c = declare("c", int32, Local); + ASR::expr_t* c = declare("c", logical, Local); std::vector idx; bool dim_found = false; for (int i = 0; i < array_rank; i++) { @@ -1967,14 +4349,13 @@ namespace Count { } } ASR::stmt_t* inner_most_do_loop = b.DoLoop(j, LBound(args[0], dim), UBound(args[0], dim), { - b.If(b.ArrayItem_01(args[0], idx), { - b.Assignment(c, b.Add(c, b.i32(1))), - }, {}) + b.Assignment(c, b.Xor(c, b.ArrayItem_01(args[0], idx))) }); - ASR::stmt_t* do_loop = PassUtils::create_do_loop_helper_count_dim(al, loc, + + ASR::stmt_t* do_loop = PassUtils::create_do_loop_helper_parity_dim(al, loc, idx, res_idx, inner_most_do_loop, c, args[0], result, 0, dim); body.push_back(al, do_loop); - body.push_back(al, Return()); + body.push_back(al, b.Return()); ASR::symbol_t *fn_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, body, nullptr, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); scope->add_symbol(fn_name, fn_sym); @@ -1982,7 +4363,199 @@ namespace Count { } } -} // namespace Count +} // namespace Parity + +namespace Norm2 { + + static inline void verify_args(const ASR::IntrinsicArrayFunction_t &x, + diag::Diagnostics& diagnostics) { + require_impl(x.n_args == 1 || x.n_args == 2, "`norm2` intrinsic accepts " + "atleast 1 and atmost 2 arguments", x.base.base.loc, diagnostics); + require_impl(x.m_args[0], "`array` argument of `norm2` intrinsic " + "cannot be nullptr", x.base.base.loc, diagnostics); + } + + static inline ASR::expr_t *eval_Norm2(Allocator &al, + const Location &loc, ASR::ttype_t *return_type, Vec& args, diag::Diagnostics& /*diag*/) { + ASR::expr_t* array = args[0]; + if (array && ASR::is_a(*array)) { + ASR::ArrayConstant_t *arr = ASR::down_cast(array); + size_t size = ASRUtils::get_fixed_size_of_array(arr->m_type); + int64_t kind = ASRUtils::extract_kind_from_ttype_t(ASRUtils::expr_type(array)); + if (kind == 4) { + float norm = 0.0; + for (size_t i = 0; i < size; i++) { + norm += ((float*)(arr->m_data))[i] * ((float*)(arr->m_data))[i]; + } + return ASRUtils::EXPR(ASR::make_RealConstant_t(al, loc, std::sqrt(norm), return_type)); + } else { + double norm = 0.0; + for (size_t i = 0; i < size; i++) { + norm += ((double*)(arr->m_data))[i] * ((double*)(arr->m_data))[i]; + } + return ASRUtils::EXPR(ASR::make_RealConstant_t(al, loc, std::sqrt(norm), return_type)); + } + } + return nullptr; + } + + static inline ASR::asr_t* create_Norm2(Allocator& al, const Location& loc, + Vec& args, diag::Diagnostics& diag) { + int64_t id_array = 0, id_array_dim = 1; + int64_t overload_id = id_array; + + ASR::expr_t *array = args[0], *dim_ = nullptr; + + if (args.size() == 2) { + dim_ = args[1]; + } + + ASR::dimension_t* array_dims = nullptr; + int64_t array_rank = extract_dimensions_from_ttype(ASRUtils::expr_type(args[0]), array_dims); + + ASR::ttype_t* array_type = ASRUtils::expr_type(array); + if ( dim_ != nullptr ) { + size_t dim_rank = ASRUtils::extract_n_dims_from_ttype(ASRUtils::expr_type(dim_)); + if (dim_rank != 0) { + append_error(diag, "`dim` argument to `norm2` must be a scalar and must not be an array", + dim_->base.loc); + return nullptr; + } + overload_id = id_array_dim; + } + if (array_rank == 1) { + overload_id = id_array; + } + + ASR::expr_t *value = nullptr; + Vec arg_values; arg_values.reserve(al, 2); + ASR::expr_t *array_value = ASRUtils::expr_value(array); + arg_values.push_back(al, array_value); + if( array ) { + ASR::expr_t *array_value = ASRUtils::expr_value(array); + arg_values.push_back(al, array_value); + } + ASR::ttype_t* type = ASRUtils::type_get_past_allocatable( + ASRUtils::type_get_past_pointer(ASRUtils::expr_type(array))); + ASR::ttype_t* return_type = ASRUtils::duplicate_type_without_dims( + al, type, loc); + if( overload_id == id_array_dim ) { + Vec dims; + size_t n_dims = ASRUtils::extract_n_dims_from_ttype(array_type); + dims.reserve(al, (int) n_dims - 1); + for( int i = 0; i < (int) n_dims - 1; i++ ) { + ASR::dimension_t dim; + dim.loc = array->base.loc; + dim.m_length = nullptr; + dim.m_start = nullptr; + dims.push_back(al, dim); + } + return_type = ASRUtils::make_Array_t_util(al, loc, + return_type, dims.p, dims.n, ASR::abiType::Source, + false); + } + + value = eval_Norm2(al, loc, return_type, arg_values, diag); + Vec arr_intrinsic_args; arr_intrinsic_args.reserve(al, 2); + arr_intrinsic_args.push_back(al, array); + if( dim_ && array_rank != 1 ) { + arr_intrinsic_args.push_back(al, dim_); + } + return make_IntrinsicArrayFunction_t_util(al, loc, + static_cast(IntrinsicArrayFunctions::Norm2), + arr_intrinsic_args.p, arr_intrinsic_args.n, overload_id, return_type, value); + } + + static inline ASR::expr_t *instantiate_Norm2(Allocator &al, + const Location &loc, SymbolTable *scope, + Vec &arg_types, ASR::ttype_t *return_type, + Vec &m_args, int64_t overload_id) { + declare_basic_variables("_lcompilers_norm2"); + fill_func_arg("array", duplicate_type_with_empty_dims(al, arg_types[0])); + if (overload_id == 0) { + ASR::expr_t *result = declare("result", return_type, ReturnVar); + /* + for array of rank 2, the following code is generated: + result = 0 + do i = lbound(array, 2), ubound(array, 2) + do j = lbound(array, 1), ubound(array, 1) + result = result + array(j, i) * array(j, i) + end do + end do + result = sqrt(result) + */ + ASR::dimension_t* array_dims = nullptr; + int64_t array_rank = extract_dimensions_from_ttype(arg_types[0], array_dims); + std::vector do_loop_variables; + for (int64_t i = 0; i < array_rank; i++) { + do_loop_variables.push_back(declare("i_" + std::to_string(i), int32, Local)); + } + body.push_back(al, b.Assignment(result, b.f_t(0.0, return_type))); + ASR::stmt_t* do_loop = PassUtils::create_do_loop_helper_norm2(al, loc, do_loop_variables, args[0], result, array_rank); + ASR::expr_t* res = EXPR(ASR::make_RealSqrt_t(al, loc, + result, return_type, nullptr)); + body.push_back(al, do_loop); + body.push_back(al, b.Assignment(result, res)); + body.push_back(al, b.Return()); + ASR::symbol_t *fn_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, + body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); + scope->add_symbol(fn_name, fn_sym); + return b.Call(fn_sym, m_args, return_type, nullptr); + } else { + fill_func_arg("dim", duplicate_type_with_empty_dims(al, arg_types[1])); + ASR::expr_t *result = declare("result", return_type, Out); + args.push_back(al, result); + /* + for array of rank 3, the following code is generated: + dim == 2 + do i = 1, ubound(mask, 1) + do k = 1, ubound(mask, 3) + c = 0 + do j = 1, ubound(mask, 2) + c = c + mask(i, j, k) * mask(i, j, k) + end do + res(i, k) = sqrt(c) + end do + end do + */ + int64_t dim = ASR::down_cast(m_args[1].m_value)->m_n; + ASR::dimension_t* array_dims = nullptr; + int64_t array_rank = extract_dimensions_from_ttype(arg_types[0], array_dims); + std::vector res_idx; + for (int i = 0; i < array_rank - 1; i++) { + res_idx.push_back(declare("i_" + std::to_string(i), int32, Local)); + } + ASR::expr_t* j = declare("j", int32, Local); + ASR::expr_t* c = declare("c", return_type, Local); + + std::vector idx; bool dim_found = false; + for (int i = 0; i < array_rank; i++) { + if (i == dim - 1) { + idx.push_back(j); + dim_found = true; + } else { + dim_found ? idx.push_back(res_idx[i-1]): + idx.push_back(res_idx[i]); + } + } + ASR::stmt_t* inner_most_do_loop = b.DoLoop(j, LBound(args[0], dim), UBound(args[0], dim), { + b.Assignment(c, b.Add(c, b.Mul(b.ArrayItem_01(args[0], idx), b.ArrayItem_01(args[0], idx)))), + }); + ASR::stmt_t* do_loop = PassUtils::create_do_loop_helper_norm2_dim(al, loc, + idx, res_idx, inner_most_do_loop, c, args[0], result, 0, dim); + ASR::expr_t* res = EXPR(ASR::make_RealSqrt_t(al, loc, + result, return_type, nullptr)); + body.push_back(al, do_loop); + body.push_back(al, b.Assignment(result, res)); + body.push_back(al, b.Return()); + ASR::symbol_t *fn_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, + body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); + scope->add_symbol(fn_name, fn_sym); + return b.Call(fn_sym, m_args, return_type, nullptr); + } + } + +} // namespace Norm2 namespace Pack { @@ -1997,17 +4570,17 @@ namespace Pack { } template - void populate_vector(std::vector &a, ASR::expr_t *vector_a, int dim) { + void populate_vector(Allocator &al, std::vector &a, ASR::expr_t *vector_a, int dim) { if (!vector_a) return; if (ASR::is_a(*vector_a)) { vector_a = ASR::down_cast(vector_a)->m_arg; } + vector_a = ASRUtils::expr_value(vector_a); LCOMPILERS_ASSERT(ASR::is_a(*vector_a)); ASR::ArrayConstant_t *a_const = ASR::down_cast(vector_a); for (int i = 0; i < dim; i++) { - ASR::expr_t* arg_a = a_const->m_args[i]; - + ASR::expr_t* arg_a = ASRUtils::fetch_ArrayConstant_value(al, a_const, i); if (ASR::is_a(*arg_a)) { a[i] = ASR::down_cast(arg_a)->m_n; } else if (ASR::is_a(*arg_a)) { @@ -2021,16 +4594,17 @@ namespace Pack { } template - void populate_vector_complex(std::vector &a, ASR::expr_t *vector_a, int dim) { + void populate_vector_complex(Allocator &al, std::vector &a, ASR::expr_t *vector_a, int dim) { if (!vector_a) return; if (ASR::is_a(*vector_a)) { vector_a = ASR::down_cast(vector_a)->m_arg; } + vector_a = ASRUtils::expr_value(vector_a); LCOMPILERS_ASSERT(ASR::is_a(*vector_a)); ASR::ArrayConstant_t *a_const = ASR::down_cast(vector_a); for (int i = 0; i < dim; i++) { - ASR::expr_t* arg_a = a_const->m_args[i]; + ASR::expr_t* arg_a = ASRUtils::fetch_ArrayConstant_value(al, a_const, i); if (ASR::is_a(*arg_a)) { arg_a = ASR::down_cast(arg_a)->m_value; @@ -2060,9 +4634,9 @@ namespace Pack { static inline ASR::expr_t *eval_Pack(Allocator & al, const Location & loc, ASR::ttype_t *return_type, Vec& args, diag::Diagnostics& diag) { + ASRBuilder builder(al, loc); ASR::expr_t *array = args[0], *mask = args[1], *vector = args[2]; ASR::ttype_t *type_array = ASRUtils::type_get_past_pointer(ASRUtils::type_get_past_allocatable(expr_type(array))); - ASR::ttype_t *type_vector = ASRUtils::type_get_past_pointer(ASRUtils::type_get_past_allocatable(expr_type(vector))); ASR::ttype_t* type_a = ASRUtils::type_get_past_array(type_array); int kind = ASRUtils::extract_kind_from_ttype_t(type_a); @@ -2071,98 +4645,139 @@ namespace Pack { bool is_vector_present = false; if (vector) is_vector_present = true; - if (is_vector_present) dim_vector = ASRUtils::get_fixed_size_of_array(type_vector); + if (is_vector_present) { + ASR::ttype_t *type_vector = ASRUtils::type_get_past_pointer(ASRUtils::type_get_past_allocatable(expr_type(vector))); + dim_vector = ASRUtils::get_fixed_size_of_array(type_vector); + } std::vector b(dim_array); - populate_vector(b, mask, dim_array); + populate_vector(al, b, mask, dim_array); if (ASRUtils::is_real(*type_a)) { if (kind == 4) { std::vector a(dim_array), c(dim_vector), res; - populate_vector(a, array, dim_array); - populate_vector(c, vector, dim_vector); + populate_vector(al, a, array, dim_array); + if (is_vector_present) { + populate_vector(al, c, vector, dim_vector); + } evaluate_Pack(a, b, c, res); - Vec values; values.reserve(al, res.size()); + std::vector values; for (auto it: res) { - values.push_back(al, EXPR(ASR::make_RealConstant_t(al, loc, it, real32))); + values.push_back(EXPR(ASR::make_RealConstant_t(al, loc, it, real32))); } - return EXPR(ASR::make_ArrayConstant_t(al, loc, values.p, values.n, return_type, ASR::arraystorageType::ColMajor)); + return builder.ArrayConstant(values, extract_type(return_type), false); } else if (kind == 8) { std::vector a(dim_array), c(dim_vector), res; - populate_vector(a, array, dim_array); - populate_vector(c, vector, dim_vector); + populate_vector(al, a, array, dim_array); + if (is_vector_present) { + populate_vector(al, c, vector, dim_vector); + } evaluate_Pack(a, b, c, res); - Vec values; values.reserve(al, res.size()); + std::vector values; for (auto it: res) { - values.push_back(al, EXPR(ASR::make_RealConstant_t(al, loc, it, real64))); + values.push_back(EXPR(ASR::make_RealConstant_t(al, loc, it, real64))); } - return EXPR(ASR::make_ArrayConstant_t(al, loc, values.p, values.n, return_type, ASR::arraystorageType::ColMajor)); + return builder.ArrayConstant(values, extract_type(return_type), false); } else { - append_error(diag, "The `dot_product` intrinsic doesn't handle kind " + std::to_string(kind) + " yet", loc); + append_error(diag, "The `pack` intrinsic doesn't handle kind " + std::to_string(kind) + " yet", loc); return nullptr; } } else if (ASRUtils::is_integer(*type_a)) { - if (kind == 4) { + if (kind == 1) { + std::vector a(dim_array), c(dim_vector), res; + populate_vector(al, a, array, dim_array); + if (is_vector_present) { + populate_vector(al, c, vector, dim_vector); + } + evaluate_Pack(a, b, c, res); + std::vector values; + for (auto it: res) { + values.push_back(EXPR(ASR::make_IntegerConstant_t(al, loc, it, int8))); + } + return builder.ArrayConstant(values, extract_type(return_type), false); + } else if (kind == 2) { + std::vector a(dim_array), c(dim_vector), res; + populate_vector(al, a, array, dim_array); + if (is_vector_present) { + populate_vector(al, c, vector, dim_vector); + } + evaluate_Pack(a, b, c, res); + std::vector values; + for (auto it: res) { + values.push_back(EXPR(ASR::make_IntegerConstant_t(al, loc, it, int16))); + } + return builder.ArrayConstant(values, extract_type(return_type), false); + } else if (kind == 4) { std::vector a(dim_array), c(dim_vector), res; - populate_vector(a, array, dim_array); - populate_vector(c, vector, dim_vector); + populate_vector(al, a, array, dim_array); + if (is_vector_present) { + populate_vector(al, c, vector, dim_vector); + } evaluate_Pack(a, b, c, res); - Vec values; values.reserve(al, res.size()); + std::vector values; for (auto it: res) { - values.push_back(al, EXPR(ASR::make_IntegerConstant_t(al, loc, it, int32))); + values.push_back(EXPR(ASR::make_IntegerConstant_t(al, loc, it, int32))); } - return EXPR(ASR::make_ArrayConstant_t(al, loc, values.p, values.n, return_type, ASR::arraystorageType::ColMajor)); + return builder.ArrayConstant(values, extract_type(return_type), false); } else if (kind == 8) { std::vector a(dim_array), c(dim_vector), res; - populate_vector(a, array, dim_array); - populate_vector(c, vector, dim_vector); + populate_vector(al, a, array, dim_array); + if (is_vector_present) { + populate_vector(al, c, vector, dim_vector); + } evaluate_Pack(a, b, c, res); - Vec values; values.reserve(al, res.size()); + std::vector values; for (auto it: res) { - values.push_back(al, EXPR(ASR::make_IntegerConstant_t(al, loc, it, int64))); + values.push_back(EXPR(ASR::make_IntegerConstant_t(al, loc, it, int64))); } - return EXPR(ASR::make_ArrayConstant_t(al, loc, values.p, values.n, return_type, ASR::arraystorageType::ColMajor)); + return builder.ArrayConstant(values, extract_type(return_type), false); } else { - append_error(diag, "The `dot_product` intrinsic doesn't handle kind " + std::to_string(kind) + " yet", loc); + append_error(diag, "The `pack` intrinsic doesn't handle kind " + std::to_string(kind) + " yet", loc); return nullptr; } } else if (ASRUtils::is_logical(*type_a)) { std::vector a(dim_array), c(dim_vector), res; - populate_vector(a, array, dim_array); - populate_vector(c, vector, dim_vector); - evaluate_Pack(a, b, c, res); - Vec values; values.reserve(al, res.size()); - for (auto it: res) { - values.push_back(al, EXPR(ASR::make_LogicalConstant_t(al, loc, it, logical))); + populate_vector(al, a, array, dim_array); + if (is_vector_present) { + populate_vector(al, c, vector, dim_vector); } - return EXPR(ASR::make_ArrayConstant_t(al, loc, values.p, values.n, return_type, ASR::arraystorageType::ColMajor)); + evaluate_Pack(a, b, c, res); + std::vector values; + for (auto it: res) { + values.push_back(EXPR(ASR::make_LogicalConstant_t(al, loc, it, int32))); + } + return builder.ArrayConstant(values, extract_type(return_type), false); } else if (ASRUtils::is_complex(*type_a)) { if (kind == 4) { std::vector> a(dim_array), c(dim_vector), res; - populate_vector_complex(a, array, dim_array); - populate_vector_complex(c, vector, dim_vector); + populate_vector_complex(al, a, array, dim_array); + if (is_vector_present) { + populate_vector_complex(al, c, vector, dim_vector); + } evaluate_Pack(a, b, c, res); - Vec values; values.reserve(al, res.size()); + std::vector values; for (auto it: res) { - values.push_back(al, EXPR(ASR::make_ComplexConstant_t(al, loc, it.first, it.second, type_get_past_array(return_type)))); + values.push_back(EXPR(ASR::make_ComplexConstant_t(al, loc, it.first, it.second, type_get_past_array(return_type)))); } - return EXPR(ASR::make_ArrayConstant_t(al, loc, values.p, values.n, return_type, ASR::arraystorageType::ColMajor)); + return builder.ArrayConstant(values, extract_type(return_type), false); } else if (kind == 8) { std::vector> a(dim_array), c(dim_vector), res; - populate_vector_complex(a, array, dim_array); - populate_vector_complex(c, vector, dim_vector); + populate_vector_complex(al, a, array, dim_array); + if (is_vector_present) { + populate_vector_complex(al, c, vector, dim_vector); + } evaluate_Pack(a, b, c, res); - Vec values; values.reserve(al, res.size()); + std::vector values; for (auto it: res) { - values.push_back(al, EXPR(ASR::make_ComplexConstant_t(al, loc, it.first, it.second, type_get_past_array(return_type)))); + values.push_back(EXPR(ASR::make_ComplexConstant_t(al, loc, it.first, it.second, type_get_past_array(return_type)))); } - return EXPR(ASR::make_ArrayConstant_t(al, loc, values.p, values.n, return_type, ASR::arraystorageType::ColMajor)); + return builder.ArrayConstant(values, extract_type(return_type), false); } else { - append_error(diag, "The `dot_product` intrinsic doesn't handle kind " + std::to_string(kind) + " yet", loc); + append_error(diag, "The `pack` intrinsic doesn't handle kind " + std::to_string(kind) + " yet", loc); return nullptr; } } else { - append_error(diag, "The `dot_product` intrinsic doesn't handle type " + ASRUtils::get_type_code(type_a) + " yet", loc); + append_error(diag, "The `pack` intrinsic doesn't handle type " + ASRUtils::get_type_code(type_a) + " yet", loc); return nullptr; } return nullptr; @@ -2201,13 +4816,16 @@ namespace Pack { int array_dim = -1, mask_dim = -1, fixed_size_array = -1; fixed_size_array = ASRUtils::get_fixed_size_of_array(type_array); extract_value(array_dims[0].m_length, array_dim); + if (mask_rank != 0) extract_value(mask_dims[0].m_length, mask_dim); if (mask_rank == 0) { Vec mask_expr; mask_expr.reserve(al, fixed_size_array); for (int i = 0; i < fixed_size_array; i++) { mask_expr.push_back(al, mask); } if (all_args_evaluated(mask_expr)) { - mask = EXPR(ASR::make_ArrayConstant_t(al, mask->base.loc, mask_expr.p, mask_expr.n, + int64_t n_data = mask_expr.n * extract_kind_from_ttype_t(logical); + mask = EXPR(ASR::make_ArrayConstant_t(al, mask->base.loc, n_data, + ASRUtils::set_ArrayConstant_data(mask_expr.p, mask_expr.n, logical), TYPE(ASR::make_Array_t(al, mask->base.loc, logical, array_dims, array_rank, ASR::array_physical_typeType::FixedSizeArray)), ASR::arraystorageType::ColMajor)); } else { @@ -2227,11 +4845,10 @@ namespace Pack { ", provided an array with rank, " + std::to_string(mask_rank), mask->base.loc); return nullptr; } - if (!dimension_expr_equal(array_dims[0].m_length, + if (array_dim != -1 && mask_dim != -1 && !dimension_expr_equal(array_dims[0].m_length, mask_dims[0].m_length)) { - append_error(diag, "The argument `mask` must be of dimension " - + std::to_string(array_dim) + ", provided an array " - "with dimension " + std::to_string(mask_dim), mask->base.loc); + append_error(diag, "Different shape for arguments `array` and `mask` for pack intrinsic " + "(" + std::to_string(array_dim) + " and " + std::to_string(mask_dim) + ")", mask->base.loc); return nullptr; } if (is_vector_present && vector_rank != 1) { @@ -2251,19 +4868,23 @@ namespace Pack { ASR::expr_t* count = EXPR(Count::create_Count(al, loc, args_count, diag)); result_dims.push_back(al, b.set_dim(array_dims[0].m_start, count)); ret_type = ASRUtils::duplicate_type(al, ret_type, &result_dims, ASR::array_physical_typeType::DescriptorArray, true); + is_type_allocatable = true; } if (is_type_allocatable) { - ret_type = TYPE(ASR::make_Allocatable_t(al, loc, ret_type)); + ret_type = TYPE(ASRUtils::make_Allocatable_t_util(al, loc, ret_type)); } - Vec m_args; m_args.reserve(al, 2); + Vec arg_values; arg_values.reserve(al, 3); + arg_values.push_back(al, expr_value(array)); arg_values.push_back(al, expr_value(mask)); + Vec m_args; m_args.reserve(al, 3); m_args.push_back(al, array); m_args.push_back(al, mask); if (is_vector_present) { + arg_values.push_back(al, expr_value(vector)); m_args.push_back(al, vector); overload_id = 3; } ASR::expr_t *value = nullptr; if (all_args_evaluated(m_args)) { - value = eval_Pack(al, loc, ret_type, m_args, diag); + value = eval_Pack(al, loc, ret_type, arg_values, diag); } return make_IntrinsicArrayFunction_t_util(al, loc, static_cast(IntrinsicArrayFunctions::Pack), @@ -2282,38 +4903,10 @@ namespace Pack { } ASR::ttype_t* ret_type = return_type; if (overload_id == 2) { - ret_type = ASRUtils::duplicate_type(al, return_type, nullptr, ASRUtils::extract_physical_type(return_type), true); - LCOMPILERS_ASSERT(ASR::is_a(*ret_type)); - ASR::Array_t *ret_type_array = ASR::down_cast(ret_type); - if (ASR::is_a(*ret_type_array->m_dims[0].m_length)) { - ASR::FunctionCall_t *func_call = ASR::down_cast(ret_type_array->m_dims[0].m_length); - if (ASR::is_a(*func_call->m_args[0].m_value)) { - ASR::ArrayPhysicalCast_t *array_cast = ASR::down_cast(func_call->m_args[0].m_value); - array_cast->m_arg = args[1]; - array_cast->m_old = ASRUtils::extract_physical_type(arg_types[1]); - array_cast->m_type = ASRUtils::duplicate_type_with_empty_dims(al, array_cast->m_type); - - ret_type = TYPE(ASR::make_Array_t(al, loc, ret_type_array->m_type, ret_type_array->m_dims, - ret_type_array->n_dims, ret_type_array->m_physical_type)); - } else { - ret_type = return_type; - } - } else if (ASR::is_a(*ret_type_array->m_dims[0].m_length)) { - ASR::IntrinsicArrayFunction_t *intrinsic_array = ASR::down_cast(ret_type_array->m_dims[0].m_length); - if (ASR::is_a(*intrinsic_array->m_args[0])) { - ASR::ArrayPhysicalCast_t *array_cast = ASR::down_cast(intrinsic_array->m_args[0]); - array_cast->m_arg = args[1]; - array_cast->m_old = ASRUtils::extract_physical_type(arg_types[1]); - array_cast->m_type = ASRUtils::duplicate_type_with_empty_dims(al, array_cast->m_type); - - ret_type = TYPE(ASR::make_Array_t(al, loc, ret_type_array->m_type, ret_type_array->m_dims, - ret_type_array->n_dims, ret_type_array->m_physical_type)); - } else { - ret_type = return_type; - } - } else { - ret_type = return_type; - } + ret_type = ASRUtils::duplicate_type_with_empty_dims( + al, ASRUtils::type_get_past_pointer( + ASRUtils::type_get_past_allocatable(return_type)), + ASR::array_physical_typeType::DescriptorArray, true); } ASR::expr_t *result = declare("result", ret_type, Out); args.push_back(al, result); @@ -2355,7 +4948,7 @@ namespace Pack { b.Assignment(k, b.Add(k, b.i32(1))) })); } - body.push_back(al, Return()); + body.push_back(al, b.Return()); ASR::symbol_t *fn_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, body, nullptr, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); scope->add_symbol(fn_name, fn_sym); @@ -2379,16 +4972,17 @@ namespace Unpack { } template - void populate_vector(std::vector &a, ASR::expr_t *vector_a, int dim) { + void populate_vector(Allocator &al, std::vector &a, ASR::expr_t *vector_a, int dim) { if (!vector_a) return; if (ASR::is_a(*vector_a)) { vector_a = ASR::down_cast(vector_a)->m_arg; } + vector_a = ASRUtils::expr_value(vector_a); LCOMPILERS_ASSERT(ASR::is_a(*vector_a)); ASR::ArrayConstant_t *a_const = ASR::down_cast(vector_a); for (int i = 0; i < dim; i++) { - ASR::expr_t* arg_a = a_const->m_args[i]; + ASR::expr_t* arg_a = ASRUtils::fetch_ArrayConstant_value(al, a_const, i); if (ASR::is_a(*arg_a)) { a[i] = ASR::down_cast(arg_a)->m_n; @@ -2403,16 +4997,17 @@ namespace Unpack { } template - void populate_vector_complex(std::vector &a, ASR::expr_t *vector_a, int dim) { + void populate_vector_complex(Allocator &al, std::vector &a, ASR::expr_t *vector_a, int dim) { if (!vector_a) return; if (ASR::is_a(*vector_a)) { vector_a = ASR::down_cast(vector_a)->m_arg; } + vector_a = ASRUtils::expr_value(vector_a); LCOMPILERS_ASSERT(ASR::is_a(*vector_a)); ASR::ArrayConstant_t *a_const = ASR::down_cast(vector_a); for (int i = 0; i < dim; i++) { - ASR::expr_t* arg_a = a_const->m_args[i]; + ASR::expr_t* arg_a = ASRUtils::fetch_ArrayConstant_value(al, a_const, i); if (ASR::is_a(*arg_a)) { arg_a = ASR::down_cast(arg_a)->m_value; @@ -2436,40 +5031,40 @@ namespace Unpack { int kind = ASRUtils::extract_kind_from_ttype_t(type_a); int dim_mask = ASRUtils::get_fixed_size_of_array(type_mask); int dim_vector = ASRUtils::get_fixed_size_of_array(type_vector); - + int k = 0; std::vector b(dim_mask); - populate_vector(b, mask, dim_mask); + populate_vector(al, b, mask, dim_mask); if (ASRUtils::is_real(*type_a)) { if (kind == 4) { std::vector a(dim_vector), c(dim_mask); - populate_vector(a, vector, dim_vector); - populate_vector(c, field, dim_mask); + populate_vector(al, a, vector, dim_vector); + populate_vector(al, c, field, dim_mask); Vec values; values.reserve(al, b.size()); - for (int i = 0; i < dim_mask; i++) { if (b[i]) { - values.push_back(al, EXPR(ASR::make_RealConstant_t(al, loc, a[i], real32))); + values.push_back(al, EXPR(ASR::make_RealConstant_t(al, loc, a[k], real32))); + k++; } else { values.push_back(al, EXPR(ASR::make_RealConstant_t(al, loc, c[i], real32))); } } - return EXPR(ASR::make_ArrayConstant_t(al, loc, values.p, values.n, return_type, ASR::arraystorageType::ColMajor)); + return EXPR(ASRUtils::make_ArrayConstructor_t_util(al, loc, values.p, values.n, return_type, ASR::arraystorageType::ColMajor)); } else if (kind == 8) { std::vector a(dim_vector), c(dim_mask); - populate_vector(a, vector, dim_vector); - populate_vector(c, field, dim_mask); + populate_vector(al, a, vector, dim_vector); + populate_vector(al, c, field, dim_mask); Vec values; values.reserve(al, b.size()); - for (int i = 0; i < dim_mask; i++) { if (b[i]) { - values.push_back(al, EXPR(ASR::make_RealConstant_t(al, loc, a[i], real64))); + values.push_back(al, EXPR(ASR::make_RealConstant_t(al, loc, a[k], real64))); + k++; } else { values.push_back(al, EXPR(ASR::make_RealConstant_t(al, loc, c[i], real64))); } } - return EXPR(ASR::make_ArrayConstant_t(al, loc, values.p, values.n, return_type, ASR::arraystorageType::ColMajor)); + return EXPR(ASRUtils::make_ArrayConstructor_t_util(al, loc, values.p, values.n, return_type, ASR::arraystorageType::ColMajor)); } else { append_error(diag, "The `unpack` intrinsic doesn't handle kind " + std::to_string(kind) + " yet", loc); return nullptr; @@ -2477,80 +5072,83 @@ namespace Unpack { } else if (ASRUtils::is_integer(*type_a)) { if (kind == 4) { std::vector a(dim_vector), c(dim_mask); - populate_vector(a, vector, dim_vector); - populate_vector(c, field, dim_mask); + populate_vector(al, a, vector, dim_vector); + populate_vector(al, c, field, dim_mask); Vec values; values.reserve(al, b.size()); - for (int i = 0; i < dim_mask; i++) { if (b[i]) { - values.push_back(al, EXPR(ASR::make_IntegerConstant_t(al, loc, a[i], int32))); + values.push_back(al, EXPR(ASR::make_IntegerConstant_t(al, loc, a[k], int32))); + k++; } else { values.push_back(al, EXPR(ASR::make_IntegerConstant_t(al, loc, c[i], int32))); } } - return EXPR(ASR::make_ArrayConstant_t(al, loc, values.p, values.n, return_type, ASR::arraystorageType::ColMajor)); + return EXPR(ASRUtils::make_ArrayConstructor_t_util(al, loc, values.p, values.n, return_type, ASR::arraystorageType::ColMajor)); } else if (kind == 8) { std::vector a(dim_vector), c(dim_mask); - populate_vector(a, vector, dim_vector); - populate_vector(c, field, dim_mask); + populate_vector(al, a, vector, dim_vector); + populate_vector(al, c, field, dim_mask); Vec values; values.reserve(al, b.size()); - for (int i = 0; i < dim_mask; i++) { if (b[i]) { - values.push_back(al, EXPR(ASR::make_IntegerConstant_t(al, loc, a[i], int64))); + values.push_back(al, EXPR(ASR::make_IntegerConstant_t(al, loc, a[k], int64))); + k++; } else { values.push_back(al, EXPR(ASR::make_IntegerConstant_t(al, loc, c[i], int64))); } } - return EXPR(ASR::make_ArrayConstant_t(al, loc, values.p, values.n, return_type, ASR::arraystorageType::ColMajor)); + return EXPR(ASRUtils::make_ArrayConstructor_t_util(al, loc, values.p, values.n, return_type, ASR::arraystorageType::ColMajor)); } else { append_error(diag, "The `unpack` intrinsic doesn't handle kind " + std::to_string(kind) + " yet", loc); return nullptr; } } else if (ASRUtils::is_logical(*type_a)) { std::vector a(dim_vector), c(dim_mask); - populate_vector(a, vector, dim_vector); - populate_vector(c, field, dim_mask); + populate_vector(al, a, vector, dim_vector); + populate_vector(al, c, field, dim_mask); Vec values; values.reserve(al, b.size()); for (int i = 0; i < dim_mask; i++) { if (b[i]) { - values.push_back(al, EXPR(ASR::make_LogicalConstant_t(al, loc, a[i], logical))); + values.push_back(al, EXPR(ASR::make_LogicalConstant_t(al, loc, a[k], logical))); + k++; } else { values.push_back(al, EXPR(ASR::make_LogicalConstant_t(al, loc, c[i], logical))); } } - return EXPR(ASR::make_ArrayConstant_t(al, loc, values.p, values.n, return_type, ASR::arraystorageType::ColMajor)); + return EXPR(ASRUtils::make_ArrayConstructor_t_util(al, loc, values.p, values.n, return_type, ASR::arraystorageType::ColMajor)); } else if (ASRUtils::is_complex(*type_a)) { if (kind == 4) { std::vector> a(dim_vector), c(dim_mask); - populate_vector_complex(a, vector, dim_vector); - populate_vector_complex(c, field, dim_mask); + populate_vector_complex(al, a, vector, dim_vector); + populate_vector_complex(al, c, field, dim_mask); Vec values; values.reserve(al, b.size()); for (int i = 0; i < dim_mask; i++) { if (b[i]) { - values.push_back(al, EXPR(ASR::make_ComplexConstant_t(al, loc, a[i].first, a[i].second, type_get_past_array(return_type)))); + values.push_back(al, EXPR(ASR::make_ComplexConstant_t(al, loc, a[k].first, a[k].second, type_get_past_array(return_type)))); + k++; } else { values.push_back(al, EXPR(ASR::make_ComplexConstant_t(al, loc, c[i].first, c[i].second, type_get_past_array(return_type)))); } } - return EXPR(ASR::make_ArrayConstant_t(al, loc, values.p, values.n, return_type, ASR::arraystorageType::ColMajor)); + return EXPR(ASRUtils::make_ArrayConstructor_t_util(al, loc, values.p, values.n, return_type, ASR::arraystorageType::ColMajor)); } else if (kind == 8) { std::vector> a(dim_vector), c(dim_mask); - populate_vector_complex(a, vector, dim_vector); - populate_vector_complex(c, field, dim_mask); + populate_vector_complex(al, a, vector, dim_vector); + populate_vector_complex(al, c, field, dim_mask); Vec values; values.reserve(al, b.size()); for (int i = 0; i < dim_mask; i++) { if (b[i]) { - values.push_back(al, EXPR(ASR::make_ComplexConstant_t(al, loc, a[i].first, a[i].second, type_get_past_array(return_type)))); + values.push_back(al, EXPR(ASR::make_ComplexConstant_t(al, loc, a[k].first, a[k].second, type_get_past_array(return_type)))); + k++; } else { values.push_back(al, EXPR(ASR::make_ComplexConstant_t(al, loc, c[i].first, c[i].second, type_get_past_array(return_type)))); } } - return EXPR(ASR::make_ArrayConstant_t(al, loc, values.p, values.n, return_type, ASR::arraystorageType::ColMajor)); + return EXPR(ASRUtils::make_ArrayConstructor_t_util(al, loc, values.p, values.n, return_type, ASR::arraystorageType::ColMajor)); } else { append_error(diag, "The `unpack` intrinsic doesn't handle kind " + std::to_string(kind) + " yet", loc); return nullptr; @@ -2619,7 +5217,7 @@ namespace Unpack { } ret_type = ASRUtils::duplicate_type(al, ret_type, &result_dims); if (is_type_allocatable) { - ret_type = TYPE(ASR::make_Allocatable_t(al, loc, ret_type)); + ret_type = TYPE(ASRUtils::make_Allocatable_t_util(al, loc, ret_type)); } Vec m_args; m_args.reserve(al, 3); m_args.push_back(al, vector); m_args.push_back(al, mask); m_args.push_back(al, field); @@ -2667,7 +5265,7 @@ namespace Unpack { body.push_back(al, b.Assignment(result, args[2])); ASR::stmt_t* do_loop = PassUtils::create_do_loop_helper_unpack(al, loc, do_loop_variables, args[0], args[1], result, k, mask_rank); body.push_back(al, do_loop); - body.push_back(al, Return()); + body.push_back(al, b.Return()); ASR::symbol_t *fn_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, body, nullptr, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); scope->add_symbol(fn_name, fn_sym); @@ -2689,7 +5287,9 @@ namespace DotProduct { } template - void populate_vector_complex(std::vector &a, std::vector& b, ASR::expr_t *vector_a, ASR::expr_t* vector_b, int dim) { + void populate_vector_complex(Allocator &al, std::vector &a, std::vector& b, ASR::expr_t *vector_a, ASR::expr_t* vector_b, int dim) { + vector_a = ASRUtils::expr_value(vector_a); + vector_b = ASRUtils::expr_value(vector_b); if (ASR::is_a(*vector_a)) { vector_a = ASR::down_cast(vector_a)->m_arg; } @@ -2701,8 +5301,8 @@ namespace DotProduct { ASR::ArrayConstant_t *b_const = ASR::down_cast(vector_b); for (int i = 0; i < dim; i++) { - ASR::expr_t* arg_a = a_const->m_args[i]; - ASR::expr_t* arg_b = b_const->m_args[i]; + ASR::expr_t* arg_a = ASRUtils::fetch_ArrayConstant_value(al, a_const, i); + ASR::expr_t* arg_b = ASRUtils::fetch_ArrayConstant_value(al, b_const, i); if (ASR::is_a(*arg_a)) { arg_a = ASR::down_cast(arg_a)->m_value; @@ -2723,7 +5323,9 @@ namespace DotProduct { } template - void populate_vector(std::vector &a, std::vector& b, ASR::expr_t *vector_a, ASR::expr_t* vector_b, int dim) { + void populate_vector(Allocator &al, std::vector &a, std::vector& b, ASR::expr_t *vector_a, ASR::expr_t* vector_b, int dim) { + vector_a = ASRUtils::expr_value(vector_a); + vector_b = ASRUtils::expr_value(vector_b); if (ASR::is_a(*vector_a)) { vector_a = ASR::down_cast(vector_a)->m_arg; } @@ -2735,8 +5337,8 @@ namespace DotProduct { ASR::ArrayConstant_t *b_const = ASR::down_cast(vector_b); for (int i = 0; i < dim; i++) { - ASR::expr_t* arg_a = a_const->m_args[i]; - ASR::expr_t* arg_b = b_const->m_args[i]; + ASR::expr_t* arg_a = ASRUtils::fetch_ArrayConstant_value(al, a_const, i); + ASR::expr_t* arg_b = ASRUtils::fetch_ArrayConstant_value(al, b_const, i); if (ASR::is_a(*arg_a)) { a[i] = ASR::down_cast(arg_a)->m_n; @@ -2765,12 +5367,12 @@ namespace DotProduct { if (ASRUtils::is_real(*type_a)) { if (kind == 4) { std::vector a(dim), b(dim); - populate_vector(a, b, vector_a, vector_b, dim); + populate_vector(al, a, b, vector_a, vector_b, dim); float result = std::inner_product(a.begin(), a.end(), b.begin(), 0.0f); return make_ConstantWithType(make_RealConstant_t, result, return_type, loc); } else if (kind == 8) { std::vector a(dim), b(dim); - populate_vector(a, b, vector_a, vector_b, dim); + populate_vector(al, a, b, vector_a, vector_b, dim); double result = std::inner_product(a.begin(), a.end(), b.begin(), 0.0); return make_ConstantWithType(make_RealConstant_t, result, return_type, loc); } else { @@ -2780,12 +5382,12 @@ namespace DotProduct { } else if (ASRUtils::is_integer(*type_a)) { if (kind == 4) { std::vector a(dim), b(dim); - populate_vector(a, b, vector_a, vector_b, dim); + populate_vector(al, a, b, vector_a, vector_b, dim); int32_t result = std::inner_product(a.begin(), a.end(), b.begin(), 0); return make_ConstantWithType(make_IntegerConstant_t, result, return_type, loc); } else if (kind == 8) { std::vector a(dim), b(dim); - populate_vector(a, b, vector_a, vector_b, dim); + populate_vector(al, a, b, vector_a, vector_b, dim); int64_t result = std::inner_product(a.begin(), a.end(), b.begin(), 0); return make_ConstantWithType(make_IntegerConstant_t, result, return_type, loc); } else { @@ -2794,7 +5396,7 @@ namespace DotProduct { } } else if (ASRUtils::is_logical(*type_a)) { std::vector a(dim), b(dim); - populate_vector(a, b, vector_a, vector_b, dim); + populate_vector(al, a, b, vector_a, vector_b, dim); bool result = false; for (int i = 0; i < dim; i++) { result = result || (a[i] && b[i]); @@ -2803,7 +5405,7 @@ namespace DotProduct { } else if (ASRUtils::is_complex(*type_a)) { if (kind == 4) { std::vector> a(dim), b(dim); - populate_vector_complex(a, b, vector_a, vector_b, dim); + populate_vector_complex(al, a, b, vector_a, vector_b, dim); std::pair result = {0.0f, 0.0f}; for (int i = 0; i < dim; i++) { result.first += a[i].first * b[i].first + (a[i].second * b[i].second); @@ -2812,7 +5414,7 @@ namespace DotProduct { return EXPR(make_ComplexConstant_t(al, loc, result.first, result.second, return_type)); } else if (kind == 8) { std::vector> a(dim), b(dim); - populate_vector_complex(a, b, vector_a, vector_b, dim); + populate_vector_complex(al, a, b, vector_a, vector_b, dim); std::pair result = {0.0, 0.0}; for (int i = 0; i < dim; i++) { result.first += a[i].first * b[i].first + (a[i].second * b[i].second); @@ -2915,7 +5517,7 @@ namespace DotProduct { if (is_logical(*return_type)) { body.push_back(al, b.Assignment(result, ASRUtils::EXPR(ASR::make_LogicalConstant_t(al, loc, false, return_type)))); body.push_back(al, b.DoLoop(i, LBound(args[0], 1), UBound(args[0], 1), { - b.Assignment(result, b.LogicalOr(result, b.And(b.ArrayItem_01(args[0], {i}), b.ArrayItem_01(args[1], {i})), loc)) + b.Assignment(result, b.Or(result, b.And(b.ArrayItem_01(args[0], {i}), b.ArrayItem_01(args[1], {i})))) })); } else if (is_complex(*return_type)) { body.push_back(al, b.Assignment(result, EXPR(ASR::make_ComplexConstant_t(al, loc, 0.0, 0.0, return_type)))); @@ -2932,17 +5534,18 @@ namespace DotProduct { body.push_back(al, b.DoLoop(i, LBound(args[0], 1), UBound(args[0], 1), { b.Assignment(result, b.Add(result, EXPR(ASR::make_ComplexBinOp_t(al, loc, func_call_conjg, ASR::binopType::Mul, b.ArrayItem_01(args[1], {i}), return_type, nullptr)))) }, nullptr)); + } else if (is_real(*return_type)) { + body.push_back(al, b.Assignment(result, make_ConstantWithType(make_RealConstant_t, 0.0, return_type, loc))); + body.push_back(al, b.DoLoop(i, LBound(args[0], 1), UBound(args[0], 1), { + b.Assignment(result, b.Add(result, b.Mul(b.ArrayItem_01(args[0], {i}), b.r2r_t(b.ArrayItem_01(args[1], {i}), ASRUtils::type_get_past_array(arg_types[0]))))) + }, nullptr)); } else { - if (is_real(*return_type)) { - body.push_back(al, b.Assignment(result, make_ConstantWithType(make_RealConstant_t, 0.0, return_type, loc))); - } else { - body.push_back(al, b.Assignment(result, make_ConstantWithType(make_IntegerConstant_t, 0, return_type, loc))); - } + body.push_back(al, b.Assignment(result, make_ConstantWithType(make_IntegerConstant_t, 0, return_type, loc))); body.push_back(al, b.DoLoop(i, LBound(args[0], 1), UBound(args[0], 1), { - b.Assignment(result, b.Add(result, b.Mul(b.ArrayItem_01(args[0], {i}), b.ArrayItem_01(args[1], {i})))) + b.Assignment(result, b.Add(result, b.Mul(b.ArrayItem_01(args[0], {i}), b.i2i_t(b.ArrayItem_01(args[1], {i}), ASRUtils::type_get_past_array(arg_types[0]))))) }, nullptr)); } - body.push_back(al, Return()); + body.push_back(al, b.Return()); ASR::symbol_t *fn_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); scope->add_symbol(fn_name, fn_sym); @@ -2991,12 +5594,12 @@ namespace Transpose { Vec result_dims; result_dims.reserve(al, 2); int overload_id = 2; result_dims.push_back(al, b.set_dim(matrix_a_dims[0].m_start, - matrix_a_dims[1].m_length)); + matrix_a_dims[1].m_length)); result_dims.push_back(al, b.set_dim(matrix_a_dims[1].m_start, matrix_a_dims[0].m_length)); ret_type = ASRUtils::duplicate_type(al, ret_type, &result_dims); if (is_type_allocatable) { - ret_type = TYPE(ASR::make_Allocatable_t(al, loc, ret_type)); + ret_type = TYPE(ASRUtils::make_Allocatable_t_util(al, loc, ret_type)); } ASR::expr_t *value = nullptr; if (all_args_evaluated(args)) { @@ -3035,7 +5638,7 @@ namespace Transpose { return_type_ = ASRUtils::make_Array_t_util(al, loc, ASRUtils::extract_type(return_type_), empty_dims.p, empty_dims.size()); if( is_allocatable ) { - return_type_ = ASRUtils::TYPE(ASR::make_Allocatable_t(al, loc, return_type_)); + return_type_ = ASRUtils::TYPE(ASRUtils::make_Allocatable_t_util(al, loc, return_type_)); } } ASR::expr_t *result = declare("result", return_type_, Out); @@ -3047,7 +5650,7 @@ namespace Transpose { b.Assignment(b.ArrayItem_01(result, {j, i}), b.ArrayItem_01(args[0], {i, j})) }, nullptr) }, nullptr)); - body.push_back(al, Return()); + body.push_back(al, b.Return()); ASR::symbol_t *fn_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, body, nullptr, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); scope->add_symbol(fn_name, fn_sym); @@ -3062,16 +5665,24 @@ namespace IntrinsicArrayFunctionRegistry { verify_array_function>>& intrinsic_function_by_id_db = { {static_cast(IntrinsicArrayFunctions::Any), {&Any::instantiate_Any, &Any::verify_args}}, + {static_cast(IntrinsicArrayFunctions::All), + {&All::instantiate_All, &All::verify_args}}, + {static_cast(IntrinsicArrayFunctions::Iany), + {&Iany::instantiate_Iany, &Iany::verify_args}}, + {static_cast(IntrinsicArrayFunctions::Iall), + {&Iall::instantiate_Iall, &Iall::verify_args}}, + {static_cast(IntrinsicArrayFunctions::Norm2), + {&Norm2::instantiate_Norm2, &Norm2::verify_args}}, {static_cast(IntrinsicArrayFunctions::MatMul), {&MatMul::instantiate_MatMul, &MatMul::verify_args}}, {static_cast(IntrinsicArrayFunctions::MaxLoc), {&MaxLoc::instantiate_MaxLoc, &MaxLoc::verify_args}}, {static_cast(IntrinsicArrayFunctions::MaxVal), {&MaxVal::instantiate_MaxVal, &MaxVal::verify_args}}, - {static_cast(IntrinsicArrayFunctions::Merge), - {&Merge::instantiate_Merge, &Merge::verify_args}}, {static_cast(IntrinsicArrayFunctions::MinLoc), {&MinLoc::instantiate_MinLoc, &MinLoc::verify_args}}, + {static_cast(IntrinsicArrayFunctions::FindLoc), + {&FindLoc::instantiate_FindLoc, &FindLoc::verify_args}}, {static_cast(IntrinsicArrayFunctions::MinVal), {&MinVal::instantiate_MinVal, &MinVal::verify_args}}, {static_cast(IntrinsicArrayFunctions::Product), @@ -3080,6 +5691,8 @@ namespace IntrinsicArrayFunctionRegistry { {&Shape::instantiate_Shape, &Shape::verify_args}}, {static_cast(IntrinsicArrayFunctions::Sum), {&Sum::instantiate_Sum, &Sum::verify_args}}, + {static_cast(IntrinsicArrayFunctions::Iparity), + {&Iparity::instantiate_Iparity, &Iparity::verify_args}}, {static_cast(IntrinsicArrayFunctions::Transpose), {&Transpose::instantiate_Transpose, &Transpose::verify_args}}, {static_cast(IntrinsicArrayFunctions::Pack), @@ -3088,26 +5701,43 @@ namespace IntrinsicArrayFunctionRegistry { {&Unpack::instantiate_Unpack, &Unpack::verify_args}}, {static_cast(IntrinsicArrayFunctions::Count), {&Count::instantiate_Count, &Count::verify_args}}, + {static_cast(IntrinsicArrayFunctions::Parity), + {&Parity::instantiate_Parity, &Parity::verify_args}}, {static_cast(IntrinsicArrayFunctions::DotProduct), {&DotProduct::instantiate_DotProduct, &DotProduct::verify_args}}, + {static_cast(IntrinsicArrayFunctions::Cshift), + {&Cshift::instantiate_Cshift, &Cshift::verify_args}}, + {static_cast(IntrinsicArrayFunctions::Eoshift), + {&Eoshift::instantiate_Eoshift, &Eoshift::verify_args}}, + {static_cast(IntrinsicArrayFunctions::Spread), + {&Spread::instantiate_Spread, &Spread::verify_args}}, }; static const std::map>& function_by_name_db = { {"any", {&Any::create_Any, &Any::eval_Any}}, + {"all", {&All::create_All, &All::eval_All}}, + {"iany", {&Iany::create_Iany, &Iany::eval_Iany}}, + {"iall", {&Iall::create_Iall, &Iall::eval_Iall}}, + {"norm2", {&Norm2::create_Norm2, &Norm2::eval_Norm2}}, {"matmul", {&MatMul::create_MatMul, &MatMul::eval_MatMul}}, {"maxloc", {&MaxLoc::create_MaxLoc, nullptr}}, {"maxval", {&MaxVal::create_MaxVal, &MaxVal::eval_MaxVal}}, - {"merge", {&Merge::create_Merge, &Merge::eval_Merge}}, {"minloc", {&MinLoc::create_MinLoc, nullptr}}, + {"findloc", {&FindLoc::create_FindLoc, nullptr}}, {"minval", {&MinVal::create_MinVal, &MinVal::eval_MinVal}}, {"product", {&Product::create_Product, &Product::eval_Product}}, {"shape", {&Shape::create_Shape, &Shape::eval_Shape}}, {"sum", {&Sum::create_Sum, &Sum::eval_Sum}}, + {"iparity", {&Iparity::create_Iparity, &Iparity::eval_Iparity}}, + {"cshift", {&Cshift::create_Cshift, &Cshift::eval_Cshift}}, + {"eoshift", {&Eoshift::create_Eoshift, &Eoshift::eval_Eoshift}}, + {"spread", {&Spread::create_Spread, &Spread::eval_Spread}}, {"transpose", {&Transpose::create_Transpose, &Transpose::eval_Transpose}}, {"pack", {&Pack::create_Pack, &Pack::eval_Pack}}, {"unpack", {&Unpack::create_Unpack, &Unpack::eval_Unpack}}, {"count", {&Count::create_Count, &Count::eval_Count}}, + {"parity", {&Parity::create_Parity, &Parity::eval_Parity}}, {"dot_product", {&DotProduct::create_DotProduct, &DotProduct::eval_DotProduct}}, }; @@ -3141,17 +5771,23 @@ namespace IntrinsicArrayFunctionRegistry { */ static inline int get_dim_index(IntrinsicArrayFunctions id) { if( id == IntrinsicArrayFunctions::Any || + id == IntrinsicArrayFunctions::All || id == IntrinsicArrayFunctions::Sum || id == IntrinsicArrayFunctions::Product || + id == IntrinsicArrayFunctions::Iparity || id == IntrinsicArrayFunctions::MaxVal || id == IntrinsicArrayFunctions::MinVal || - id == IntrinsicArrayFunctions::Count) { + id == IntrinsicArrayFunctions::Count || + id == IntrinsicArrayFunctions::Parity) { return 1; // dim argument index - } else if( id == IntrinsicArrayFunctions::MatMul || id == IntrinsicArrayFunctions::Transpose || id == IntrinsicArrayFunctions::Pack || + } else if( id == IntrinsicArrayFunctions::MatMul || + id == IntrinsicArrayFunctions::Transpose || + id == IntrinsicArrayFunctions::Pack || + id == IntrinsicArrayFunctions::Cshift || + id == IntrinsicArrayFunctions::Eoshift || + id == IntrinsicArrayFunctions::Spread || id == IntrinsicArrayFunctions::Unpack ) { return 2; // return variable index - } else { - LCOMPILERS_ASSERT(false); } return -1; } @@ -3160,7 +5796,8 @@ namespace IntrinsicArrayFunctionRegistry { // Dim argument is already handled for the following if( id == IntrinsicArrayFunctions::Shape || id == IntrinsicArrayFunctions::MaxLoc || - id == IntrinsicArrayFunctions::MinLoc ) { + id == IntrinsicArrayFunctions::MinLoc || + id == IntrinsicArrayFunctions::FindLoc ) { return false; } else { return true; @@ -3168,10 +5805,10 @@ namespace IntrinsicArrayFunctionRegistry { } static inline bool is_elemental(int64_t id) { - IntrinsicArrayFunctions id_ = static_cast(id); - return (id_ == IntrinsicArrayFunctions::Merge); + // IntrinsicArrayFunctions id_ = static_cast(id); + // return (id_ == IntrinsicArrayFunctions::Merge); + return id == -1; } - } // namespace IntrinsicArrayFunctionRegistry } // namespace ASRUtils diff --git a/src/libasr/pass/intrinsic_function.cpp b/src/libasr/pass/intrinsic_function.cpp index 43f5ab1794..ed9f84bb32 100644 --- a/src/libasr/pass/intrinsic_function.cpp +++ b/src/libasr/pass/intrinsic_function.cpp @@ -9,7 +9,6 @@ #include #include -#include namespace LCompilers { @@ -45,17 +44,14 @@ class ReplaceIntrinsicFunctions: public ASR::BaseExprReplacerm_value; return; } + Vec new_args; new_args.reserve(al, x->n_args); // Replace any IntrinsicElementalFunctions in the argument first: for( size_t i = 0; i < x->n_args; i++ ) { - ASR::expr_t** current_expr_copy_ = current_expr; - current_expr = &(x->m_args[i]); - replace_expr(x->m_args[i]); ASR::call_arg_t arg0; arg0.loc = (*current_expr)->base.loc; - arg0.m_value = *current_expr; // Use the converted arg + arg0.m_value = x->m_args[i]; new_args.push_back(al, arg0); - current_expr = current_expr_copy_; } // TODO: currently we always instantiate a new function. // Rather we should reuse the old instantiation if it has @@ -73,12 +69,15 @@ class ReplaceIntrinsicFunctions: public ASR::BaseExprReplacern_args; i++ ) { arg_types.push_back(al, ASRUtils::expr_type(x->m_args[i])); } + ASR::ttype_t* type = nullptr; + type = ASRUtils::extract_type(x->m_type); ASR::expr_t* current_expr_ = instantiate_function(al, x->base.base.loc, - global_scope, arg_types, x->m_type, new_args, x->m_overload_id); + global_scope, arg_types, type, new_args, x->m_overload_id); *current_expr = current_expr_; } void replace_IntrinsicArrayFunction(ASR::IntrinsicArrayFunction_t* x) { + std::string intrinsic_name_ = std::string(ASRUtils::get_array_intrinsic_name(x->m_arr_intrinsic_id)); if (x->m_value) { *current_expr = x->m_value; return; @@ -87,14 +86,10 @@ class ReplaceIntrinsicFunctions: public ASR::BaseExprReplacer new_args; new_args.reserve(al, x->n_args); // Replace any IntrinsicArrayFunctions in the argument first: for( size_t i = 0; i < x->n_args; i++ ) { - ASR::expr_t** current_expr_copy_ = current_expr; - current_expr = &(x->m_args[i]); - replace_expr(x->m_args[i]); ASR::call_arg_t arg0; arg0.loc = (*current_expr)->base.loc; - arg0.m_value = *current_expr; // Use the converted arg + arg0.m_value = x->m_args[i]; new_args.push_back(al, arg0); - current_expr = current_expr_copy_; } // TODO: currently we always instantiate a new function. @@ -117,7 +112,9 @@ class ReplaceIntrinsicFunctions: public ASR::BaseExprReplacerm_type, new_args, x->m_overload_id); ASR::expr_t* func_call = current_expr_; *current_expr = current_expr_; - if (ASR::is_a(*func_call)) { + bool condition = ASR::is_a(*func_call); + condition = condition && ASRUtils::is_array(x->m_type); + if (condition) { ASR::symbol_t *call_sym = ASRUtils::symbol_get_past_external( ASR::down_cast(func_call)->m_name); func2intrinsicid[call_sym] = (ASRUtils::IntrinsicArrayFunctions) x->m_arr_intrinsic_id; @@ -159,13 +156,15 @@ class ReplaceFunctionCallReturningArray: public ASR::BaseExprReplacer& func2intrinsicid; public: - + ASR::expr_t* result_var_; // Declared in array_struct_temporary SymbolTable* current_scope; ReplaceFunctionCallReturningArray(Allocator& al_, Vec& pass_result_, std::map& func2intrinsicid_) : al(al_), pass_result(pass_result_), result_counter(0), - func2intrinsicid(func2intrinsicid_), current_scope(nullptr) {} + func2intrinsicid(func2intrinsicid_), + result_var_(nullptr), + current_scope(nullptr) {} // Not called from anywhere but kept for future use. // Especially if we don't find alternatives to allocatables @@ -261,113 +260,28 @@ class ReplaceFunctionCallReturningArray: public ASR::BaseExprReplacerm_name); - int n_dims = ASRUtils::extract_n_dims_from_ttype(x->m_type); - if( func2intrinsicid.find(x_m_name) == func2intrinsicid.end() || n_dims == 0 || - !ASRUtils::IntrinsicArrayFunctionRegistry::handle_dim(func2intrinsicid[x_m_name])) { - return ; + if( func2intrinsicid.find(x_m_name) == func2intrinsicid.end() ) { + return; } Vec new_args; new_args.reserve(al, x->n_args + 1); for( size_t i = 0; i < x->n_args; i++ ) { - if (x->m_args[i].m_value != nullptr) { - ASR::expr_t** current_expr_copy_9 = current_expr; - current_expr = &(x->m_args[i].m_value); - this->replace_expr(x->m_args[i].m_value); - ASR::call_arg_t new_arg; - new_arg.loc = x->m_args[i].loc; - new_arg.m_value = *current_expr; - new_args.push_back(al, new_arg); - current_expr = current_expr_copy_9; - } + ASR::call_arg_t new_arg; + new_arg.loc = x->m_args[i].loc; + new_arg.m_value = x->m_args[i].m_value; + new_args.push_back(al, new_arg); } - ASR::expr_t* result_var_ = nullptr; - int dim_index = ASRUtils::IntrinsicArrayFunctionRegistry:: - get_dim_index(func2intrinsicid[x_m_name]); - if( dim_index == 1 ) { - ASR::expr_t* dim = x->m_args[dim_index].m_value; - if( !ASRUtils::is_value_constant(ASRUtils::expr_value(dim)) ) { - result_var_ = PassUtils::create_var(result_counter, - std::string(ASRUtils::symbol_name(x->m_name)) + "_res", - x->base.base.loc, x->m_type, al, current_scope); - if (ASRUtils::is_allocatable(ASRUtils::expr_type(result_var_)) && - func2intrinsicid[x_m_name] == ASRUtils::IntrinsicArrayFunctions::Sum) { - PassUtils::allocate_res_var(al, x, new_args, result_var_, pass_result, {0, 0, 1}); - } - } else { - int constant_dim; - if (ASRUtils::extract_value(ASRUtils::expr_value(dim), constant_dim)) { - result_var_ = get_result_var_for_constant_dim(constant_dim, n_dims, - ASRUtils::symbol_name(x->m_name), x->base.base.loc, - x->m_type, x->m_args[0].m_value); - } else { - throw LCompilersException("Constant dimension cannot be extracted."); - } - } - } else if ( dim_index == 2 ) { - ASR::expr_t* func_call_count = nullptr; - if (func2intrinsicid[x_m_name] == ASRUtils::IntrinsicArrayFunctions::Pack) { - ASR::Function_t* pack = ASR::down_cast(ASRUtils::symbol_get_past_external(x->m_name)); - ASR::symbol_t* res = pack->m_symtab->resolve_symbol("result"); - if (res) { - ASR::Variable_t* res_var = ASR::down_cast(res); - ASR::Array_t* res_arr = ASR::down_cast(res_var->m_type); - if (ASR::is_a(*res_arr->m_dims[0].m_length)) { - ASRUtils::ExprStmtDuplicator expr_stmt_duplicator(al); - func_call_count = res_arr->m_dims[0].m_length; - func_call_count = expr_stmt_duplicator.duplicate_expr(func_call_count); - - ASR::FunctionCall_t* func_call = ASR::down_cast(func_call_count); - if (ASR::is_a(*func_call->m_args[0].m_value)) { - ASR::ArrayPhysicalCast_t *array_cast = ASR::down_cast(func_call->m_args[0].m_value); - array_cast->m_arg = ASR::down_cast(new_args[1].m_value)->m_arg; - array_cast->m_old = ASRUtils::extract_physical_type(ASRUtils::expr_type(array_cast->m_arg)); - array_cast->m_type = ASRUtils::duplicate_type(al, ASRUtils::expr_type(array_cast->m_arg), nullptr, - ASR::array_physical_typeType::DescriptorArray, true); - - func_call->m_args[0].m_value = ASRUtils::EXPR((ASR::asr_t*) array_cast); - } - } - } - } - result_var_ = PassUtils::create_var(result_counter, - std::string(ASRUtils::symbol_name(x->m_name)) + "_res", - x->base.base.loc, x->m_type, al, current_scope); - if (func_call_count) { - // allocate result array - Vec alloc_args; alloc_args.reserve(al, 1); - Vec alloc_dims; alloc_dims.reserve(al, 2); - ASR::alloc_arg_t alloc_arg; alloc_arg.loc = x->base.base.loc; - ASR::dimension_t dim; dim.loc = x->base.base.loc; - dim.m_start = ASRUtils::EXPR(ASR::make_IntegerConstant_t(al, x->base.base.loc, 1, - ASRUtils::TYPE(ASR::make_Integer_t(al, x->base.base.loc, 4)))); - dim.m_length = func_call_count; - alloc_dims.push_back(al, dim); - alloc_arg.m_a = result_var_; alloc_arg.m_len_expr = nullptr; - alloc_arg.m_type = nullptr; alloc_arg.m_dims = alloc_dims.p; - alloc_arg.n_dims = alloc_dims.size(); - alloc_args.push_back(al, alloc_arg); - - ASR::stmt_t* allocate_stmt = ASRUtils::STMT(ASR::make_Allocate_t(al, - x->base.base.loc, alloc_args.p, alloc_args.n, nullptr, nullptr, nullptr)); - pass_result.push_back(al, allocate_stmt); - } - } else { - LCOMPILERS_ASSERT(false); - } - result_counter += 1; ASR::call_arg_t new_arg; - LCOMPILERS_ASSERT(result_var_) - new_arg.loc = result_var_->base.loc; - new_arg.m_value = result_var_; + LCOMPILERS_ASSERT(this->result_var_) + new_arg.loc = this->result_var_->base.loc; + new_arg.m_value = this->result_var_; new_args.push_back(al, new_arg); - pass_result.push_back(al, ASRUtils::STMT(ASRUtils::make_SubroutineCall_t_util( + ASR::stmt_t* subrout_call = ASRUtils::STMT(ASRUtils::make_SubroutineCall_t_util( al, x->base.base.loc, x->m_name, x->m_original_name, new_args.p, - new_args.size(), x->m_dt, nullptr, false, false))); - - *current_expr = new_args.p[new_args.size() - 1].m_value; + new_args.size(), x->m_dt, nullptr, false, false)); + pass_result.push_back(al, subrout_call); } - }; class ReplaceFunctionCallReturningArrayVisitor : public ASR::CallReplacerOnExpressionsVisitor @@ -383,10 +297,13 @@ class ReplaceFunctionCallReturningArrayVisitor : public ASR::CallReplacerOnExpre ReplaceFunctionCallReturningArrayVisitor(Allocator& al_, std::map& func2intrinsicid_) : - al(al_), replacer(al_, pass_result, func2intrinsicid_), parent_body(nullptr) { + al(al_), + replacer(al_, pass_result, func2intrinsicid_), + parent_body(nullptr) { pass_result.n = 0; } + void call_replacer() { replacer.current_expr = current_expr; replacer.current_scope = current_scope; @@ -409,25 +326,34 @@ class ReplaceFunctionCallReturningArrayVisitor : public ASR::CallReplacerOnExpre parent_body = &body; visit_stmt(*m_body[i]); parent_body = parent_body_copy; - for (size_t j=0; j < pass_result.size(); j++) { - body.push_back(al, pass_result[j]); + if( pass_result.size() > 0 ) { + for (size_t j=0; j < pass_result.size(); j++) { + body.push_back(al, pass_result[j]); + } + } else { + body.push_back(al, m_body[i]); } - body.push_back(al, m_body[i]); } m_body = body.p; n_body = body.size(); pass_result.n = 0; } + void visit_Assignment(const ASR::Assignment_t& x) { + replacer.result_var_ = x.m_target; + ASR::CallReplacerOnExpressionsVisitor::visit_Assignment(x); + replacer.result_var_ = nullptr; + } + }; void pass_replace_intrinsic_function(Allocator &al, ASR::TranslationUnit_t &unit, - const LCompilers::PassOptions& /*pass_options*/) { + const LCompilers::PassOptions& /*pass_options*/) { std::map func2intrinsicid; ReplaceIntrinsicFunctionsVisitor v(al, unit.m_symtab, func2intrinsicid); v.visit_TranslationUnit(unit); - ReplaceFunctionCallReturningArrayVisitor u(al, func2intrinsicid); - u.visit_TranslationUnit(unit); + // ReplaceFunctionCallReturningArrayVisitor u(al, func2intrinsicid); + // u.visit_TranslationUnit(unit); PassUtils::UpdateDependenciesVisitor w(al); w.visit_TranslationUnit(unit); } diff --git a/src/libasr/pass/intrinsic_function_registry.h b/src/libasr/pass/intrinsic_function_registry.h index d68cba8207..0ac6ff6800 100644 --- a/src/libasr/pass/intrinsic_function_registry.h +++ b/src/libasr/pass/intrinsic_function_registry.h @@ -16,7 +16,7 @@ namespace ASRUtils { return #X; \ } -inline std::string get_intrinsic_name(int x) { +inline std::string get_intrinsic_name(int64_t x) { switch (x) { INTRINSIC_NAME_CASE(ObjectType) INTRINSIC_NAME_CASE(Kind) @@ -25,6 +25,12 @@ inline std::string get_intrinsic_name(int x) { INTRINSIC_NAME_CASE(Cos) INTRINSIC_NAME_CASE(Tan) INTRINSIC_NAME_CASE(Asin) + INTRINSIC_NAME_CASE(Asind) + INTRINSIC_NAME_CASE(Acosd) + INTRINSIC_NAME_CASE(Atand) + INTRINSIC_NAME_CASE(Sind) + INTRINSIC_NAME_CASE(Cosd) + INTRINSIC_NAME_CASE(Tand) INTRINSIC_NAME_CASE(Acos) INTRINSIC_NAME_CASE(Atan) INTRINSIC_NAME_CASE(Sinh) @@ -36,14 +42,17 @@ inline std::string get_intrinsic_name(int x) { INTRINSIC_NAME_CASE(Atanh) INTRINSIC_NAME_CASE(Erf) INTRINSIC_NAME_CASE(Erfc) + INTRINSIC_NAME_CASE(ErfcScaled) INTRINSIC_NAME_CASE(Gamma) INTRINSIC_NAME_CASE(Log) INTRINSIC_NAME_CASE(Log10) + INTRINSIC_NAME_CASE(Logical) INTRINSIC_NAME_CASE(LogGamma) INTRINSIC_NAME_CASE(Trunc) INTRINSIC_NAME_CASE(Fix) INTRINSIC_NAME_CASE(Abs) INTRINSIC_NAME_CASE(Aimag) + INTRINSIC_NAME_CASE(Dreal) INTRINSIC_NAME_CASE(Exp) INTRINSIC_NAME_CASE(Exp2) INTRINSIC_NAME_CASE(Expm1) @@ -51,16 +60,30 @@ inline std::string get_intrinsic_name(int x) { INTRINSIC_NAME_CASE(FlipSign) INTRINSIC_NAME_CASE(FloorDiv) INTRINSIC_NAME_CASE(Mod) - INTRINSIC_NAME_CASE(Trailz) + INTRINSIC_NAME_CASE(Isnan) + INTRINSIC_NAME_CASE(Nearest) + INTRINSIC_NAME_CASE(CompilerVersion) + INTRINSIC_NAME_CASE(CompilerOptions) + INTRINSIC_NAME_CASE(CommandArgumentCount) + INTRINSIC_NAME_CASE(Spacing) INTRINSIC_NAME_CASE(Modulo) + INTRINSIC_NAME_CASE(OutOfRange) INTRINSIC_NAME_CASE(BesselJ0) INTRINSIC_NAME_CASE(BesselJ1) + INTRINSIC_NAME_CASE(BesselJN) INTRINSIC_NAME_CASE(BesselY0) + INTRINSIC_NAME_CASE(BesselY1) + INTRINSIC_NAME_CASE(BesselYN) + INTRINSIC_NAME_CASE(SameTypeAs) INTRINSIC_NAME_CASE(Mvbits) + INTRINSIC_NAME_CASE(MoveAlloc) + INTRINSIC_NAME_CASE(Merge) + INTRINSIC_NAME_CASE(Mergebits) INTRINSIC_NAME_CASE(Shiftr) INTRINSIC_NAME_CASE(Rshift) INTRINSIC_NAME_CASE(Shiftl) INTRINSIC_NAME_CASE(Dshiftl) + INTRINSIC_NAME_CASE(Dshiftr) INTRINSIC_NAME_CASE(Ishft) INTRINSIC_NAME_CASE(Bgt) INTRINSIC_NAME_CASE(Blt) @@ -75,8 +98,11 @@ inline std::string get_intrinsic_name(int x) { INTRINSIC_NAME_CASE(SetExponent) INTRINSIC_NAME_CASE(Not) INTRINSIC_NAME_CASE(Iand) + INTRINSIC_NAME_CASE(And) INTRINSIC_NAME_CASE(Ior) + INTRINSIC_NAME_CASE(Or) INTRINSIC_NAME_CASE(Ieor) + INTRINSIC_NAME_CASE(Xor) INTRINSIC_NAME_CASE(Ibclr) INTRINSIC_NAME_CASE(Ibset) INTRINSIC_NAME_CASE(Btest) @@ -90,14 +116,20 @@ inline std::string get_intrinsic_name(int x) { INTRINSIC_NAME_CASE(StringFindSet) INTRINSIC_NAME_CASE(SubstrIndex) INTRINSIC_NAME_CASE(Range) + INTRINSIC_NAME_CASE(Radix) + INTRINSIC_NAME_CASE(StorageSize) INTRINSIC_NAME_CASE(Hypot) INTRINSIC_NAME_CASE(SelectedIntKind) INTRINSIC_NAME_CASE(SelectedRealKind) INTRINSIC_NAME_CASE(SelectedCharKind) + INTRINSIC_NAME_CASE(Present) INTRINSIC_NAME_CASE(Adjustl) INTRINSIC_NAME_CASE(Adjustr) + INTRINSIC_NAME_CASE(StringLenTrim) + INTRINSIC_NAME_CASE(StringTrim) INTRINSIC_NAME_CASE(Ichar) INTRINSIC_NAME_CASE(Char) + INTRINSIC_NAME_CASE(Achar) INTRINSIC_NAME_CASE(MinExponent) INTRINSIC_NAME_CASE(MaxExponent) INTRINSIC_NAME_CASE(Ishftc) @@ -116,9 +148,11 @@ inline std::string get_intrinsic_name(int x) { INTRINSIC_NAME_CASE(Sign) INTRINSIC_NAME_CASE(SignFromValue) INTRINSIC_NAME_CASE(Nint) + INTRINSIC_NAME_CASE(Idnint) INTRINSIC_NAME_CASE(Aint) INTRINSIC_NAME_CASE(Popcnt) INTRINSIC_NAME_CASE(Poppar) + INTRINSIC_NAME_CASE(Real) INTRINSIC_NAME_CASE(Dim) INTRINSIC_NAME_CASE(Anint) INTRINSIC_NAME_CASE(Sqrt) @@ -133,6 +167,8 @@ inline std::string get_intrinsic_name(int x) { INTRINSIC_NAME_CASE(Epsilon) INTRINSIC_NAME_CASE(Precision) INTRINSIC_NAME_CASE(Tiny) + INTRINSIC_NAME_CASE(BitSize) + INTRINSIC_NAME_CASE(NewLine) INTRINSIC_NAME_CASE(Conjg) INTRINSIC_NAME_CASE(Huge) INTRINSIC_NAME_CASE(Dprod) @@ -162,8 +198,7 @@ inline std::string get_intrinsic_name(int x) { INTRINSIC_NAME_CASE(SymbolicLogQ) INTRINSIC_NAME_CASE(SymbolicSinQ) INTRINSIC_NAME_CASE(SymbolicGetArgument) - INTRINSIC_NAME_CASE(SymbolicIsInteger) - INTRINSIC_NAME_CASE(SymbolicIsPositive) + INTRINSIC_NAME_CASE(Int) default : { throw LCompilersException("pickle: intrinsic_id not implemented"); } @@ -178,53 +213,79 @@ namespace IntrinsicElementalFunctionRegistry { {static_cast(IntrinsicElementalFunctions::ObjectType), {nullptr, &ObjectType::verify_args}}, {static_cast(IntrinsicElementalFunctions::Gamma), - {&Gamma::instantiate_Gamma, &UnaryIntrinsicFunction::verify_args}}, + {&Gamma::instantiate_Gamma, &Gamma::verify_args}}, {static_cast(IntrinsicElementalFunctions::Log10), - {&Log10::instantiate_Log10, &UnaryIntrinsicFunction::verify_args}}, - {static_cast(IntrinsicElementalFunctions::Log), - {&Log::instantiate_Log, &UnaryIntrinsicFunction::verify_args}}, + {&Log10::instantiate_Log10, &Log10::verify_args}}, {static_cast(IntrinsicElementalFunctions::LogGamma), - {&LogGamma::instantiate_LogGamma, &UnaryIntrinsicFunction::verify_args}}, + {&LogGamma::instantiate_LogGamma, &LogGamma::verify_args}}, {static_cast(IntrinsicElementalFunctions::Erf), - {&Erf::instantiate_Erf, &UnaryIntrinsicFunction::verify_args}}, + {&Erf::instantiate_Erf, &Erf::verify_args}}, {static_cast(IntrinsicElementalFunctions::Erfc), - {&Erfc::instantiate_Erfc, &UnaryIntrinsicFunction::verify_args}}, + {&Erfc::instantiate_Erfc, &Erfc::verify_args}}, + {static_cast(IntrinsicElementalFunctions::ErfcScaled), + {&ErfcScaled::instantiate_ErfcScaled, &ErfcScaled::verify_args}}, {static_cast(IntrinsicElementalFunctions::Trunc), - {&Trunc::instantiate_Trunc, &UnaryIntrinsicFunction::verify_args}}, + {&Trunc::instantiate_Trunc, &Trunc::verify_args}}, {static_cast(IntrinsicElementalFunctions::Fix), - {&Fix::instantiate_Fix, &UnaryIntrinsicFunction::verify_args}}, + {&Fix::instantiate_Fix, &Fix::verify_args}}, {static_cast(IntrinsicElementalFunctions::Sin), - {&Sin::instantiate_Sin, &UnaryIntrinsicFunction::verify_args}}, + {&Sin::instantiate_Sin, &Sin::verify_args}}, + {static_cast(IntrinsicElementalFunctions::OutOfRange), + {&OutOfRange::instantiate_OutOfRange, &OutOfRange::verify_args}}, + {static_cast(IntrinsicElementalFunctions::BesselJ0), + {&BesselJ0::instantiate_BesselJ0, &BesselJ0::verify_args}}, + {static_cast(IntrinsicElementalFunctions::BesselJ1), + {&BesselJ1::instantiate_BesselJ1, &BesselJ1::verify_args}}, + {static_cast(IntrinsicElementalFunctions::BesselY0), + {&BesselY0::instantiate_BesselY0, &BesselY0::verify_args}}, + {static_cast(IntrinsicElementalFunctions::BesselY1), + {&BesselY1::instantiate_BesselY1, &BesselY1::verify_args}}, + {static_cast(IntrinsicElementalFunctions::Asind), + {&Asind::instantiate_Asind, &Asind::verify_args}}, + {static_cast(IntrinsicElementalFunctions::Acosd), + {&Acosd::instantiate_Acosd, &Acosd::verify_args}}, + {static_cast(IntrinsicElementalFunctions::Atand), + {&Atand::instantiate_Atand, &Atand::verify_args}}, + {static_cast(IntrinsicElementalFunctions::Sind), + {&Sind::instantiate_Sind, &Sind::verify_args}}, + {static_cast(IntrinsicElementalFunctions::Cosd), + {&Cosd::instantiate_Cosd, &Cosd::verify_args}}, + {static_cast(IntrinsicElementalFunctions::Tand), + {&Tand::instantiate_Tand, &Tand::verify_args}}, {static_cast(IntrinsicElementalFunctions::Cos), - {&Cos::instantiate_Cos, &UnaryIntrinsicFunction::verify_args}}, + {&Cos::instantiate_Cos, &Cos::verify_args}}, {static_cast(IntrinsicElementalFunctions::Tan), - {&Tan::instantiate_Tan, &UnaryIntrinsicFunction::verify_args}}, + {&Tan::instantiate_Tan, &Tan::verify_args}}, {static_cast(IntrinsicElementalFunctions::Asin), - {&Asin::instantiate_Asin, &UnaryIntrinsicFunction::verify_args}}, + {&Asin::instantiate_Asin, &Asin::verify_args}}, {static_cast(IntrinsicElementalFunctions::Acos), - {&Acos::instantiate_Acos, &UnaryIntrinsicFunction::verify_args}}, + {&Acos::instantiate_Acos, &Acos::verify_args}}, {static_cast(IntrinsicElementalFunctions::Atan), - {&Atan::instantiate_Atan, &UnaryIntrinsicFunction::verify_args}}, + {&Atan::instantiate_Atan, &Atan::verify_args}}, {static_cast(IntrinsicElementalFunctions::Sinh), - {&Sinh::instantiate_Sinh, &UnaryIntrinsicFunction::verify_args}}, + {&Sinh::instantiate_Sinh, &Sinh::verify_args}}, {static_cast(IntrinsicElementalFunctions::Cosh), - {&Cosh::instantiate_Cosh, &UnaryIntrinsicFunction::verify_args}}, + {&Cosh::instantiate_Cosh, &Cosh::verify_args}}, {static_cast(IntrinsicElementalFunctions::Tanh), - {&Tanh::instantiate_Tanh, &UnaryIntrinsicFunction::verify_args}}, + {&Tanh::instantiate_Tanh, &Tanh::verify_args}}, {static_cast(IntrinsicElementalFunctions::Atan2), - {&Atan2::instantiate_Atan2, &BinaryIntrinsicFunction::verify_args}}, + {&Atan2::instantiate_Atan2, &Atan2::verify_args}}, {static_cast(IntrinsicElementalFunctions::Asinh), - {&Asinh::instantiate_Asinh, &UnaryIntrinsicFunction::verify_args}}, + {&Asinh::instantiate_Asinh, &Asinh::verify_args}}, {static_cast(IntrinsicElementalFunctions::Acosh), - {&Acosh::instantiate_Acosh, &UnaryIntrinsicFunction::verify_args}}, + {&Acosh::instantiate_Acosh, &Acosh::verify_args}}, {static_cast(IntrinsicElementalFunctions::Atanh), - {&Atanh::instantiate_Atanh, &UnaryIntrinsicFunction::verify_args}}, + {&Atanh::instantiate_Atanh, &Atanh::verify_args}}, + {static_cast(IntrinsicElementalFunctions::Log), + {&Log::instantiate_Log, &Log::verify_args}}, + {static_cast(IntrinsicElementalFunctions::Logical), + {&Logical::instantiate_Logical, &Logical::verify_args}}, {static_cast(IntrinsicElementalFunctions::Exp), - {&Exp::instantiate_Exp, &UnaryIntrinsicFunction::verify_args}}, + {&Exp::instantiate_Exp, &Exp::verify_args}}, {static_cast(IntrinsicElementalFunctions::Exp2), - {nullptr, &UnaryIntrinsicFunction::verify_args}}, + {nullptr, &Exp2::verify_args}}, {static_cast(IntrinsicElementalFunctions::Expm1), - {nullptr, &UnaryIntrinsicFunction::verify_args}}, + {nullptr, &Expm1::verify_args}}, {static_cast(IntrinsicElementalFunctions::FMA), {&FMA::instantiate_FMA, &FMA::verify_args}}, {static_cast(IntrinsicElementalFunctions::FlipSign), @@ -235,32 +296,58 @@ namespace IntrinsicElementalFunctionRegistry { {&Mod::instantiate_Mod, &Mod::verify_args}}, {static_cast(IntrinsicElementalFunctions::Trailz), {&Trailz::instantiate_Trailz, &Trailz::verify_args}}, + {static_cast(IntrinsicElementalFunctions::Isnan), + {&Isnan::instantiate_Isnan, &Isnan::verify_args}}, + {static_cast(IntrinsicElementalFunctions::Nearest), + {&Nearest::instantiate_Nearest, &Nearest::verify_args}}, + {static_cast(IntrinsicElementalFunctions::CompilerVersion), + {nullptr, &CompilerVersion::verify_args}}, + {static_cast(IntrinsicElementalFunctions::CompilerOptions), + {nullptr, &CompilerOptions::verify_args}}, + {static_cast(IntrinsicElementalFunctions::CommandArgumentCount), + {&CommandArgumentCount::instantiate_CommandArgumentCount, &CommandArgumentCount::verify_args}}, + {static_cast(IntrinsicElementalFunctions::Spacing), + {&Spacing::instantiate_Spacing, &Spacing::verify_args}}, {static_cast(IntrinsicElementalFunctions::Modulo), {&Modulo::instantiate_Modulo, &Modulo::verify_args}}, - {static_cast(IntrinsicElementalFunctions::BesselJ0), - {&BesselJ0::instantiate_BesselJ0, &BesselJ0::verify_args}}, - {static_cast(IntrinsicElementalFunctions::BesselJ1), - {&BesselJ1::instantiate_BesselJ1, &BesselJ1::verify_args}}, - {static_cast(IntrinsicElementalFunctions::BesselY0), - {&BesselY0::instantiate_BesselY0, &BesselY0::verify_args}}, + {static_cast(IntrinsicElementalFunctions::BesselJN), + {&BesselJN::instantiate_BesselJN, &BesselJN::verify_args}}, + {static_cast(IntrinsicElementalFunctions::BesselYN), + {&BesselYN::instantiate_BesselYN, &BesselYN::verify_args}}, + {static_cast(IntrinsicElementalFunctions::SameTypeAs), + {nullptr, &SameTypeAs::verify_args}}, + {static_cast(IntrinsicElementalFunctions::Merge), + {&Merge::instantiate_Merge, &Merge::verify_args}}, {static_cast(IntrinsicElementalFunctions::Mvbits), {&Mvbits::instantiate_Mvbits, &Mvbits::verify_args}}, + {static_cast(IntrinsicElementalFunctions::MoveAlloc), + {&MoveAlloc::instantiate_MoveAlloc, &MoveAlloc::verify_args}}, + {static_cast(IntrinsicElementalFunctions::Mergebits), + {&Mergebits::instantiate_Mergebits, &Mergebits::verify_args}}, {static_cast(IntrinsicElementalFunctions::Shiftr), {&Shiftr::instantiate_Shiftr, &Shiftr::verify_args}}, {static_cast(IntrinsicElementalFunctions::Adjustl), {&Adjustl::instantiate_Adjustl, &Adjustl::verify_args}}, {static_cast(IntrinsicElementalFunctions::Adjustr), {&Adjustr::instantiate_Adjustr, &Adjustr::verify_args}}, + {static_cast(IntrinsicElementalFunctions::StringLenTrim), + {&StringLenTrim::instantiate_StringLenTrim, &StringLenTrim::verify_args}}, + {static_cast(IntrinsicElementalFunctions::StringTrim), + {&StringTrim::instantiate_StringTrim, &StringTrim::verify_args}}, {static_cast(IntrinsicElementalFunctions::Ichar), {&Ichar::instantiate_Ichar, &Ichar::verify_args}}, {static_cast(IntrinsicElementalFunctions::Char), {&Char::instantiate_Char, &Char::verify_args}}, + {static_cast(IntrinsicElementalFunctions::Achar), + {&Achar::instantiate_Achar, &Achar::verify_args}}, {static_cast(IntrinsicElementalFunctions::Rshift), {&Rshift::instantiate_Rshift, &Rshift::verify_args}}, {static_cast(IntrinsicElementalFunctions::Shiftl), {&Shiftl::instantiate_Shiftl, &Shiftl::verify_args}}, {static_cast(IntrinsicElementalFunctions::Dshiftl), {&Dshiftl::instantiate_Dshiftl, &Dshiftl::verify_args}}, + {static_cast(IntrinsicElementalFunctions::Dshiftr), + {&Dshiftr::instantiate_Dshiftr, &Dshiftr::verify_args}}, {static_cast(IntrinsicElementalFunctions::Ishft), {&Ishft::instantiate_Ishft, &Ishft::verify_args}}, {static_cast(IntrinsicElementalFunctions::Bgt), @@ -289,10 +376,16 @@ namespace IntrinsicElementalFunctionRegistry { {&Not::instantiate_Not, &Not::verify_args}}, {static_cast(IntrinsicElementalFunctions::Iand), {&Iand::instantiate_Iand, &Iand::verify_args}}, + {static_cast(IntrinsicElementalFunctions::And), + {&And::instantiate_And, &And::verify_args}}, {static_cast(IntrinsicElementalFunctions::Ior), {&Ior::instantiate_Ior, &Ior::verify_args}}, + {static_cast(IntrinsicElementalFunctions::Or), + {&Or::instantiate_Or, &Or::verify_args}}, {static_cast(IntrinsicElementalFunctions::Ieor), {&Ieor::instantiate_Ieor, &Ieor::verify_args}}, + {static_cast(IntrinsicElementalFunctions::Xor), + {&Xor::instantiate_Xor, &Xor::verify_args}}, {static_cast(IntrinsicElementalFunctions::Ibclr), {&Ibclr::instantiate_Ibclr, &Ibclr::verify_args}}, {static_cast(IntrinsicElementalFunctions::Btest), @@ -308,7 +401,7 @@ namespace IntrinsicElementalFunctionRegistry { {static_cast(IntrinsicElementalFunctions::Hypot), {&Hypot::instantiate_Hypot, &Hypot::verify_args}}, {static_cast(IntrinsicElementalFunctions::Kind), - {&Kind::instantiate_Kind, &Kind::verify_args}}, + {nullptr, &Kind::verify_args}}, {static_cast(IntrinsicElementalFunctions::Rank), {nullptr, &Rank::verify_args}}, {static_cast(IntrinsicElementalFunctions::Digits), @@ -324,13 +417,15 @@ namespace IntrinsicElementalFunctionRegistry { {static_cast(IntrinsicElementalFunctions::SubstrIndex), {&SubstrIndex::instantiate_SubstrIndex, &SubstrIndex::verify_args}}, {static_cast(IntrinsicElementalFunctions::MinExponent), - {&MinExponent::instantiate_MinExponent, &MinExponent::verify_args}}, + {nullptr, &MinExponent::verify_args}}, {static_cast(IntrinsicElementalFunctions::MaxExponent), - {&MaxExponent::instantiate_MaxExponent, &MaxExponent::verify_args}}, + {nullptr, &MaxExponent::verify_args}}, {static_cast(IntrinsicElementalFunctions::Abs), {&Abs::instantiate_Abs, &Abs::verify_args}}, {static_cast(IntrinsicElementalFunctions::Aimag), {&Aimag::instantiate_Aimag, &Aimag::verify_args}}, + {static_cast(IntrinsicElementalFunctions::Dreal), + {&Dreal::instantiate_Dreal, &Dreal::verify_args}}, {static_cast(IntrinsicElementalFunctions::Partition), {&Partition::instantiate_Partition, &Partition::verify_args}}, {static_cast(IntrinsicElementalFunctions::ListIndex), @@ -359,6 +454,8 @@ namespace IntrinsicElementalFunctionRegistry { {&Sign::instantiate_Sign, &Sign::verify_args}}, {static_cast(IntrinsicElementalFunctions::Radix), {nullptr, &Radix::verify_args}}, + {static_cast(IntrinsicElementalFunctions::StorageSize), + {nullptr, &StorageSize::verify_args}}, {static_cast(IntrinsicElementalFunctions::Scale), {&Scale::instantiate_Scale, &Scale::verify_args}}, {static_cast(IntrinsicElementalFunctions::Dprod), @@ -371,8 +468,12 @@ namespace IntrinsicElementalFunctionRegistry { {&Popcnt::instantiate_Popcnt, &Popcnt::verify_args}}, {static_cast(IntrinsicElementalFunctions::Poppar), {&Poppar::instantiate_Poppar, &Poppar::verify_args}}, + {static_cast(IntrinsicElementalFunctions::Real), + {&Real::instantiate_Real, &Real::verify_args}}, {static_cast(IntrinsicElementalFunctions::Nint), {&Nint::instantiate_Nint, &Nint::verify_args}}, + {static_cast(IntrinsicElementalFunctions::Idnint), + {&Idnint::instantiate_Idnint, &Idnint::verify_args}}, {static_cast(IntrinsicElementalFunctions::Anint), {&Anint::instantiate_Anint, &Anint::verify_args}}, {static_cast(IntrinsicElementalFunctions::Dim), @@ -405,10 +506,16 @@ namespace IntrinsicElementalFunctionRegistry { {nullptr, &Precision::verify_args}}, {static_cast(IntrinsicElementalFunctions::Tiny), {nullptr, &UnaryIntrinsicFunction::verify_args}}, + {static_cast(IntrinsicElementalFunctions::BitSize), + {nullptr, &UnaryIntrinsicFunction::verify_args}}, + {static_cast(IntrinsicElementalFunctions::NewLine), + {nullptr, &UnaryIntrinsicFunction::verify_args}}, {static_cast(IntrinsicElementalFunctions::Huge), {nullptr, &UnaryIntrinsicFunction::verify_args}}, {static_cast(IntrinsicElementalFunctions::SelectedIntKind), {&SelectedIntKind::instantiate_SelectedIntKind, &SelectedIntKind::verify_args}}, + {static_cast(IntrinsicElementalFunctions::Present), + {&Present::instantiate_Present, &Present::verify_args}}, {static_cast(IntrinsicElementalFunctions::SelectedRealKind), {&SelectedRealKind::instantiate_SelectedRealKind, &SelectedRealKind::verify_args}}, {static_cast(IntrinsicElementalFunctions::SelectedCharKind), @@ -465,6 +572,10 @@ namespace IntrinsicElementalFunctionRegistry { {nullptr, &SymbolicSinQ::verify_args}}, {static_cast(IntrinsicElementalFunctions::SymbolicGetArgument), {nullptr, &SymbolicGetArgument::verify_args}}, + {static_cast(IntrinsicElementalFunctions::CommandArgumentCount), + {&CommandArgumentCount::instantiate_CommandArgumentCount, &CommandArgumentCount::verify_args}}, + {static_cast(IntrinsicElementalFunctions::Int), + {&Int::instantiate_Int, &Int::verify_args}}, {static_cast(IntrinsicElementalFunctions::SymbolicIsInteger), {nullptr, &SymbolicIsInteger::verify_args}}, {static_cast(IntrinsicElementalFunctions::SymbolicIsPositive), @@ -480,12 +591,16 @@ namespace IntrinsicElementalFunctionRegistry { "log"}, {static_cast(IntrinsicElementalFunctions::Log10), "log10"}, + {static_cast(IntrinsicElementalFunctions::Logical), + "logical"}, {static_cast(IntrinsicElementalFunctions::LogGamma), "log_gamma"}, {static_cast(IntrinsicElementalFunctions::Erf), "erf"}, {static_cast(IntrinsicElementalFunctions::Erfc), "erfc"}, + {static_cast(IntrinsicElementalFunctions::ErfcScaled), + "erfc_scaled"}, {static_cast(IntrinsicElementalFunctions::Trunc), "trunc"}, {static_cast(IntrinsicElementalFunctions::Fix), @@ -520,6 +635,8 @@ namespace IntrinsicElementalFunctionRegistry { "abs"}, {static_cast(IntrinsicElementalFunctions::Aimag), "aimag"}, + {static_cast(IntrinsicElementalFunctions::Dreal), + "dreal"}, {static_cast(IntrinsicElementalFunctions::Exp), "exp"}, {static_cast(IntrinsicElementalFunctions::Exp2), @@ -534,14 +651,56 @@ namespace IntrinsicElementalFunctionRegistry { "mod"}, {static_cast(IntrinsicElementalFunctions::Trailz), "trailz"}, + {static_cast(IntrinsicElementalFunctions::Isnan), + "isnan"}, + {static_cast(IntrinsicElementalFunctions::Nearest), + "nearest"}, + {static_cast(IntrinsicElementalFunctions::CompilerVersion), + "compiler_version"}, + {static_cast(IntrinsicElementalFunctions::CompilerOptions), + "compiler_options"}, + {static_cast(IntrinsicElementalFunctions::CommandArgumentCount), + "command_argument_count"}, + {static_cast(IntrinsicElementalFunctions::Spacing), + "spacing"}, {static_cast(IntrinsicElementalFunctions::Modulo), "modulo"}, + {static_cast(IntrinsicElementalFunctions::Asin), + "asind"}, + {static_cast(IntrinsicElementalFunctions::Acos), + "acosd"}, + {static_cast(IntrinsicElementalFunctions::Atan), + "atand"}, + {static_cast(IntrinsicElementalFunctions::Sind), + "sind"}, + {static_cast(IntrinsicElementalFunctions::Cosd), + "cosd"}, + {static_cast(IntrinsicElementalFunctions::Tand), + "tand"}, + {static_cast(IntrinsicElementalFunctions::OutOfRange), + "out_of_range"}, {static_cast(IntrinsicElementalFunctions::BesselJ0), "bessel_j0"}, + {static_cast(IntrinsicElementalFunctions::BesselJ1), + "bessel_j1"}, {static_cast(IntrinsicElementalFunctions::BesselY0), "bessel_y0"}, + {static_cast(IntrinsicElementalFunctions::BesselY1), + "bessel_y1"}, + {static_cast(IntrinsicElementalFunctions::BesselJN), + "bessel_jn"}, + {static_cast(IntrinsicElementalFunctions::BesselYN), + "bessel_yn"}, + {static_cast(IntrinsicElementalFunctions::SameTypeAs), + "same_type_as"}, + {static_cast(IntrinsicElementalFunctions::Merge), + "merge"}, {static_cast(IntrinsicElementalFunctions::Mvbits), "mvbits"}, + {static_cast(IntrinsicElementalFunctions::MoveAlloc), + "move_alloc"}, + {static_cast(IntrinsicElementalFunctions::Mergebits), + "mergebits"}, {static_cast(IntrinsicElementalFunctions::Shiftr), "shiftr"}, {static_cast(IntrinsicElementalFunctions::Rshift), @@ -550,14 +709,22 @@ namespace IntrinsicElementalFunctionRegistry { "adjustl"}, {static_cast(IntrinsicElementalFunctions::Adjustr), "adjustr"}, + {static_cast(IntrinsicElementalFunctions::StringLenTrim), + "len_trim"}, + {static_cast(IntrinsicElementalFunctions::StringTrim), + "trim"}, {static_cast(IntrinsicElementalFunctions::Ichar), "ichar"}, {static_cast(IntrinsicElementalFunctions::Char), "char"}, + {static_cast(IntrinsicElementalFunctions::Achar), + "achar"}, {static_cast(IntrinsicElementalFunctions::Shiftl), "shiftl"}, {static_cast(IntrinsicElementalFunctions::Dshiftl), "dshiftl"}, + {static_cast(IntrinsicElementalFunctions::Dshiftr), + "dshiftr"}, {static_cast(IntrinsicElementalFunctions::Ishft), "ishft"}, {static_cast(IntrinsicElementalFunctions::Bgt), @@ -586,10 +753,16 @@ namespace IntrinsicElementalFunctionRegistry { "not"}, {static_cast(IntrinsicElementalFunctions::Iand), "iand"}, + {static_cast(IntrinsicElementalFunctions::And), + "and"}, {static_cast(IntrinsicElementalFunctions::Ior), "ior"}, + {static_cast(IntrinsicElementalFunctions::Or), + "or"}, {static_cast(IntrinsicElementalFunctions::Ieor), "ieor"}, + {static_cast(IntrinsicElementalFunctions::Xor), + "xor"}, {static_cast(IntrinsicElementalFunctions::Ibclr), "ibclr"}, {static_cast(IntrinsicElementalFunctions::Ibset), @@ -606,6 +779,8 @@ namespace IntrinsicElementalFunctionRegistry { "hypot"}, {static_cast(IntrinsicElementalFunctions::SelectedIntKind), "selected_int_kind"}, + {static_cast(IntrinsicElementalFunctions::Present), + "present"}, {static_cast(IntrinsicElementalFunctions::SelectedRealKind), "selected_real_kind"}, {static_cast(IntrinsicElementalFunctions::SelectedCharKind), @@ -658,6 +833,8 @@ namespace IntrinsicElementalFunctionRegistry { "ishftc"}, {static_cast(IntrinsicElementalFunctions::Radix), "radix"}, + {static_cast(IntrinsicElementalFunctions::StorageSize), + "storage_size"}, {static_cast(IntrinsicElementalFunctions::Scale), "scale"}, {static_cast(IntrinsicElementalFunctions::Dprod), @@ -672,8 +849,12 @@ namespace IntrinsicElementalFunctionRegistry { "popcnt"}, {static_cast(IntrinsicElementalFunctions::Poppar), "poppar"}, + {static_cast(IntrinsicElementalFunctions::Real), + "real"}, {static_cast(IntrinsicElementalFunctions::Nint), "nint"}, + {static_cast(IntrinsicElementalFunctions::Idnint), + "idnint"}, {static_cast(IntrinsicElementalFunctions::Anint), "anint"}, {static_cast(IntrinsicElementalFunctions::Dim), @@ -704,6 +885,10 @@ namespace IntrinsicElementalFunctionRegistry { "precision"}, {static_cast(IntrinsicElementalFunctions::Tiny), "tiny"}, + {static_cast(IntrinsicElementalFunctions::BitSize), + "bit_size"}, + {static_cast(IntrinsicElementalFunctions::NewLine), + "new_line"}, {static_cast(IntrinsicElementalFunctions::Huge), "huge"}, {static_cast(IntrinsicElementalFunctions::SymbolicSymbol), @@ -762,6 +947,8 @@ namespace IntrinsicElementalFunctionRegistry { "SymbolicIsInteger"}, {static_cast(IntrinsicElementalFunctions::SymbolicIsPositive), "SymbolicIsPositive"}, + {static_cast(IntrinsicElementalFunctions::Int), + "int"}, }; @@ -775,9 +962,21 @@ namespace IntrinsicElementalFunctionRegistry { {"log_gamma", {&LogGamma::create_LogGamma, &LogGamma::eval_LogGamma}}, {"erf", {&Erf::create_Erf, &Erf::eval_Erf}}, {"erfc", {&Erfc::create_Erfc, &Erfc::eval_Erfc}}, + {"erfc_scaled", {&ErfcScaled::create_ErfcScaled, &ErfcScaled::eval_ErfcScaled}}, {"trunc", {&Trunc::create_Trunc, &Trunc::eval_Trunc}}, {"fix", {&Fix::create_Fix, &Fix::eval_Fix}}, {"sin", {&Sin::create_Sin, &Sin::eval_Sin}}, + {"bessel_j0", {&BesselJ0::create_BesselJ0, &BesselJ0::eval_BesselJ0}}, + {"bessel_j1", {&BesselJ1::create_BesselJ1, &BesselJ1::eval_BesselJ1}}, + {"bessel_y0", {&BesselY0::create_BesselY0, &BesselY0::eval_BesselY0}}, + {"bessel_y1", {&BesselY1::create_BesselY1, &BesselY1::eval_BesselY1}}, + {"same_type_as", {&SameTypeAs::create_SameTypeAs, &SameTypeAs::eval_SameTypeAs}}, + {"asind", {&Asind::create_Asind, &Asind::eval_Asind}}, + {"acosd", {&Acosd::create_Acosd, &Acosd::eval_Acosd}}, + {"atand", {&Atand::create_Atand, &Atand::eval_Atand}}, + {"sind", {&Sind::create_Sind, &Sind::eval_Sind}}, + {"cosd", {&Cosd::create_Cosd, &Cosd::eval_Cosd}}, + {"tand", {&Tand::create_Tand, &Tand::eval_Tand}}, {"cos", {&Cos::create_Cos, &Cos::eval_Cos}}, {"tan", {&Tan::create_Tan, &Tan::eval_Tan}}, {"asin", {&Asin::create_Asin, &Asin::eval_Asin}}, @@ -792,6 +991,7 @@ namespace IntrinsicElementalFunctionRegistry { {"atanh", {&Atanh::create_Atanh, &Atanh::eval_Atanh}}, {"abs", {&Abs::create_Abs, &Abs::eval_Abs}}, {"aimag", {&Aimag::create_Aimag, &Aimag::eval_Aimag}}, + {"dreal", {&Dreal::create_Dreal, &Dreal::eval_Dreal}}, {"exp", {&Exp::create_Exp, &Exp::eval_Exp}}, {"exp2", {&Exp2::create_Exp2, &Exp2::eval_Exp2}}, {"expm1", {&Expm1::create_Expm1, &Expm1::eval_Expm1}}, @@ -799,16 +999,26 @@ namespace IntrinsicElementalFunctionRegistry { {"floordiv", {&FloorDiv::create_FloorDiv, &FloorDiv::eval_FloorDiv}}, {"mod", {&Mod::create_Mod, &Mod::eval_Mod}}, {"trailz", {&Trailz::create_Trailz, &Trailz::eval_Trailz}}, + {"isnan", {&Isnan::create_Isnan, &Isnan::eval_Isnan}}, + {"nearest", {&Nearest::create_Nearest, &Nearest::eval_Nearest}}, + {"compiler_version", {&CompilerVersion::create_CompilerVersion, &CompilerVersion::eval_CompilerVersion}}, + {"compiler_options", {&CompilerOptions::create_CompilerOptions, &CompilerOptions::eval_CompilerOptions}}, + {"command_argument_count", {&CommandArgumentCount::create_CommandArgumentCount, nullptr}}, + {"spacing", {&Spacing::create_Spacing, &Spacing::eval_Spacing}}, {"modulo", {&Modulo::create_Modulo, &Modulo::eval_Modulo}}, - {"bessel_j0", {&BesselJ0::create_BesselJ0, &BesselJ0::eval_BesselJ0}}, - {"bessel_j1", {&BesselJ1::create_BesselJ1, &BesselJ1::eval_BesselJ1}}, - {"bessel_y0", {&BesselY0::create_BesselY0, &BesselY0::eval_BesselY0}}, + {"bessel_jn", {&BesselJN::create_BesselJN, &BesselJN::eval_BesselJN}}, + {"bessel_yn", {&BesselYN::create_BesselYN, &BesselYN::eval_BesselYN}}, + {"merge", {&Merge::create_Merge, &Merge::eval_Merge}}, {"mvbits", {&Mvbits::create_Mvbits, &Mvbits::eval_Mvbits}}, + {"move_alloc", {&MoveAlloc::create_MoveAlloc, &MoveAlloc::eval_MoveAlloc}}, + {"merge_bits", {&Mergebits::create_Mergebits, &Mergebits::eval_Mergebits}}, {"shiftr", {&Shiftr::create_Shiftr, &Shiftr::eval_Shiftr}}, {"rshift", {&Rshift::create_Rshift, &Rshift::eval_Rshift}}, {"shiftl", {&Shiftl::create_Shiftl, &Shiftl::eval_Shiftl}}, {"lshift", {&Shiftl::create_Shiftl, &Shiftl::eval_Shiftl}}, {"dshiftl", {&Dshiftl::create_Dshiftl, &Dshiftl::eval_Dshiftl}}, + {"dshiftr", {&Dshiftr::create_Dshiftr, &Dshiftr::eval_Dshiftr}}, + {"logical", {&Logical::create_Logical, &Logical::eval_Logical}}, {"ishft", {&Ishft::create_Ishft, &Ishft::eval_Ishft}}, {"bgt", {&Bgt::create_Bgt, &Bgt::eval_Bgt}}, {"blt", {&Blt::create_Blt, &Blt::eval_Blt}}, @@ -823,8 +1033,11 @@ namespace IntrinsicElementalFunctionRegistry { {"set_exponent", {&SetExponent::create_SetExponent, &SetExponent::eval_SetExponent}}, {"not", {&Not::create_Not, &Not::eval_Not}}, {"iand", {&Iand::create_Iand, &Iand::eval_Iand}}, + {"and", {&And::create_And, &And::eval_And}}, {"ior", {&Ior::create_Ior, &Ior::eval_Ior}}, + {"or", {&Or::create_Or, &Or::eval_Or}}, {"ieor", {&Ieor::create_Ieor, &Ieor::eval_Ieor}}, + {"xor", {&Xor::create_Xor, &Xor::eval_Xor}}, {"ibclr", {&Ibclr::create_Ibclr, &Ibclr::eval_Ibclr}}, {"ibset", {&Ibset::create_Ibset, &Ibset::eval_Ibset}}, {"btest", {&Btest::create_Btest, &Btest::eval_Btest}}, @@ -833,6 +1046,7 @@ namespace IntrinsicElementalFunctionRegistry { {"_lfortran_tolowercase", {&ToLowerCase::create_ToLowerCase, &ToLowerCase::eval_ToLowerCase}}, {"hypot", {&Hypot::create_Hypot, &Hypot::eval_Hypot}}, {"selected_int_kind", {&SelectedIntKind::create_SelectedIntKind, &SelectedIntKind::eval_SelectedIntKind}}, + {"present", {&Present::create_Present, &Present::eval_Present}}, {"selected_real_kind", {&SelectedRealKind::create_SelectedRealKind, &SelectedRealKind::eval_SelectedRealKind}}, {"selected_char_kind", {&SelectedCharKind::create_SelectedCharKind, &SelectedCharKind::eval_SelectedCharKind}}, {"kind", {&Kind::create_Kind, &Kind::eval_Kind}}, @@ -857,13 +1071,18 @@ namespace IntrinsicElementalFunctionRegistry { {"max0", {&Max::create_Max, &Max::eval_Max}}, {"adjustl", {&Adjustl::create_Adjustl, &Adjustl::eval_Adjustl}}, {"adjustr", {&Adjustr::create_Adjustr, &Adjustr::eval_Adjustr}}, + {"len_trim", {&StringLenTrim::create_StringLenTrim, &StringLenTrim::eval_StringLenTrim}}, + {"trim", {&StringTrim::create_StringTrim, &StringTrim::eval_StringTrim}}, {"ichar", {&Ichar::create_Ichar, &Ichar::eval_Ichar}}, {"char", {&Char::create_Char, &Char::eval_Char}}, + {"achar", {&Achar::create_Achar, &Achar::eval_Achar}}, {"min0", {&Min::create_Min, &Min::eval_Min}}, {"max", {&Max::create_Max, &Max::eval_Max}}, {"min", {&Min::create_Min, &Min::eval_Min}}, {"ishftc", {&Ishftc::create_Ishftc, &Ishftc::eval_Ishftc}}, {"radix", {&Radix::create_Radix, &Radix::eval_Radix}}, + {"out_of_range", {&OutOfRange::create_OutOfRange, &OutOfRange::eval_OutOfRange}}, + {"storage_size", {&StorageSize::create_StorageSize, &StorageSize::eval_StorageSize}}, {"scale", {&Scale::create_Scale, &Scale::eval_Scale}}, {"dprod", {&Dprod::create_Dprod, &Dprod::eval_Dprod}}, {"range", {&Range::create_Range, &Range::eval_Range}}, @@ -871,7 +1090,9 @@ namespace IntrinsicElementalFunctionRegistry { {"aint", {&Aint::create_Aint, &Aint::eval_Aint}}, {"popcnt", {&Popcnt::create_Popcnt, &Popcnt::eval_Popcnt}}, {"poppar", {&Poppar::create_Poppar, &Poppar::eval_Poppar}}, + {"real", {&Real::create_Real, &Real::eval_Real}}, {"nint", {&Nint::create_Nint, &Nint::eval_Nint}}, + {"idnint", {&Idnint::create_Idnint, &Idnint::eval_Idnint}}, {"anint", {&Anint::create_Anint, &Anint::eval_Anint}}, {"dim", {&Dim::create_Dim, &Dim::eval_Dim}}, {"floor", {&Floor::create_Floor, &Floor::eval_Floor}}, @@ -885,6 +1106,8 @@ namespace IntrinsicElementalFunctionRegistry { {"epsilon", {&Epsilon::create_Epsilon, &Epsilon::eval_Epsilon}}, {"precision", {&Precision::create_Precision, &Precision::eval_Precision}}, {"tiny", {&Tiny::create_Tiny, &Tiny::eval_Tiny}}, + {"bit_size", {&BitSize::create_BitSize, &BitSize::eval_BitSize}}, + {"new_line", {&NewLine::create_NewLine, &NewLine::eval_NewLine}}, {"conjg", {&Conjg::create_Conjg, &Conjg::eval_Conjg}}, {"huge", {&Huge::create_Huge, &Huge::eval_Huge}}, {"Symbol", {&SymbolicSymbol::create_SymbolicSymbol, &SymbolicSymbol::eval_SymbolicSymbol}}, @@ -915,6 +1138,7 @@ namespace IntrinsicElementalFunctionRegistry { {"GetArgument", {&SymbolicGetArgument::create_SymbolicGetArgument, &SymbolicGetArgument::eval_SymbolicGetArgument}}, {"is_integer", {&SymbolicIsInteger::create_SymbolicIsInteger, &SymbolicIsInteger::eval_SymbolicIsInteger}}, {"is_positive", {&SymbolicIsPositive::create_SymbolicIsPositive, &SymbolicIsPositive::eval_SymbolicIsPositive}}, + {"int", {&Int::create_Int, &Int::eval_Int}}, }; static inline bool is_intrinsic_function(const std::string& name) { @@ -926,7 +1150,7 @@ namespace IntrinsicElementalFunctionRegistry { } static inline create_intrinsic_function get_create_function(const std::string& name) { - return std::get<0>(intrinsic_function_by_name_db.at(name)); + return std::get<0>(intrinsic_function_by_name_db.at(name)); } static inline verify_function get_verify_function(int64_t id) { @@ -1031,7 +1255,7 @@ namespace IntrinsicImpureFunctionRegistry { return #X; \ } -inline std::string get_impure_intrinsic_name(int x) { +inline std::string get_impure_intrinsic_name(int64_t x) { switch (x) { IMPURE_INTRINSIC_NAME_CASE(IsIostatEnd) IMPURE_INTRINSIC_NAME_CASE(IsIostatEor) diff --git a/src/libasr/pass/intrinsic_functions.h b/src/libasr/pass/intrinsic_functions.h index 4fdb328153..feb48040e7 100644 --- a/src/libasr/pass/intrinsic_functions.h +++ b/src/libasr/pass/intrinsic_functions.h @@ -3,6 +3,7 @@ #include #include +#include namespace LCompilers::ASRUtils { @@ -20,6 +21,7 @@ the code size. enum class IntrinsicElementalFunctions : int64_t { ObjectType, Kind, // if kind is reordered, update `extract_kind` in `asr_utils.h` + Mod, // if mod is reordered, update `pass/openmp.cpp` Rank, Sin, Cos, @@ -32,10 +34,17 @@ enum class IntrinsicElementalFunctions : int64_t { Tanh, Atan2, Asinh, + Sind, + Cosd, + Tand, + Asind, + Acosd, + Atand, Acosh, Atanh, Erf, Erfc, + ErfcScaled, Gamma, Log, Log10, @@ -44,23 +53,35 @@ enum class IntrinsicElementalFunctions : int64_t { Fix, Abs, Aimag, + Dreal, Exp, Exp2, Expm1, FMA, FlipSign, - Mod, Trailz, + Isnan, + Nearest, + Spacing, Modulo, BesselJ0, BesselJ1, + BesselJN, BesselY0, + BesselY1, + BesselYN, + SameTypeAs, + Merge, Mvbits, + MoveAlloc, + Mergebits, Shiftr, Rshift, Shiftl, Dshiftl, + Dshiftr, Ishft, + OutOfRange, Bgt, Blt, Bge, @@ -94,8 +115,11 @@ enum class IntrinsicElementalFunctions : int64_t { SelectedCharKind, Adjustl, Adjustr, + StringLenTrim, + StringTrim, Ichar, Char, + Achar, MinExponent, MaxExponent, FloorDiv, @@ -112,12 +136,19 @@ enum class IntrinsicElementalFunctions : int64_t { Max, Min, Radix, + IsContiguous, + StorageSize, Scale, Dprod, Range, Sign, + CompilerVersion, + CompilerOptions, + CommandArgumentCount, SignFromValue, + Logical, Nint, + Idnint, Aint, Anint, Dim, @@ -133,10 +164,13 @@ enum class IntrinsicElementalFunctions : int64_t { Epsilon, Precision, Tiny, + BitSize, + NewLine, Conjg, Huge, Popcnt, Poppar, + Real, SymbolicSymbol, SymbolicAdd, SymbolicSub, @@ -163,6 +197,11 @@ enum class IntrinsicElementalFunctions : int64_t { SymbolicLogQ, SymbolicSinQ, SymbolicGetArgument, + Int, + Present, + And, + Or, + Xor, SymbolicIsInteger, SymbolicIsPositive, // ... @@ -290,61 +329,61 @@ static inline ASR::symbol_t *create_KMP_function(Allocator &al, body.push_back(al, b.Assignment(s_len, b.StringLen(args[0]))); body.push_back(al, b.Assignment(pat_len, b.StringLen(args[1]))); - body.push_back(al, b.Assignment(result, b.i32_n(-1))); - body.push_back(al, b.If(b.iEq(pat_len, b.i32(0)), { - b.Assignment(result, b.i32(0)), Return() + body.push_back(al, b.Assignment(result, b.i_neg(b.i32(-1), int32))); + body.push_back(al, b.If(b.Eq(pat_len, b.i32(0)), { + b.Assignment(result, b.i32(0)), b.Return() }, { - b.If(b.iEq(s_len, b.i32(0)), { Return() }, {}) + b.If(b.Eq(s_len, b.i32(0)), { b.Return() }, {}) })); body.push_back(al, b.Assignment(lps, EXPR(ASR::make_ListConstant_t(al, loc, nullptr, 0, List(int32))))); body.push_back(al, b.Assignment(i, b.i32(0))); - body.push_back(al, b.While(b.iLtE(i, b.iSub(pat_len, b.i32(1))), { - b.Assignment(i, b.iAdd(i, b.i32(1))), + body.push_back(al, b.While(b.LtE(i, b.Sub(pat_len, b.i32(1))), { + b.Assignment(i, b.Add(i, b.i32(1))), b.ListAppend(lps, b.i32(0)) })); - body.push_back(al, b.Assignment(flag, b.bool32(false))); + body.push_back(al, b.Assignment(flag, b.bool_t(0, logical))); body.push_back(al, b.Assignment(i, b.i32(1))); body.push_back(al, b.Assignment(pi_len, b.i32(0))); - body.push_back(al, b.While(b.iLt(i, pat_len), { - b.If(b.sEq(b.StringItem(args[1], b.iAdd(i, b.i32(1))), - b.StringItem(args[1], b.iAdd(pi_len, b.i32(1)))), { - b.Assignment(pi_len, b.iAdd(pi_len, b.i32(1))), + body.push_back(al, b.While(b.Lt(i, pat_len), { + b.If(b.Eq(b.StringItem(args[1], b.Add(i, b.i32(1))), + b.StringItem(args[1], b.Add(pi_len, b.i32(1)))), { + b.Assignment(pi_len, b.Add(pi_len, b.i32(1))), b.Assignment(b.ListItem(lps, i, int32), pi_len), - b.Assignment(i, b.iAdd(i, b.i32(1))) + b.Assignment(i, b.Add(i, b.i32(1))) }, { - b.If(b.iNotEq(pi_len, b.i32(0)), { - b.Assignment(pi_len, b.ListItem(lps, b.iSub(pi_len, b.i32(1)), int32)) + b.If(b.NotEq(pi_len, b.i32(0)), { + b.Assignment(pi_len, b.ListItem(lps, b.Sub(pi_len, b.i32(1)), int32)) }, { - b.Assignment(i, b.iAdd(i, b.i32(1))) + b.Assignment(i, b.Add(i, b.i32(1))) }) }) })); body.push_back(al, b.Assignment(j, b.i32(0))); body.push_back(al, b.Assignment(i, b.i32(0))); - body.push_back(al, b.While(b.And(b.iGtE(b.iSub(s_len, i), - b.iSub(pat_len, j)), b.Not(flag)), { - b.If(b.sEq(b.StringItem(args[1], b.iAdd(j, b.i32(1))), - b.StringItem(args[0], b.iAdd(i, b.i32(1)))), { - b.Assignment(i, b.iAdd(i, b.i32(1))), - b.Assignment(j, b.iAdd(j, b.i32(1))) + body.push_back(al, b.While(b.And(b.GtE(b.Sub(s_len, i), + b.Sub(pat_len, j)), b.Not(flag)), { + b.If(b.Eq(b.StringItem(args[1], b.Add(j, b.i32(1))), + b.StringItem(args[0], b.Add(i, b.i32(1)))), { + b.Assignment(i, b.Add(i, b.i32(1))), + b.Assignment(j, b.Add(j, b.i32(1))) }, {}), - b.If(b.iEq(j, pat_len), { - b.Assignment(result, b.iSub(i, j)), - b.Assignment(flag, b.bool32(true)), - b.Assignment(j, b.ListItem(lps, b.iSub(j, b.i32(1)), int32)) + b.If(b.Eq(j, pat_len), { + b.Assignment(result, b.Sub(i, j)), + b.Assignment(flag, b.bool_t(1, logical)), + b.Assignment(j, b.ListItem(lps, b.Sub(j, b.i32(1)), int32)) }, { - b.If(b.And(b.iLt(i, s_len), b.sNotEq(b.StringItem(args[1], b.iAdd(j, b.i32(1))), - b.StringItem(args[0], b.iAdd(i, b.i32(1))))), { - b.If(b.iNotEq(j, b.i32(0)), { - b.Assignment(j, b.ListItem(lps, b.iSub(j, b.i32(1)), int32)) + b.If(b.And(b.Lt(i, s_len), b.NotEq(b.StringItem(args[1], b.Add(j, b.i32(1))), + b.StringItem(args[0], b.Add(i, b.i32(1))))), { + b.If(b.NotEq(j, b.i32(0)), { + b.Assignment(j, b.ListItem(lps, b.Sub(j, b.i32(1)), int32)) }, { - b.Assignment(i, b.iAdd(i, b.i32(1))) + b.Assignment(i, b.Add(i, b.i32(1))) }) }, {}) }) })); - body.push_back(al, Return()); + body.push_back(al, b.Return()); ASR::symbol_t *fn_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); scope->add_symbol(fn_name, fn_sym); @@ -361,120 +400,15 @@ static inline void verify_args(const ASR::IntrinsicElementalFunction_t& x, ASR::ttype_t* input_type = ASRUtils::expr_type(x.m_args[0]); ASR::ttype_t* output_type = x.m_type; ASRUtils::require_impl(ASRUtils::check_equal_type(input_type, output_type, true), - "The input and output type of elemental intrinsics must exactly match, input type: " + + "The input and output type of elemental intrinsic, " + + std::to_string(static_cast(x.m_intrinsic_id)) + + " must exactly match, input type: " + ASRUtils::get_type_code(input_type) + " output type: " + ASRUtils::get_type_code(output_type), loc, diagnostics); } } // namespace UnaryIntrinsicFunction -namespace BinaryIntrinsicFunction { - -static inline ASR::expr_t* instantiate_functions(Allocator &al, - const Location &loc, SymbolTable *scope, std::string new_name, - ASR::ttype_t *arg_type, ASR::ttype_t *return_type, - Vec& new_args, int64_t /*overload_id*/) { - std::string c_func_name; - switch (arg_type->type) { - case ASR::ttypeType::Complex : { - if (ASRUtils::extract_kind_from_ttype_t(arg_type) == 4) { - c_func_name = "_lfortran_c" + new_name; - } else { - c_func_name = "_lfortran_z" + new_name; - } - break; - } - default : { - if (ASRUtils::extract_kind_from_ttype_t(arg_type) == 4) { - c_func_name = "_lfortran_s" + new_name; - } else { - c_func_name = "_lfortran_d" + new_name; - } - } - } - new_name = "_lcompilers_" + new_name + "_" + type_to_str_python(arg_type); - - declare_basic_variables(new_name); - if (scope->get_symbol(new_name)) { - ASR::symbol_t *s = scope->get_symbol(new_name); - ASR::Function_t *f = ASR::down_cast(s); - return b.Call(s, new_args, expr_type(f->m_return_var)); - } - fill_func_arg("x", arg_type); - fill_func_arg("y", arg_type) - auto result = declare(new_name, return_type, ReturnVar); - - { - SymbolTable *fn_symtab_1 = al.make_new(fn_symtab); - Vec args_1; - { - args_1.reserve(al, 2); - ASR::expr_t *arg_1 = b.Variable(fn_symtab_1, "x", arg_type, - ASR::intentType::In, ASR::abiType::BindC, true); - ASR::expr_t *arg_2 = b.Variable(fn_symtab_1, "y", arg_type, - ASR::intentType::In, ASR::abiType::BindC, true); - args_1.push_back(al, arg_1); - args_1.push_back(al, arg_2); - } - - ASR::expr_t *return_var_1 = b.Variable(fn_symtab_1, c_func_name, - arg_type, ASRUtils::intent_return_var, ASR::abiType::BindC, false); - - SetChar dep_1; dep_1.reserve(al, 1); - Vec body_1; body_1.reserve(al, 1); - ASR::symbol_t *s = make_ASR_Function_t(c_func_name, fn_symtab_1, dep_1, args_1, - body_1, return_var_1, ASR::abiType::BindC, ASR::deftypeType::Interface, s2c(al, c_func_name)); - fn_symtab->add_symbol(c_func_name, s); - dep.push_back(al, s2c(al, c_func_name)); - body.push_back(al, b.Assignment(result, b.Call(s, args, arg_type))); - } - - ASR::symbol_t *new_symbol = make_ASR_Function_t(fn_name, fn_symtab, dep, args, - body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); - scope->add_symbol(fn_name, new_symbol); - return b.Call(new_symbol, new_args, return_type); -} - -static inline ASR::asr_t* create_BinaryFunction(Allocator& al, const Location& loc, - Vec& args, eval_intrinsic_function eval_function, - int64_t intrinsic_id, int64_t overload_id, ASR::ttype_t* type, diag::Diagnostics& diag) { - ASR::expr_t *value = nullptr; - ASR::expr_t *arg_value_1 = ASRUtils::expr_value(args[0]); - ASR::expr_t *arg_value_2 = ASRUtils::expr_value(args[1]); - if (arg_value_1 && arg_value_2) { - Vec arg_values; - arg_values.reserve(al, 2); - arg_values.push_back(al, arg_value_1); - arg_values.push_back(al, arg_value_2); - value = eval_function(al, loc, type, arg_values, diag); - } - - return ASRUtils::make_IntrinsicElementalFunction_t_util(al, loc, intrinsic_id, - args.p, args.n, overload_id, type, value); -} - -static inline void verify_args(const ASR::IntrinsicElementalFunction_t& x, - diag::Diagnostics& diagnostics) { - const Location& loc = x.base.base.loc; - ASRUtils::require_impl(x.n_args == 2, - "Binary intrinsics must have only 2 input arguments", - loc, diagnostics); - - ASR::ttype_t* input_type = ASRUtils::expr_type(x.m_args[0]); - ASR::ttype_t* input_type_2 = ASRUtils::expr_type(x.m_args[1]); - ASR::ttype_t* output_type = x.m_type; - ASRUtils::require_impl(ASRUtils::check_equal_type(input_type, input_type_2, true), - "The types of both the arguments of binary intrinsics must exactly match, argument 1 type: " + - ASRUtils::get_type_code(input_type) + " argument 2 type: " + ASRUtils::get_type_code(input_type_2), - loc, diagnostics); - ASRUtils::require_impl(ASRUtils::check_equal_type(input_type, output_type, true), - "The input and output type of elemental intrinsics must exactly match, input type: " + - ASRUtils::get_type_code(input_type) + " output type: " + ASRUtils::get_type_code(output_type), - loc, diagnostics); -} - -} // namespace BinaryIntrinsicFunction - // `X` is the name of the function in the IntrinsicElementalFunctions enum and // we use the same name for `create_X` and other places // `eval_X` is the name of the function in the `std` namespace for compile @@ -487,24 +421,7 @@ namespace X { diag::Diagnostics& /*diag*/) { \ double rv = ASR::down_cast(args[0])->m_r; \ ASRUtils::ASRBuilder b(al, loc); \ - return b.f(std::eval_X(rv), t); \ - } \ - static inline ASR::asr_t* create_##X(Allocator &al, const Location &loc, \ - Vec &args, \ - diag::Diagnostics& diag) { \ - ASR::ttype_t *type = ASRUtils::expr_type(args[0]); \ - if (args.n != 1) { \ - append_error(diag, "Intrinsic `"#X"` accepts exactly one argument", \ - loc); \ - return nullptr; \ - } else if (!ASRUtils::is_real(*type)) { \ - append_error(diag, "`x` argument of `"#X"` must be real", \ - args[0]->base.loc); \ - return nullptr; \ - } \ - return UnaryIntrinsicFunction::create_UnaryFunction(al, loc, args, \ - eval_##X, static_cast(IntrinsicElementalFunctions::X), \ - 0, type, diag); \ + return b.f_t(std::eval_X(rv), t); \ } \ static inline ASR::expr_t* instantiate_##X (Allocator &al, \ const Location &loc, SymbolTable *scope, \ @@ -522,11 +439,28 @@ create_unary_function(Log10, log10, log10) create_unary_function(Erf, erf, erf) create_unary_function(Erfc, erfc, erfc) +namespace Isnan{ + static inline ASR::expr_t *eval_Isnan(Allocator &al, const Location &loc, + ASR::ttype_t *t, Vec &args, + diag::Diagnostics& /*diag*/) { + double rv = ASR::down_cast(args[0])->m_r; + ASRUtils::ASRBuilder b(al, loc); + return b.bool_t(std::isnan(rv), t); + } + static inline ASR::expr_t* instantiate_Isnan(Allocator &al, + const Location &loc, SymbolTable *scope, + Vec &arg_types, ASR::ttype_t *return_type, + Vec &new_args, int64_t overload_id) { + return UnaryIntrinsicFunction::instantiate_functions(al, loc, scope, + "is_nan", arg_types[0], return_type, new_args, overload_id); + } +} + namespace ObjectType { static inline void verify_args(const ASR::IntrinsicElementalFunction_t& x, diag::Diagnostics& diagnostics) { ASRUtils::require_impl(x.n_args == 1, - "ASR Verify: type() takes only 1 argument `object`", + "type() takes only 1 argument `object`", x.base.base.loc, diagnostics); } @@ -539,16 +473,12 @@ namespace ObjectType { object_type += "int"; break; } case ASR::ttypeType::Real : { object_type += "float"; break; - } case ASR::ttypeType::Character : { + } case ASR::ttypeType::String : { object_type += "str"; break; } case ASR::ttypeType::List : { object_type += "list"; break; } case ASR::ttypeType::Dict : { object_type += "dict"; break; - } case ASR::ttypeType::Set : { - object_type += "set"; break; - } case ASR::ttypeType::Tuple : { - object_type += "tuple"; break; } default: { LCOMPILERS_ASSERT_MSG(false, "Unsupported type"); break; @@ -591,23 +521,6 @@ namespace Fix { return make_ConstantWithType(make_RealConstant_t, val, t, loc); } - static inline ASR::asr_t* create_Fix(Allocator& al, const Location& loc, - Vec& args, - diag::Diagnostics& diag) { - ASR::ttype_t *type = ASRUtils::expr_type(args[0]); - if (args.n != 1) { - append_error(diag, "Intrinsic `fix` accepts exactly one argument", loc); - return nullptr; - } else if (!ASRUtils::is_real(*type)) { - append_error(diag, "`fix` argument of `fix` must be real", - args[0]->base.loc); - return nullptr; - } - return UnaryIntrinsicFunction::create_UnaryFunction(al, loc, args, - eval_Fix, static_cast(IntrinsicElementalFunctions::Fix), - 0, type, diag); - } - static inline ASR::expr_t* instantiate_Fix (Allocator &al, const Location &loc, SymbolTable *scope, Vec& arg_types, ASR::ttype_t *return_type, Vec& new_args, @@ -644,24 +557,6 @@ namespace X { } \ return nullptr; \ } \ - static inline ASR::asr_t* create_##X(Allocator& al, const Location& loc, \ - Vec& args, \ - diag::Diagnostics& diag) \ - { \ - ASR::ttype_t *type = ASRUtils::expr_type(args[0]); \ - if (args.n != 1) { \ - append_error(diag, "Intrinsic `"#X"` accepts exactly one argument", \ - loc); \ - return nullptr; \ - } else if (!ASRUtils::is_real(*type) && !ASRUtils::is_complex(*type)) { \ - append_error(diag, "`x` argument of `"#X"` must be real or complex",\ - args[0]->base.loc); \ - return nullptr; \ - } \ - return UnaryIntrinsicFunction::create_UnaryFunction(al, loc, args, \ - eval_##X, static_cast(IntrinsicElementalFunctions::X), \ - 0, type, diag); \ - } \ static inline ASR::expr_t* instantiate_##X (Allocator &al, \ const Location &loc, SymbolTable *scope, \ Vec& arg_types, ASR::ttype_t *return_type, \ @@ -686,6 +581,84 @@ create_trig(Acosh, acosh, acosh) create_trig(Atanh, atanh, atanh) create_trig(Log, log, log) +namespace MathIntrinsicFunction{ + static inline ASR::expr_t* instantiate_functions(Allocator &al, const Location &loc, + SymbolTable *scope, std::string lcompiler_name, Vec& arg_types, ASR::ttype_t *return_type, + Vec& new_args, int64_t /*overload_id*/) { + std::string c_func_name; + if (ASRUtils::extract_kind_from_ttype_t(arg_types[0]) == 4) { + c_func_name = "_lfortran_s" + lcompiler_name; + } else { + c_func_name = "_lfortran_d" + lcompiler_name; + } + std::string new_name = "_lcompilers_" + lcompiler_name + "_"+ type_to_str_python(arg_types[0]); + + declare_basic_variables(new_name); + if (scope->get_symbol(new_name)) { + ASR::symbol_t *s = scope->get_symbol(new_name); + ASR::Function_t *f = ASR::down_cast(s); + return b.Call(s, new_args, expr_type(f->m_return_var)); + } + fill_func_arg("x", arg_types[0]); + auto result = declare(new_name, return_type, ReturnVar); + { + ASR::symbol_t *s = b.create_c_func(c_func_name, fn_symtab, return_type, arg_types.size(), arg_types); + fn_symtab->add_symbol(c_func_name, s); + dep.push_back(al, s2c(al, c_func_name)); + body.push_back(al, b.Assignment(result, b.Call(s, args, return_type))); + } + + ASR::symbol_t *new_symbol = make_ASR_Function_t(fn_name, fn_symtab, dep, args, + body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); + scope->add_symbol(fn_name, new_symbol); + return b.Call(new_symbol, new_args, return_type); + } +} + +#define create_math_bindc(math_func, stdeval, degree, lcompilers_name) \ +namespace math_func { \ + static inline ASR::expr_t *eval_##math_func(Allocator &al, const Location &loc, \ + ASR::ttype_t *t, Vec& args, \ + diag::Diagnostics& /*diag*/) { \ + LCOMPILERS_ASSERT(args.size() == 1); \ + double rv = ASR::down_cast(args[0])->m_r; \ + double result = stdeval(rv); \ + if ( degree == 1 ) { \ + double PI = 3.14159265358979323846; \ + result = result * 180.0/PI; \ + } else if ( degree == 2 ) { \ + double PI = 3.14159265358979323846; \ + result = stdeval( ( rv * PI ) / 180.0 ); \ + } \ + return make_ConstantWithType(make_RealConstant_t, result, t, loc); \ + } \ + static inline ASR::expr_t* instantiate_##math_func (Allocator &al, \ + const Location &loc, SymbolTable *scope, \ + Vec& arg_types, ASR::ttype_t *return_type, \ + Vec& new_args,int64_t overload_id) { \ + return MathIntrinsicFunction::instantiate_functions(al, loc, scope, \ + #lcompilers_name, arg_types, return_type, new_args, overload_id); \ + } \ +} // namespace math_func + +/* + Degree acts as a switch + - if degree = 1, math function output is in degrees + - if degree = 2, math function input is in degrees + - degree = 0, implies no change in input or output ( radians ) +*/ + +create_math_bindc(BesselJ0, j0, 0, bessel_j0) +create_math_bindc(BesselJ1, j1, 0, bessel_j1) +create_math_bindc(BesselY0, y0, 0, bessel_y0) +create_math_bindc(BesselY1, y1, 0, bessel_y1) +create_math_bindc(Asind, asin, 1, asind) +create_math_bindc(Acosd, acos, 1, acosd) +create_math_bindc(Atand, atan, 1, atand) +create_math_bindc(Sind, sin, 2, sind) +create_math_bindc(Cosd, cos, 2, cosd) +create_math_bindc(Tand, tan, 2, tand) + namespace Aimag { static inline ASR::expr_t *eval_Aimag(Allocator &al, const Location &loc, @@ -693,18 +666,26 @@ namespace Aimag { ASRUtils::ASRBuilder b(al, loc); std::complex crv; if( ASRUtils::extract_value(args[0], crv) ) { - return b.f(crv.imag(), t); + ASR::ComplexConstant_t *c = ASR::down_cast(ASRUtils::expr_value(args[0])); + return make_ConstantWithType(make_RealConstant_t, c->m_im, t, loc); } else { return nullptr; } } - static inline ASR::expr_t* instantiate_Aimag (Allocator &al, - const Location &loc, SymbolTable* /*scope*/, - Vec& /*arg_types*/, ASR::ttype_t *return_type, + static inline ASR::expr_t* instantiate_Aimag(Allocator &al, + const Location &loc, SymbolTable* scope, + Vec& arg_types, ASR::ttype_t *return_type, Vec &new_args,int64_t /*overload_id*/) { - return EXPR(ASR::make_ComplexIm_t(al, loc, new_args[0].m_value, - return_type, nullptr)); + declare_basic_variables("_lcompilers_aimag_" + type_to_str_python(arg_types[0])); + fill_func_arg("x", arg_types[0]); + auto result = declare(fn_name, return_type, ReturnVar); + body.push_back(al, b.Assignment(result, EXPR(ASR::make_ComplexIm_t(al, loc, + args[0], return_type, nullptr)))); + ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, + body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); + scope->add_symbol(fn_name, f_sym); + return b.Call(f_sym, new_args, return_type, nullptr); } } // namespace Aimag @@ -720,30 +701,52 @@ namespace Atan2 { } return nullptr; } - static inline ASR::asr_t* create_Atan2(Allocator& al, const Location& loc, - Vec& args, - diag::Diagnostics& diag) - { - ASR::ttype_t *type_1 = ASRUtils::expr_type(args[0]); - ASR::ttype_t *type_2 = ASRUtils::expr_type(args[1]); - if (!ASRUtils::is_real(*type_1)) { - append_error(diag, "`x` argument of \"atan2\" must be real",args[0]->base.loc); - return nullptr; - } else if (!ASRUtils::is_real(*type_2)) { - append_error(diag, "`y` argument of \"atan2\" must be real",args[1]->base.loc); - return nullptr; - } - return BinaryIntrinsicFunction::create_BinaryFunction(al, loc, args, - eval_Atan2, static_cast(IntrinsicElementalFunctions::Atan2), - 0, type_1, diag); - } static inline ASR::expr_t* instantiate_Atan2 (Allocator &al, const Location &loc, SymbolTable *scope, Vec& arg_types, ASR::ttype_t *return_type, - Vec& new_args,int64_t overload_id) { + Vec& new_args,int64_t /*overload_id*/) { ASR::ttype_t* arg_type = arg_types[0]; - return BinaryIntrinsicFunction::instantiate_functions(al, loc, scope, - "atan2", arg_type, return_type, new_args, overload_id); + std::string c_func_name; + std::string new_name = "atan2"; + switch (arg_type->type) { + case ASR::ttypeType::Complex : { + if (ASRUtils::extract_kind_from_ttype_t(arg_type) == 4) { + c_func_name = "_lfortran_c" + new_name; + } else { + c_func_name = "_lfortran_z" + new_name; + } + break; + } + default : { + if (ASRUtils::extract_kind_from_ttype_t(arg_type) == 4) { + c_func_name = "_lfortran_s" + new_name; + } else { + c_func_name = "_lfortran_d" + new_name; + } + } + } + new_name = "_lcompilers_" + new_name + "_" + type_to_str_python(arg_type); + + declare_basic_variables(new_name); + if (scope->get_symbol(new_name)) { + ASR::symbol_t *s = scope->get_symbol(new_name); + ASR::Function_t *f = ASR::down_cast(s); + return b.Call(s, new_args, expr_type(f->m_return_var)); + } + fill_func_arg("x", arg_type); + fill_func_arg("y", arg_type); + auto result = declare(new_name, return_type, ReturnVar); + { + ASR::symbol_t *s = b.create_c_func(c_func_name, fn_symtab, return_type, arg_types.size(), arg_types); + fn_symtab->add_symbol(c_func_name, s); + dep.push_back(al, s2c(al, c_func_name)); + body.push_back(al, b.Assignment(result, b.Call(s, args, return_type))); + } + + ASR::symbol_t *new_symbol = make_ASR_Function_t(fn_name, fn_symtab, dep, args, + body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); + scope->add_symbol(fn_name, new_symbol); + return b.Call(new_symbol, new_args, return_type); } } @@ -759,8 +762,8 @@ namespace Abs { ASR::ttype_t* output_type = x.m_type; std::string input_type_str = ASRUtils::get_type_code(input_type); std::string output_type_str = ASRUtils::get_type_code(output_type); - if( ASR::is_a(*ASRUtils::type_get_past_pointer(ASRUtils::type_get_past_array(input_type))) ) { - ASRUtils::require_impl(ASR::is_a(*output_type), + if (ASRUtils::is_complex(*input_type)) { + ASRUtils::require_impl(ASRUtils::is_real(*output_type), "Abs intrinsic must return output of real for complex input, found: " + output_type_str, loc, diagnostics); int input_kind = ASRUtils::extract_kind_from_ttype_t(input_type); @@ -771,7 +774,7 @@ namespace Abs { loc, diagnostics); } else { ASRUtils::require_impl(ASRUtils::check_equal_type(input_type, output_type, true), - "The input and output type of elemental intrinsics must exactly match, input type: " + + "The input and output type of Abs intrinsic must exactly match, input type: " + input_type_str + " output type: " + output_type_str, loc, diagnostics); } } @@ -813,10 +816,20 @@ namespace Abs { args[0]->base.loc); return nullptr; } + // if the argument is "complex" (scalar or array or pointer ...) + // the return argument is of type "real", so we change "type" accordingly if (is_complex(*type)) { - type = TYPE(ASR::make_Real_t(al, type->base.loc, - ASRUtils::extract_kind_from_ttype_t(type))); + ASR::ttype_t* real_type = TYPE(ASR::make_Real_t(al, type->base.loc, + ASRUtils::extract_kind_from_ttype_t(type))); + if (ASR::is_a(*type)) { + ASR::Array_t* e = ASR::down_cast(type); + type = TYPE(ASR::make_Array_t(al, type->base.loc, real_type, + e->m_dims, e->n_dims, e->m_physical_type)); + } else { + type = real_type; + } } + // array_struct_temporary: TODO: Calculate type according to input arguments return UnaryIntrinsicFunction::create_UnaryFunction(al, loc, args, eval_Abs, static_cast(IntrinsicElementalFunctions::Abs), 0, ASRUtils::type_get_past_allocatable(type), diag); @@ -843,16 +856,16 @@ namespace Abs { */ if (is_integer(*arg_types[0]) || is_real(*arg_types[0])) { if (is_integer(*arg_types[0])) { - body.push_back(al, b.If(b.iGtE(args[0], b.i(0, arg_types[0])), { + body.push_back(al, b.If(b.GtE(args[0], b.i_t(0, arg_types[0])), { b.Assignment(result, args[0]) }, { - b.Assignment(result, b.i32_neg(args[0], arg_types[0])) + b.Assignment(result, b.i_neg(args[0], arg_types[0])) })); } else { - body.push_back(al, b.If(b.fGtE(args[0], b.f(0, arg_types[0])), { + body.push_back(al, b.If(b.GtE(args[0], b.f_t(0, arg_types[0])), { b.Assignment(result, args[0]) }, { - b.Assignment(result, b.f32_neg(args[0], arg_types[0])) + b.Assignment(result, b.f_neg(args[0], arg_types[0])) })); } } else { @@ -861,9 +874,9 @@ namespace Abs { ASRUtils::extract_kind_from_ttype_t(arg_types[0]))); ASR::down_cast(ASR::down_cast(result)->m_v)->m_type = return_type = real_type; body.push_back(al, b.Assignment(result, - b.ElementalPow(b.ElementalAdd(b.ElementalPow(EXPR(ASR::make_ComplexRe_t(al, loc, - args[0], real_type, nullptr)), b.f(2.0, real_type), loc), b.ElementalPow(EXPR(ASR::make_ComplexIm_t(al, loc, - args[0], real_type, nullptr)), b.f(2.0, real_type), loc), loc), b.f(0.5, real_type), loc))); + b.Pow(b.Add(b.Pow(EXPR(ASR::make_ComplexRe_t(al, loc, + args[0], real_type, nullptr)), b.f_t(2.0, real_type)), b.Pow(EXPR(ASR::make_ComplexIm_t(al, loc, + args[0], real_type, nullptr)), b.f_t(2.0, real_type))), b.f_t(0.5, real_type)))); } ASR::symbol_t *f_sym = make_ASR_Function_t(func_name, fn_symtab, dep, args, body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); @@ -883,30 +896,53 @@ namespace Radix { } // namespace Radix +namespace StorageSize { + + static ASR::expr_t *eval_StorageSize(Allocator &al, const Location &loc, + ASR::ttype_t* t1, Vec &args, diag::Diagnostics& /*diag*/) { + int64_t kind = ASRUtils::extract_kind_from_ttype_t(expr_type(args[0])); + if (is_character(*expr_type(args[0]))) { + int64_t len = ASR::down_cast(ASRUtils::type_get_past_array(expr_type(args[0])))->m_len; + return make_ConstantWithType(make_IntegerConstant_t, 8*len, t1, loc); + } else if (is_complex(*expr_type(args[0]))) { + if (kind == 4) return make_ConstantWithType(make_IntegerConstant_t, 64, t1, loc); + else if (kind == 8) return make_ConstantWithType(make_IntegerConstant_t, 128, t1, loc); + else return make_ConstantWithType(make_IntegerConstant_t, -1, t1, loc); + } else { + if (kind == 1) return make_ConstantWithType(make_IntegerConstant_t, 8, t1, loc); + else if (kind == 2) return make_ConstantWithType(make_IntegerConstant_t, 16, t1, loc); + else if (kind == 4) return make_ConstantWithType(make_IntegerConstant_t, 32, t1, loc); + else if (kind == 8) return make_ConstantWithType(make_IntegerConstant_t, 64, t1, loc); + else return make_ConstantWithType(make_IntegerConstant_t, -1, t1, loc); + } + } + +} // namespace StorageSize + namespace Scale { static ASR::expr_t *eval_Scale(Allocator &al, const Location &loc, ASR::ttype_t* arg_type, Vec &args, diag::Diagnostics& /*diag*/) { - double value_X = ASR::down_cast(expr_value(args[0]))->m_r; - int64_t value_I = ASR::down_cast(expr_value(args[1]))->m_n; + double value_X = ASR::down_cast(args[0])->m_r; + int64_t value_I = ASR::down_cast(args[1])->m_n; double result = value_X * std::pow(2, value_I); ASRUtils::ASRBuilder b(al, loc); - return b.f(result, arg_type); + return b.f_t(result, arg_type); } static inline ASR::expr_t* instantiate_Scale(Allocator &al, const Location &loc, SymbolTable *scope, Vec& arg_types, ASR::ttype_t *return_type, Vec& new_args, int64_t /*overload_id*/) { - declare_basic_variables(""); + declare_basic_variables("_lcompilers_scale_" + type_to_str_python(arg_types[0])); fill_func_arg("x", arg_types[0]); - fill_func_arg("y", arg_types[1]); + fill_func_arg("i", arg_types[1]); auto result = declare(fn_name, return_type, ReturnVar); /* * r = scale(x, y) * r = x * 2**y */ - //TODO: Radix for most of the device is 2, so we can use the b.i2r32(2) instead of args[1]. Fix (find a way to get the radix of the device and use it here) - body.push_back(al, b.Assignment(result, b.r_tMul(args[0], b.i2r32(b.iPow(b.i(2, arg_types[1]), args[1], arg_types[1])), arg_types[0]))); + //TODO: Radix for most of the device is 2, so we can use the b.i2r_t(2, real32) instead of args[1]. Fix (find a way to get the radix of the device and use it here) + body.push_back(al, b.Assignment(result, b.Mul(args[0], b.i2r_t(b.Pow(b.i_t(2, arg_types[1]), args[1]), return_type)))); ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); scope->add_symbol(fn_name, f_sym); return b.Call(f_sym, new_args, return_type, nullptr); @@ -915,26 +951,36 @@ namespace Scale { namespace Dprod { static ASR::expr_t *eval_Dprod(Allocator &al, const Location &loc, - ASR::ttype_t* return_type, Vec &args, diag::Diagnostics& /*diag*/) { - double value_X = ASR::down_cast(expr_value(args[0]))->m_r; - double value_Y = ASR::down_cast(expr_value(args[1]))->m_r; + ASR::ttype_t* return_type, Vec &args, diag::Diagnostics& diag) { + double value_X = ASR::down_cast(args[0])->m_r; + double value_Y = ASR::down_cast(args[1])->m_r; + if (ASRUtils::extract_kind_from_ttype_t(expr_type(args[0])) != 4 || + ASRUtils::extract_kind_from_ttype_t(expr_type(args[1])) != 4) { + append_error(diag, "Arguments to dprod must be real(4)", loc); + return nullptr; + } double result = value_X * value_Y; ASRUtils::ASRBuilder b(al, loc); - return b.f(result, return_type); + return b.f_t(result, return_type); } static inline ASR::expr_t* instantiate_Dprod(Allocator &al, const Location &loc, SymbolTable *scope, Vec& arg_types, ASR::ttype_t *return_type, Vec& new_args, int64_t /*overload_id*/) { - declare_basic_variables(""); + declare_basic_variables("_lcompilers_dprod_" + type_to_str_python(arg_types[0])); fill_func_arg("x", arg_types[0]); fill_func_arg("y", arg_types[1]); + if (ASRUtils::extract_kind_from_ttype_t(arg_types[0]) != 4 || + ASRUtils::extract_kind_from_ttype_t(arg_types[1]) != 4) { + LCompilersException("Arguments to dprod must be default real"); + return nullptr; + } auto result = declare(fn_name, return_type, ReturnVar); /* * r = dprod(x, y) * r = x * y */ - body.push_back(al, b.Assignment(result, b.r2r64(b.r32Mul(args[0],args[1])))); + body.push_back(al, b.Assignment(result, b.r2r_t(b.Mul(args[0],args[1]), real64))); ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); scope->add_symbol(fn_name, f_sym); return b.Call(f_sym, new_args, return_type, nullptr); @@ -942,6 +988,16 @@ namespace Dprod { } // namespace Dprod +namespace SameTypeAs { + + static ASR::expr_t *eval_SameTypeAs(Allocator &/*al*/, const Location &loc, + ASR::ttype_t* /*t1*/, Vec &/*args*/, diag::Diagnostics& diag) { + append_error(diag, "same_type_as is not implemented yet", loc); + return nullptr; + } + +} // namespace SameTypeAs + namespace Range { static ASR::expr_t *eval_Range(Allocator &al, const Location &loc, @@ -980,66 +1036,319 @@ namespace Range { } // namespace Range -namespace Sign { +namespace OutOfRange +{ - static ASR::expr_t *eval_Sign(Allocator &al, const Location &loc, - ASR::ttype_t* t1, Vec &args, diag::Diagnostics& /*diag*/) { - if (ASRUtils::is_real(*t1)) { - double rv1 = std::abs(ASR::down_cast(args[0])->m_r); - double rv2 = ASR::down_cast(args[1])->m_r; - rv1 = copysign(rv1, rv2); - return make_ConstantWithType(make_RealConstant_t, rv1, t1, loc); - } else { - int64_t iv1 = std::abs(ASR::down_cast(args[0])->m_n); - int64_t iv2 = ASR::down_cast(args[1])->m_n; - if (iv2 < 0) iv1 = -iv1; - return make_ConstantWithType(make_IntegerConstant_t, iv1, t1, loc); + static ASR::expr_t* eval_OutOfRange(Allocator& al, const Location& loc, + ASR::ttype_t* return_type, Vec& args, diag::Diagnostics& /*diag*/){ + ASRUtils::ASRBuilder b(al, loc); + long long max_val_int = 0; + long long min_val_int = 0; + double max_val_float = 0.0; + double min_val_float = 0.0; + + ASR::ttype_t* arg_type_1 = expr_type(args[0]); + ASR::ttype_t* arg_type_2 = expr_type(args[1]); + int32_t kind_2 = extract_kind_from_ttype_t(arg_type_2); + switch (kind_2) { + case 1: + max_val_int = 127; + min_val_int = -128; + break; + case 2: + max_val_int = 32767; + min_val_int = -32768; + break; + case 4: + max_val_int = 2147483647; + min_val_int = -2147483648; + max_val_float = 3.4028234663852886e+38; + min_val_float = -3.4028234663852886e+38; + break; + case 8: + max_val_int = 9223372036854775807; + min_val_int = -9223372036854775807; + max_val_float = 1.7976931348623157e+308; + min_val_float = -1.7976931348623157e+308; + break; + } + if (is_integer(*arg_type_1)) { + int64_t value = ASR::down_cast(args[0])->m_n; + if (is_integer(*arg_type_2)) { + if (value > max_val_int || value < min_val_int) { + return b.bool_t(1, return_type); + } + } else if (is_real(*arg_type_2)) { + if ((double) value > max_val_float || (double) value < min_val_float) { + return b.bool_t(1, return_type); + } + } + } else if (is_real(*arg_type_1)) { + double value = ASR::down_cast(args[0])->m_r; + if (is_integer(*arg_type_2)) { + if (value > (double) max_val_int || value < (double) min_val_int) { + return b.bool_t(1, return_type); + } + } else if (is_real(*arg_type_2)) { + if (value > max_val_float || value < min_val_float) { + return b.bool_t(1, return_type); + } + } } + + return b.bool_t(0, return_type); } - static inline ASR::expr_t* instantiate_Sign(Allocator &al, const Location &loc, - SymbolTable *scope, Vec& arg_types, ASR::ttype_t *return_type, + static inline ASR::expr_t* instantiate_OutOfRange(Allocator& al, const Location& loc, + SymbolTable* scope, Vec& arg_types, ASR::ttype_t* return_type, Vec& new_args, int64_t /*overload_id*/) { - declare_basic_variables("_lcompilers_sign_" + type_to_str_python(arg_types[0])); - fill_func_arg("x", arg_types[0]); - fill_func_arg("y", arg_types[0]); - auto result = declare(fn_name, return_type, ReturnVar); - if (is_real(*arg_types[0])) { - Vec args; args.reserve(al, 2); - visit_expr_list(al, new_args, args); - return ASRUtils::EXPR(ASR::make_RealCopySign_t(al, loc, args[0], args[1], arg_types[0], nullptr)); - } else { - /* - * r = abs(x) - * if (y < 0) then - * r = -r - * end if - */ - body.push_back(al, b.If(b.iGtE(args[0], b.i(0, arg_types[0])), { - b.Assignment(result, args[0]) - }, { - b.Assignment(result, b.i32_neg(args[0], arg_types[0])) - })); - body.push_back(al, b.If(b.iLt(args[1], b.i(0, arg_types[0])), { - b.Assignment(result, b.i32_neg(result, arg_types[0])) - }, {})); - ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, - body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); - scope->add_symbol(fn_name, f_sym); - return b.Call(f_sym, new_args, return_type, nullptr); - } - } + declare_basic_variables("_lcompilers_out_of_range_" + type_to_str_python(arg_types[0])); -} // namespace Sign + fill_func_arg("value", arg_types[0]); + fill_func_arg("mold", arg_types[1]); + fill_func_arg("round", arg_types[2]); -namespace Shiftr { + auto result = declare(fn_name, return_type, ReturnVar); - static ASR::expr_t *eval_Shiftr(Allocator &al, const Location &loc, - ASR::ttype_t* t1, Vec &args, diag::Diagnostics& /*diag*/) { - int64_t val1 = ASR::down_cast(args[0])->m_n; - int64_t val2 = ASR::down_cast(args[1])->m_n; - int64_t val = val1 >> val2; + ASR::expr_t* max_val = nullptr; + ASR::expr_t* min_val = nullptr; + int kind1 = extract_kind_from_ttype_t(arg_types[0]); + int kind2 = extract_kind_from_ttype_t(arg_types[1]); + + if (is_integer(*arg_types[1])) { + if (kind2 == 4) { + if (kind1 == 4) { + max_val = b.i32(2147483647); + min_val = b.i32(-2147483648); + body.push_back(al, + b.If(b.Or(b.Gt(args[0], max_val), b.Lt(args[0], min_val)), + { b.Assignment(result, b.bool_t(true, return_type)) }, + { b.Assignment(result, b.bool_t(false, return_type)) })); + } else { + max_val = b.i64(2147483647); + min_val = b.i64(-2147483648); + body.push_back(al, + b.If(b.Or(b.Gt(args[0], max_val), b.Lt(args[0], min_val)), + { b.Assignment(result, b.bool_t(true, return_type)) }, + { b.Assignment(result, b.bool_t(false, return_type)) })); + } + } else if (kind2 == 8) { + max_val = b.i64(9223372036854775807); + min_val = b.i64(-9223372036854775807); + body.push_back(al, + b.If(b.Or(b.Gt(b.i2i_t(args[0], arg_types[1]), max_val), b.Lt(b.i2i_t(args[0], arg_types[1]), min_val)), + { b.Assignment(result, b.bool_t(true, return_type)) }, + { b.Assignment(result, b.bool_t(false, return_type)) })); + } + } else if (is_real(*arg_types[1])) { + if (kind2 == 4) { + if (kind1 == 4) { + max_val = b.f32(3.4028235e+38f); + min_val = b.f32(-3.4028235e+38f); + body.push_back(al, b.If(b.Or(b.Gt(args[0], max_val), b.Lt(args[0], min_val)), + { b.Assignment(result, b.bool_t(true, return_type)) }, + { b.Assignment(result, b.bool_t(false, return_type)) })); + } else if (kind1 == 8) { + max_val = b.f64(3.4028235e+38f); + min_val = b.f64(-3.4028235e+38f); + body.push_back(al, b.If(b.Or(b.Gt(args[0], max_val), b.Lt(args[0], min_val)), + { b.Assignment(result, b.bool_t(true, return_type))}, + { b.Assignment(result, b.bool_t(false, return_type))})); + } + } else if (kind2 == 8) { + max_val = b.f64(1.7976931348623157e+308); + min_val = b.f64(-1.7976931348623157e+308); + body.push_back(al, b.If( b.Or(b.Gt(b.i2i_t(args[0], arg_types[1]), max_val), b.Lt(b.i2i_t(args[0], arg_types[1]), min_val)), + { b.Assignment(result, b.bool_t(true, return_type)) }, + { b.Assignment(result, b.bool_t(false, return_type)) })); + } + } + + ASR::symbol_t *new_symbol = make_ASR_Function_t(fn_name, fn_symtab, dep, args, + body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); + scope->add_symbol(fn_name, new_symbol); + return b.Call(new_symbol, new_args, return_type); + } + + +} // namespace OutOfRange + +namespace CompilerVersion { + + static inline void verify_args(const ASR::IntrinsicElementalFunction_t& x, diag::Diagnostics& diagnostics) { + ASRUtils::require_impl(x.n_args == 0, + "compiler_version() takes no argument", + x.base.base.loc, diagnostics); + } + + static ASR::expr_t *eval_CompilerVersion(Allocator &al, const Location &loc, + ASR::ttype_t */*t1*/, Vec &/*args*/, diag::Diagnostics& /*diag*/) { + ASRUtils::ASRBuilder b(al, loc); + std::string version = LFORTRAN_VERSION; + return b.StringConstant("LFortran version " + version, character(-1)); + } + + static inline ASR::asr_t* create_CompilerVersion(Allocator& al, const Location& loc, Vec& args, diag::Diagnostics& diag) { + ASR::ttype_t *return_type = character(-1); + ASR::expr_t *m_value = nullptr; + return_type = ASRUtils::extract_type(return_type); + m_value = eval_CompilerVersion(al, loc, return_type, args, diag); + if (diag.has_error()) { + return nullptr; + } + return ASR::make_IntrinsicElementalFunction_t(al, loc, static_cast(IntrinsicElementalFunctions::CompilerVersion), + nullptr, 0, 0, return_type, m_value); + } +} // namespace CompilerVersion + +namespace CompilerOptions { + + static inline void verify_args(const ASR::IntrinsicElementalFunction_t& x, diag::Diagnostics& diagnostics) { + ASRUtils::require_impl(x.n_args == 0, + "compiler_options() takes no argument", + x.base.base.loc, diagnostics); + } + + static ASR::expr_t *eval_CompilerOptions(Allocator &al, const Location &loc, + ASR::ttype_t */*t1*/, Vec &/*args*/, diag::Diagnostics& /*diag*/) { + ASRUtils::ASRBuilder b(al, loc); + return b.StringConstant(lcompilers_commandline_options, character(-1)); + } + + static inline ASR::asr_t* create_CompilerOptions(Allocator& al, const Location& loc, Vec& args, diag::Diagnostics& diag) { + ASR::ttype_t *return_type = character(-1); + ASR::expr_t *m_value = nullptr; + return_type = ASRUtils::extract_type(return_type); + m_value = eval_CompilerOptions(al, loc, return_type, args, diag); + if (diag.has_error()) { + return nullptr; + } + return ASR::make_IntrinsicElementalFunction_t(al, loc, static_cast(IntrinsicElementalFunctions::CompilerOptions), + nullptr, 0, 0, return_type, m_value); + } +} // namespace CompilerOptions + +namespace CommandArgumentCount { + + static inline void verify_args(const ASR::IntrinsicElementalFunction_t& x, diag::Diagnostics& diagnostics) { + ASRUtils::require_impl(x.n_args == 0, + "command_argument_count() takes no argument", + x.base.base.loc, diagnostics); + } + + static inline ASR::asr_t* create_CommandArgumentCount(Allocator& al, const Location& loc, Vec& /*args*/, diag::Diagnostics& diag) { + ASR::ttype_t *return_type = ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)); + ASR::expr_t *m_value = nullptr; + return_type = ASRUtils::extract_type(return_type); + m_value = nullptr; + if (diag.has_error()) { + return nullptr; + } + return ASR::make_IntrinsicElementalFunction_t(al, loc, static_cast(IntrinsicElementalFunctions::CommandArgumentCount), + nullptr, 0, 0, return_type, m_value); + } + + static inline ASR::expr_t* instantiate_CommandArgumentCount(Allocator &al, const Location &loc, + SymbolTable *scope, Vec& arg_types, ASR::ttype_t *return_type, + Vec& new_args, int64_t /*overload_id*/){ + std::string c_func_name; + c_func_name = "_lfortran_command_argument_count"; + std::string new_name = "_lcompilers_command_argument_count_"; + + declare_basic_variables(new_name); + if (scope->get_symbol(new_name)) { + ASR::symbol_t *s = scope->get_symbol(new_name); + ASR::Function_t *f = ASR::down_cast(s); + return b.Call(s, new_args, expr_type(f->m_return_var)); + } + auto result = declare(new_name, return_type, ReturnVar); + { + ASR::symbol_t *s = b.create_c_func(c_func_name, fn_symtab, return_type, 0, arg_types); + fn_symtab->add_symbol(c_func_name, s); + dep.push_back(al, s2c(al, c_func_name)); + body.push_back(al, b.Assignment(result, b.Call(s, args, return_type))); + } + + ASR::symbol_t *new_symbol = make_ASR_Function_t(fn_name, fn_symtab, dep, args, + body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); + scope->add_symbol(fn_name, new_symbol); + return b.Call(new_symbol, new_args, return_type); + } +} // namespace CommandArgumentCount + +namespace Sign { + + static ASR::expr_t *eval_Sign(Allocator &al, const Location &loc, + ASR::ttype_t* t1, Vec &args, diag::Diagnostics& /*diag*/) { + if (ASRUtils::is_real(*t1)) { + double rv1 = std::abs(ASR::down_cast(args[0])->m_r); + double rv2 = ASR::down_cast(args[1])->m_r; + rv1 = copysign(rv1, rv2); + return make_ConstantWithType(make_RealConstant_t, rv1, t1, loc); + } else { + int64_t iv1 = std::abs(ASR::down_cast(args[0])->m_n); + int64_t iv2 = ASR::down_cast(args[1])->m_n; + if (iv2 < 0) iv1 = -iv1; + return make_ConstantWithType(make_IntegerConstant_t, iv1, t1, loc); + } + } + + static inline ASR::expr_t* instantiate_Sign(Allocator &al, const Location &loc, + SymbolTable *scope, Vec& arg_types, ASR::ttype_t *return_type, + Vec& new_args, int64_t /*overload_id*/) { + declare_basic_variables("_lcompilers_sign_" + type_to_str_python(arg_types[0])); + fill_func_arg("x", arg_types[0]); + fill_func_arg("y", arg_types[0]); + auto result = declare(fn_name, return_type, ReturnVar); + if (is_real(*arg_types[0])) { + Vec args; args.reserve(al, 2); + visit_expr_list(al, new_args, args); + return ASRUtils::EXPR(ASR::make_RealCopySign_t(al, loc, args[0], args[1], arg_types[0], nullptr)); + } else { + /* + * r = abs(x) + * if (y < 0) then + * r = -r + * end if + */ + body.push_back(al, b.If(b.GtE(args[0], b.i_t(0, arg_types[0])), { + b.Assignment(result, args[0]) + }, { + b.Assignment(result, b.i_neg(args[0], arg_types[0])) + })); + body.push_back(al, b.If(b.Lt(args[1], b.i_t(0, arg_types[0])), { + b.Assignment(result, b.i_neg(result, arg_types[0])) + }, {})); + + ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, + body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); + scope->add_symbol(fn_name, f_sym); + return b.Call(f_sym, new_args, return_type, nullptr); + } + } + +} // namespace Sign + +namespace Shiftr { + + static ASR::expr_t *eval_Shiftr(Allocator &al, const Location &loc, + ASR::ttype_t* t1, Vec &args, diag::Diagnostics& diag) { + int64_t val1 = ASR::down_cast(args[0])->m_n; + int64_t val2 = ASR::down_cast(args[1])->m_n; + int kind = ASRUtils::extract_kind_from_ttype_t(ASR::down_cast(args[0])->m_type); + if(val2 < 0) { + append_error(diag, "The shift argument of 'shiftr' intrinsic must be non-negative integer", args[1]->base.loc); + return nullptr; + } + int k_val = kind * 8; + if (val2 > k_val) { + diag.add(diag::Diagnostic("The shift argument of 'shiftr' intrinsic must be less than or equal to the bit size of the integer", diag::Level::Error, + diag::Stage::Semantic, {diag::Label("Shift value is " + std::to_string(val2) + + ", but bit size of integer is " + std::to_string(k_val), { args[1]->base.loc })})); + return nullptr; + } + int64_t val = val1 >> val2; return make_ConstantWithType(make_IntegerConstant_t, val, t1, loc); } @@ -1054,7 +1363,7 @@ namespace Shiftr { * r = shiftr(x, y) * r = x >> y */ - body.push_back(al, b.Assignment(result, b.i_BitRshift(args[0], b.i2i(args[1], arg_types[0]), arg_types[0]))); + body.push_back(al, b.Assignment(result, b.BitRshift(args[0], b.i2i_t(args[1], arg_types[0]), arg_types[0]))); ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); @@ -1072,9 +1381,21 @@ namespace Shiftr { namespace Rshift { static ASR::expr_t *eval_Rshift(Allocator &al, const Location &loc, - ASR::ttype_t* t1, Vec &args, diag::Diagnostics& /*diag*/) { + ASR::ttype_t* t1, Vec &args, diag::Diagnostics& diag) { int64_t val1 = ASR::down_cast(args[0])->m_n; int64_t val2 = ASR::down_cast(args[1])->m_n; + int kind = ASRUtils::extract_kind_from_ttype_t(ASR::down_cast(args[0])->m_type); + if(val2 < 0) { + append_error(diag, "The shift argument of 'rshift' intrinsic must be non-negative integer", args[1]->base.loc); + return nullptr; + } + int k_val = kind * 8; + if (val2 > k_val) { + diag.add(diag::Diagnostic("The shift argument of 'rshift' intrinsic must be less than or equal to the bit size of the integer", diag::Level::Error, + diag::Stage::Semantic, {diag::Label("Shift value is " + std::to_string(val2) + + ", but bit size of integer is " + std::to_string(k_val), { args[1]->base.loc })})); + return nullptr; + } int64_t val = val1 >> val2; return make_ConstantWithType(make_IntegerConstant_t, val, t1, loc); } @@ -1090,7 +1411,7 @@ namespace Rshift { * r = rshift(x, y) * r = x >> y */ - body.push_back(al, b.Assignment(result, b.i_BitRshift(args[0], args[1], arg_types[0]))); + body.push_back(al, b.Assignment(result, b.BitRshift(args[0], args[1], arg_types[0]))); ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); @@ -1104,9 +1425,21 @@ namespace Rshift { namespace Shiftl { static ASR::expr_t *eval_Shiftl(Allocator &al, const Location &loc, - ASR::ttype_t* t1, Vec &args, diag::Diagnostics& /*diag*/) { + ASR::ttype_t* t1, Vec &args, diag::Diagnostics& diag) { int64_t val1 = ASR::down_cast(args[0])->m_n; int64_t val2 = ASR::down_cast(args[1])->m_n; + int kind = ASRUtils::extract_kind_from_ttype_t(ASR::down_cast(args[0])->m_type); + if(val2 < 0) { + append_error(diag, "The shift argument of 'shiftl' intrinsic must be non-negative integer", args[1]->base.loc); + return nullptr; + } + int k_val = kind * 8; + if (val2 > k_val) { + diag.add(diag::Diagnostic("The shift argument of 'shiftl' intrinsic must be less than or equal to the bit size of the integer", diag::Level::Error, + diag::Stage::Semantic, {diag::Label("Shift value is " + std::to_string(val2) + + ", but bit size of integer is " + std::to_string(k_val), { args[1]->base.loc })})); + return nullptr; + } int64_t val = val1 << val2; return make_ConstantWithType(make_IntegerConstant_t, val, t1, loc); } @@ -1122,7 +1455,7 @@ namespace Shiftl { * r = shiftl(x, y) * r = x << y */ - body.push_back(al, b.Assignment(result, b.i_BitLshift(args[0], b.i2i(args[1], arg_types[0]), arg_types[0]))); + body.push_back(al, b.Assignment(result, b.BitLshift(args[0], b.i2i_t(args[1], arg_types[0]), arg_types[0]))); ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); @@ -1139,22 +1472,21 @@ namespace Shiftl { namespace Dshiftl { - static ASR::expr_t *eval_Dshiftl(Allocator &al, const Location &loc, - ASR::ttype_t* t1, Vec &args, diag::Diagnostics& diag) { + static ASR::expr_t *eval_Dshiftl(Allocator &al, const Location &loc, + ASR::ttype_t* t1, Vec &args, diag::Diagnostics& diag) { int64_t val1 = ASR::down_cast(args[0])->m_n; int64_t val2 = ASR::down_cast(args[1])->m_n; int64_t shift = ASR::down_cast(args[2])->m_n; - int kind1 = ASRUtils::extract_kind_from_ttype_t(ASR::down_cast(args[0])->m_type); - int kind2 = ASRUtils::extract_kind_from_ttype_t(ASR::down_cast(args[1])->m_type); - if(kind1 != kind2) { - append_error(diag, "The kind of first argument of 'dshiftl' intrinsic must be the same as second arguement", loc); + int kind = ASRUtils::extract_kind_from_ttype_t(ASR::down_cast(args[0])->m_type); + if(shift < 0){ + append_error(diag, "The shift argument of 'dshiftl' intrinsic must be non-negative integer", args[2]->base.loc); return nullptr; } - if(shift < 0){ - append_error(diag, "The shift argument of 'dshiftl' intrinsic must be non-negative integer", loc); + int k_val = kind * 8; + if (shift > k_val) { + append_error(diag, "The shift argument of 'dshiftl' intrinsic must be less than or equal to the bit size of the integer", args[2]->base.loc); return nullptr; } - int k_val = (kind1 == 8) ? 64: 32; int64_t val = (val1 << shift) | (val2 >> (k_val - shift)); return make_ConstantWithType(make_IntegerConstant_t, val, t1, loc); } @@ -1173,11 +1505,11 @@ namespace Dshiftl { * r = x << shift | y >> (32 - shift) ! kind = 4 * r = x << shift | y >> (64 - shift) ! kind = 8 */ - body.push_back(al, b.Assignment(result, b.i_BitLshift(args[0], b.i2i(args[2], return_type), return_type))); - body.push_back(al, b.If(b.iEq(b.i(extract_kind_from_ttype_t(arg_types[0]), int32), b.i(4, int32)), { - b.Assignment(result, b.i_BitOr(result, b.i_BitRshift(args[1], b.i_tSub(b.i(32, return_type), args[2], return_type), return_type), return_type)) + body.push_back(al, b.Assignment(result, b.BitLshift(args[0], b.i2i_t(args[2], return_type), return_type))); + body.push_back(al, b.If(b.Eq(b.i32(extract_kind_from_ttype_t(arg_types[0])), b.i32(4)), { + b.Assignment(result, b.Or(result, b.BitRshift(args[1], b.Sub(b.i_t(32, return_type), args[2]), return_type))) }, { - b.Assignment(result, b.i_BitOr(result, b.i_BitRshift(args[1], b.i_tSub(b.i(64, return_type), args[2], return_type), return_type), return_type)) + b.Assignment(result, b.Or(result, b.BitRshift(args[1], b.Sub(b.i_t(64, return_type), args[2]), return_type))) })); ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, @@ -1189,6 +1521,110 @@ namespace Dshiftl { } // namespace Dshiftl +namespace Dshiftr { + + static ASR::expr_t *eval_Dshiftr(Allocator &al, const Location &loc, + ASR::ttype_t* t1, Vec &args, diag::Diagnostics& diag) { + int64_t val1 = ASR::down_cast(args[0])->m_n; + int64_t val2 = ASR::down_cast(args[1])->m_n; + int64_t shift = ASR::down_cast(args[2])->m_n; + int kind1 = ASRUtils::extract_kind_from_ttype_t(ASR::down_cast(args[0])->m_type); + int kind2 = ASRUtils::extract_kind_from_ttype_t(ASR::down_cast(args[1])->m_type); + if(kind1 != kind2) { + append_error(diag, "The kind of first argument of 'dshiftr' intrinsic must be the same as second argument", loc); + return nullptr; + } + if(shift < 0){ + append_error(diag, "The shift argument of 'dshiftr' intrinsic must be non-negative integer", args[2]->base.loc); + return nullptr; + } + int64_t k_val = kind1 * 8; + if (shift > k_val) { + append_error(diag, "The shift argument of 'dshiftr' intrinsic must be less than or equal to the bit size of the integer", args[2]->base.loc); + return nullptr; + } + int64_t rightmostI = val1 & ((1LL << shift) - 1); + int64_t result = rightmostI << (k_val - shift); + int64_t leftmostJ; + if (val2 < 0) { + leftmostJ = (val2 >> shift) & ((1LL << (k_val - shift)) - 1LL); + } else { + leftmostJ = val2 >> shift; + } + result |= leftmostJ; + return make_ConstantWithType(make_IntegerConstant_t, result, t1, loc); + } + + + static inline ASR::expr_t* instantiate_Dshiftr(Allocator &al, const Location &loc, + SymbolTable *scope, Vec& arg_types, ASR::ttype_t *return_type, + Vec& new_args, int64_t /*overload_id*/) { + declare_basic_variables("_lcompilers_dshiftr_" + type_to_str_python(arg_types[0])); + fill_func_arg("i", arg_types[0]); + fill_func_arg("j", arg_types[1]); + fill_func_arg("shift", arg_types[2]); + auto final_result = declare("x", int64, Local); + auto result = declare(fn_name , return_type, ReturnVar); + + body.push_back(al, b.Assignment(final_result, b.BitLshift(b.And(b.i2i_t(args[0], int64), + b.Sub(b.BitLshift(b.i64(1), b.i2i_t(args[2], int64), int64), b.i64(1))), + b.Sub(b.Mul(b.i64(extract_kind_from_ttype_t(arg_types[0])), b.i64(8)), b.i2i_t(args[2], int64)), int64))); + + body.push_back(al, b.If(b.Lt(b.i2i_t(args[1], int64), b.i64(0)), { + b.Assignment(final_result, b.Or(final_result, b.And(b.BitRshift(b.i2i_t(args[1], int64), + b.Sub(b.Mul((b.i64(extract_kind_from_ttype_t(arg_types[0]))), b.i64(8)), b.i2i_t(args[2], int64)), int64), + b.Sub(b.BitLshift(b.i64(1), b.Sub(b.Mul((b.i64(extract_kind_from_ttype_t(arg_types[0]))), b.i64(8)), + b.i2i_t(args[2], int64)), int64), b.i64(1))))) + }, { + b.Assignment(final_result, b.Or(final_result, b.BitRshift(b.i2i_t(args[1], int64), + b.Sub(b.Mul((b.i64(extract_kind_from_ttype_t(arg_types[0]))), b.i64(8)), b.i2i_t(args[2], int64)), int64))) + })); + body.push_back(al, b.Assignment(result, b.i2i_t(final_result, return_type))); + + ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, + body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); + scope->add_symbol(fn_name, f_sym); + return b.Call(f_sym, new_args, return_type, nullptr); + + } + +} // namespace Dshiftr + +namespace Dreal { + + static inline ASR::expr_t *eval_Dreal(Allocator &al, const Location &loc, + ASR::ttype_t *t, Vec& args, diag::Diagnostics& diag) { + ASRUtils::ASRBuilder b(al, loc); + std::complex crv; + int kind = ASRUtils::extract_kind_from_ttype_t(ASR::down_cast(args[0])->m_type); + if(kind == 4){ + append_error(diag, "The argument of 'dreal' intrinsic must be of kind 8", loc); + return nullptr; + } + if( ASRUtils::extract_value(args[0], crv) ) { + double result = std::real(crv); + return make_ConstantWithType(make_RealConstant_t, result, t, loc); + } else { + return nullptr; + } + } + + static inline ASR::expr_t* instantiate_Dreal(Allocator &al, const Location &loc, + SymbolTable* scope, Vec& arg_types, ASR::ttype_t *return_type, + Vec &new_args,int64_t /*overload_id*/) { + declare_basic_variables("_lcompilers_dreal_" + type_to_str_python(arg_types[0])); + fill_func_arg("x", arg_types[0]); + auto result = declare(fn_name, return_type, ReturnVar); + body.push_back(al, b.Assignment(result, b.c2r_t(args[0], real64))); + + ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, + body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); + scope->add_symbol(fn_name, f_sym); + return b.Call(f_sym, new_args, return_type, nullptr); + } + +} // namespace Dreal + namespace Ishft { @@ -1221,10 +1657,10 @@ namespace Ishft { * r = x << y * } */ - body.push_back(al, b.If(b.iLtE(args[1], b.i(0, arg_types[0])), { - b.Assignment(result, b.i_BitRshift(args[0], b.iMul(b.i(-1, arg_types[0]), args[1]), arg_types[0])) + body.push_back(al, b.If(b.LtE(args[1], b.i_t(0, arg_types[0])), { + b.Assignment(result, b.BitRshift(args[0], b.Mul(b.i_t(-1, arg_types[0]), args[1]), arg_types[0])) }, { - b.Assignment(result, b.i_BitLshift(args[0], args[1], arg_types[0])) + b.Assignment(result, b.BitLshift(args[0], args[1], arg_types[0])) })); ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, @@ -1261,14 +1697,14 @@ namespace Bgt { fill_func_arg("x", arg_types[0]); fill_func_arg("y", arg_types[1]); auto result = declare(fn_name, logical, ReturnVar); - body.push_back(al, b.Assignment(result, b.bool32(0))); - body.push_back(al, b.If(b.Or(b.iGt(b.iMul(args[0], args[1]), b.i(0, arg_types[0])), b.And(b.iEq(b.iMul(args[0], args[1]), b.i(0, arg_types[0])), b.Or(b.iGt(args[0], b.i(0, arg_types[0])), b.iGt(args[1], b.i(0, arg_types[0]))))), { - b.If(b.iGt(args[0], args[1]), { - b.Assignment(result, b.bool32(1)) + body.push_back(al, b.Assignment(result, b.bool_t(0, logical))); + body.push_back(al, b.If(b.Or(b.Gt(b.Mul(args[0], args[1]), b.i_t(0, arg_types[0])), b.And(b.Eq(b.Mul(args[0], args[1]), b.i_t(0, arg_types[0])), b.Or(b.Gt(args[0], b.i_t(0, arg_types[0])), b.Gt(args[1], b.i_t(0, arg_types[0]))))), { + b.If(b.Gt(args[0], args[1]), { + b.Assignment(result, b.bool_t(1, logical)) }, {}) }, { - b.If(b.iLt(args[0], args[1]), { - b.Assignment(result, b.bool32(1)) + b.If(b.Lt(args[0], args[1]), { + b.Assignment(result, b.bool_t(1, logical)) }, {}) })); @@ -1306,14 +1742,14 @@ namespace Blt { fill_func_arg("x", arg_types[0]); fill_func_arg("y", arg_types[1]); auto result = declare(fn_name, logical, ReturnVar); - body.push_back(al, b.Assignment(result, b.bool32(0))); - body.push_back(al, b.If(b.Or(b.iGt(b.iMul(args[0], args[1]), b.i(0, arg_types[0])), b.And(b.iEq(b.iMul(args[0], args[1]), b.i(0, arg_types[0])), b.Or(b.iGt(args[0], b.i(0, arg_types[0])), b.iGt(args[1], b.i(0, arg_types[0]))))), { - b.If(b.iLt(args[0], args[1]), { - b.Assignment(result, b.bool32(1)) + body.push_back(al, b.Assignment(result, b.bool_t(0, logical))); + body.push_back(al, b.If(b.Or(b.Gt(b.Mul(args[0], args[1]), b.i_t(0, arg_types[0])), b.And(b.Eq(b.Mul(args[0], args[1]), b.i_t(0, arg_types[0])), b.Or(b.Gt(args[0], b.i_t(0, arg_types[0])), b.Gt(args[1], b.i_t(0, arg_types[0]))))), { + b.If(b.Lt(args[0], args[1]), { + b.Assignment(result, b.bool_t(1, logical)) }, {}) }, { - b.If(b.iGt(args[0], args[1]), { - b.Assignment(result, b.bool32(1)) + b.If(b.Gt(args[0], args[1]), { + b.Assignment(result, b.bool_t(1, logical)) }, {}) })); @@ -1351,14 +1787,14 @@ namespace Bge { fill_func_arg("x", arg_types[0]); fill_func_arg("y", arg_types[1]); auto result = declare(fn_name, logical, ReturnVar); - body.push_back(al, b.Assignment(result, b.bool32(0))); - body.push_back(al, b.If(b.Or(b.iGt(b.iMul(args[0], args[1]), b.i(0, arg_types[0])), b.And(b.iEq(b.iMul(args[0], args[1]), b.i(0, arg_types[0])), b.Or(b.iGt(args[0], b.i(0, arg_types[0])), b.iGt(args[1], b.i(0, arg_types[0]))))), { - b.If(b.iGtE(args[0], args[1]), { - b.Assignment(result, b.bool32(1)) + body.push_back(al, b.Assignment(result, b.bool_t(0, logical))); + body.push_back(al, b.If(b.Or(b.Gt(b.Mul(args[0], args[1]), b.i_t(0, arg_types[0])), b.And(b.Eq(b.Mul(args[0], args[1]), b.i_t(0, arg_types[0])), b.Or(b.Gt(args[0], b.i_t(0, arg_types[0])), b.Gt(args[1], b.i_t(0, arg_types[0]))))), { + b.If(b.GtE(args[0], args[1]), { + b.Assignment(result, b.bool_t(1, logical)) }, {}) }, { - b.If(b.iLtE(args[0], args[1]), { - b.Assignment(result, b.bool32(1)) + b.If(b.LtE(args[0], args[1]), { + b.Assignment(result, b.bool_t(1, logical)) }, {}) })); @@ -1370,6 +1806,61 @@ namespace Bge { } // namespace Bge +namespace Present { + + static ASR::expr_t *eval_Present(Allocator &/*al*/, const Location &/*loc*/, + ASR::ttype_t* /*t1*/, Vec &/*args*/, diag::Diagnostics& /*diag*/) { return nullptr; } + + static inline void verify_args(const ASR::IntrinsicElementalFunction_t& x, diag::Diagnostics& diagnostics) { + if (x.n_args != 1) { + ASRUtils::require_impl(false, "Unexpected number of args, Present takes 1 arguments, found " + std::to_string(x.n_args), x.base.base.loc, diagnostics); + } + } + + static inline ASR::asr_t* create_Present(Allocator& al, const Location& loc, Vec& args, diag::Diagnostics& diag) { + ASR::expr_t* arg = args[0]; + if (!ASR::is_a(*arg)) { + diag.semantic_error_label( + "Argument to 'present' must be a variable, but got an expression", + {arg->base.loc}, + "Expected a variable here" + ); + + return nullptr; + } + + ASR::symbol_t* sym = ASR::down_cast(arg)->m_v; + ASR::Variable_t* var = ASR::down_cast(sym); + if (var->m_presence != ASR::presenceType::Optional) { + diag.semantic_error_label( + "Argument to 'present' must be an optional dummy argument", + {arg->base.loc}, + "This variable is not 'optional'" + ); + + return nullptr; + } + + ASRUtils::ExprStmtDuplicator expr_duplicator(al); + expr_duplicator.allow_procedure_calls = true; + + ASR::ttype_t* type_ = ASRUtils::TYPE(ASR::make_Logical_t(al, loc, 4)); + ASR::ttype_t *return_type = type_; + ASR::expr_t *m_value = nullptr; + + Vec m_args; m_args.reserve(al, 1); + m_args.push_back(al, args[0]); + + return ASR::make_IntrinsicElementalFunction_t(al, loc, + static_cast(IntrinsicElementalFunctions::Present), + m_args.p, m_args.n, 0, return_type, m_value); + } + + static inline ASR::expr_t* instantiate_Present(Allocator &/*al*/, const Location &/*loc*/, + SymbolTable */*scope*/, Vec& /*arg_types*/, ASR::ttype_t */*return_type*/, + Vec& /*new_args*/, int64_t /*overload_id*/) { return nullptr;} +} + namespace Ble { static ASR::expr_t *eval_Ble(Allocator &al, const Location &loc, @@ -1396,14 +1887,14 @@ namespace Ble { fill_func_arg("x", arg_types[0]); fill_func_arg("y", arg_types[1]); auto result = declare(fn_name, logical, ReturnVar); - body.push_back(al, b.Assignment(result, b.bool32(0))); - body.push_back(al, b.If(b.Or(b.iGt(b.iMul(args[0], args[1]), b.i(0, arg_types[0])), b.And(b.iEq(b.iMul(args[0], args[1]), b.i(0, arg_types[0])), b.Or(b.iGt(args[0], b.i(0, arg_types[0])), b.iGt(args[1], b.i(0, arg_types[0]))))), { - b.If(b.iLtE(args[0], args[1]), { - b.Assignment(result, b.bool32(1)) + body.push_back(al, b.Assignment(result, b.bool_t(0, logical))); + body.push_back(al, b.If(b.Or(b.Gt(b.Mul(args[0], args[1]), b.i_t(0, arg_types[0])), b.And(b.Eq(b.Mul(args[0], args[1]), b.i_t(0, arg_types[0])), b.Or(b.Gt(args[0], b.i_t(0, arg_types[0])), b.Gt(args[1], b.i_t(0, arg_types[0]))))), { + b.If(b.LtE(args[0], args[1]), { + b.Assignment(result, b.bool_t(1, logical)) }, {}) }, { - b.If(b.iGtE(args[0], args[1]), { - b.Assignment(result, b.bool32(1)) + b.If(b.GtE(args[0], args[1]), { + b.Assignment(result, b.bool_t(1, logical)) }, {}) })); @@ -1432,10 +1923,10 @@ namespace Lgt { SymbolTable *scope, Vec& arg_types, ASR::ttype_t *return_type, Vec& new_args, int64_t /*overload_id*/) { declare_basic_variables("_lcompilers_lgt_" + type_to_str_python(type_get_past_allocatable(arg_types[0]))); - fill_func_arg("x", ASRUtils::TYPE(ASR::make_Character_t(al, loc, 1, -1, nullptr))); - fill_func_arg("y", ASRUtils::TYPE(ASR::make_Character_t(al, loc, 1, -1, nullptr))); + fill_func_arg("x", ASRUtils::TYPE(ASR::make_String_t(al, loc, 1, -1, nullptr, ASR::string_physical_typeType::PointerString))); + fill_func_arg("y", ASRUtils::TYPE(ASR::make_String_t(al, loc, 1, -1, nullptr, ASR::string_physical_typeType::PointerString))); auto result = declare(fn_name, return_type, ReturnVar); - body.push_back(al, b.Assignment(result, b.sGt(args[0], args[1]))); + body.push_back(al, b.Assignment(result, b.Gt(args[0], args[1]))); ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); @@ -1462,10 +1953,10 @@ namespace Llt { SymbolTable *scope, Vec& arg_types, ASR::ttype_t *return_type, Vec& new_args, int64_t /*overload_id*/) { declare_basic_variables("_lcompilers_llt_" + type_to_str_python(arg_types[0])); - fill_func_arg("x", ASRUtils::TYPE(ASR::make_Character_t(al, loc, 1, -1, nullptr))); - fill_func_arg("y", ASRUtils::TYPE(ASR::make_Character_t(al, loc, 1, -1, nullptr))); + fill_func_arg("x", ASRUtils::TYPE(ASR::make_String_t(al, loc, 1, -1, nullptr, ASR::string_physical_typeType::PointerString))); + fill_func_arg("y", ASRUtils::TYPE(ASR::make_String_t(al, loc, 1, -1, nullptr, ASR::string_physical_typeType::PointerString))); auto result = declare(fn_name, return_type, ReturnVar); - body.push_back(al, b.Assignment(result, b.sLt(args[0], args[1]))); + body.push_back(al, b.Assignment(result, b.Lt(args[0], args[1]))); ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); @@ -1492,10 +1983,10 @@ namespace Lge { SymbolTable *scope, Vec& arg_types, ASR::ttype_t *return_type, Vec& new_args, int64_t /*overload_id*/) { declare_basic_variables("_lcompilers_lge_" + type_to_str_python(arg_types[0])); - fill_func_arg("x", ASRUtils::TYPE(ASR::make_Character_t(al, loc, 1, -1, nullptr))); - fill_func_arg("y", ASRUtils::TYPE(ASR::make_Character_t(al, loc, 1, -1, nullptr))); + fill_func_arg("x", ASRUtils::TYPE(ASR::make_String_t(al, loc, 1, -1, nullptr, ASR::string_physical_typeType::PointerString))); + fill_func_arg("y", ASRUtils::TYPE(ASR::make_String_t(al, loc, 1, -1, nullptr, ASR::string_physical_typeType::PointerString))); auto result = declare(fn_name, return_type, ReturnVar); - body.push_back(al, b.Assignment(result, b.sGtE(args[0], args[1]))); + body.push_back(al, b.Assignment(result, b.GtE(args[0], args[1]))); ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); @@ -1522,10 +2013,10 @@ namespace Lle { SymbolTable *scope, Vec& arg_types, ASR::ttype_t *return_type, Vec& new_args, int64_t /*overload_id*/) { declare_basic_variables("_lcompilers_lle_" + type_to_str_python(arg_types[0])); - fill_func_arg("x", ASRUtils::TYPE(ASR::make_Character_t(al, loc, 1, -1, nullptr))); - fill_func_arg("y", ASRUtils::TYPE(ASR::make_Character_t(al, loc, 1, -1, nullptr))); + fill_func_arg("x", ASRUtils::TYPE(ASR::make_String_t(al, loc, 1, -1, nullptr, ASR::string_physical_typeType::PointerString))); + fill_func_arg("y", ASRUtils::TYPE(ASR::make_String_t(al, loc, 1, -1, nullptr, ASR::string_physical_typeType::PointerString))); auto result = declare(fn_name, return_type, ReturnVar); - body.push_back(al, b.Assignment(result, b.sLtE(args[0], args[1]))); + body.push_back(al, b.Assignment(result, b.LtE(args[0], args[1]))); ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); @@ -1535,26 +2026,71 @@ namespace Lle { } // namespace Lle -namespace Not { +namespace Int { - static ASR::expr_t *eval_Not(Allocator &al, const Location &loc, - ASR::ttype_t* t1, Vec &args, diag::Diagnostics& /*diag*/) { - int64_t val = ASR::down_cast(args[0])->m_n; - int64_t result = ~val; - return make_ConstantWithType(make_IntegerConstant_t, result, t1, loc); + static ASR::expr_t *eval_Int(Allocator &al, const Location &loc, + ASR::ttype_t* t1, Vec &args, diag::Diagnostics& diag) { + int64_t i = -1; + if (ASR::is_a(*args[0])) { + i = ASR::down_cast(ASRUtils::expr_value(args[0]))->m_n; + return make_ConstantWithType(make_IntegerConstant_t, i, t1, loc); + } else if (ASR::is_a(*args[0])) { + i = ASR::down_cast(ASRUtils::expr_value(args[0]))->m_r; + return make_ConstantWithType(make_IntegerConstant_t, i, t1, loc); + } else if (ASR::is_a(*args[0])) { + i = ASR::down_cast(ASRUtils::expr_value(args[0]))->m_re; + return make_ConstantWithType(make_IntegerConstant_t, i, t1, loc); + } else { + append_error(diag, "Invalid argument to `int` intrinsic", loc); + return nullptr; + } } - static inline ASR::expr_t* instantiate_Not(Allocator &al, const Location &loc, + static inline ASR::expr_t* instantiate_Int(Allocator &al, const Location &loc, SymbolTable *scope, Vec& arg_types, ASR::ttype_t *return_type, Vec& new_args, int64_t /*overload_id*/) { - declare_basic_variables("_lcompilers_not_" + type_to_str_python(arg_types[0])); - fill_func_arg("x", arg_types[0]); + declare_basic_variables("_lcompilers_int_" + type_to_str_python(arg_types[0])); + fill_func_arg("a", arg_types[0]); auto result = declare(fn_name, return_type, ReturnVar); - /* - * r = not(x) + if (is_integer(*arg_types[0])) { + body.push_back(al, b.Assignment(result, b.i2i_t(args[0], return_type))); + } else if (is_real(*arg_types[0])) { + body.push_back(al, b.Assignment(result, b.r2i_t(args[0], return_type))); + } else if (is_complex(*arg_types[0])) { + body.push_back(al, b.Assignment(result, b.c2i_t(args[0], return_type))); + } else { + return nullptr; + } + + ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, + body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); + scope->add_symbol(fn_name, f_sym); + ASR::expr_t* bcall = b.Call(f_sym, new_args, return_type, nullptr); + return bcall; + } + +} // namespace Int + +namespace Not { + + static ASR::expr_t *eval_Not(Allocator &al, const Location &loc, + ASR::ttype_t* t1, Vec &args, diag::Diagnostics& /*diag*/) { + int64_t val = ASR::down_cast(args[0])->m_n; + int64_t result = ~val; + return make_ConstantWithType(make_IntegerConstant_t, result, t1, loc); + } + + static inline ASR::expr_t* instantiate_Not(Allocator &al, const Location &loc, + SymbolTable *scope, Vec& arg_types, ASR::ttype_t *return_type, + Vec& new_args, int64_t /*overload_id*/) { + declare_basic_variables("_lcompilers_not_" + type_to_str_python(arg_types[0])); + fill_func_arg("x", arg_types[0]); + auto result = declare(fn_name, return_type, ReturnVar); + /* + * r = not(x) * r = ~x */ - body.push_back(al, b.Assignment(result, b.i_BitNot(args[0], return_type))); + body.push_back(al, b.Assignment(result, b.Not(args[0]))); ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); @@ -1590,7 +2126,7 @@ namespace Iand { * r = iand(x, y) * r = x & y */ - body.push_back(al, b.Assignment(result, b.i_BitAnd(args[0], args[1], return_type))); + body.push_back(al, b.Assignment(result, b.And(args[0], args[1]))); ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); @@ -1604,6 +2140,46 @@ namespace Iand { } // namespace Iand +namespace And { + + static ASR::expr_t *eval_And(Allocator &al, const Location &loc, + ASR::ttype_t* t1, Vec &args, diag::Diagnostics& /*diag*/) { + if(ASR::is_a(*args[0])){ + int64_t val1 = ASR::down_cast(args[0])->m_n; + int64_t val2 = ASR::down_cast(args[1])->m_n; + int64_t result; + result = val1 & val2; + return make_ConstantWithType(make_IntegerConstant_t, result, t1, loc); + } else { + bool val1 = ASR::down_cast(args[0])->m_value; + bool val2 = ASR::down_cast(args[1])->m_value; + bool result; + result = val1 & val2; + return make_ConstantWithType(make_LogicalConstant_t, result, t1, loc); + } + } + + static inline ASR::expr_t* instantiate_And(Allocator &al, const Location &loc, + SymbolTable *scope, Vec& arg_types, ASR::ttype_t *return_type, + Vec& new_args, int64_t /*overload_id*/) { + declare_basic_variables("_lcompilers_and_" + type_to_str_python(arg_types[0])); + fill_func_arg("x", arg_types[0]); + fill_func_arg("y", arg_types[1]); + auto result = declare(fn_name, return_type, ReturnVar); + /* + * r = and(x, y) + * r = x & y + */ + body.push_back(al, b.Assignment(result, b.And(args[0], args[1]))); + + ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, + body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); + scope->add_symbol(fn_name, f_sym); + return b.Call(f_sym, new_args, return_type, nullptr); + } + +} // namespace And + namespace Ior { static ASR::expr_t *eval_Ior(Allocator &al, const Location &loc, @@ -1626,7 +2202,7 @@ namespace Ior { * r = ior(x, y) * r = x | y */ - body.push_back(al, b.Assignment(result, b.i_BitOr(args[0], args[1], return_type))); + body.push_back(al, b.Assignment(result, b.Or(args[0], args[1]))); ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); @@ -1640,6 +2216,46 @@ namespace Ior { } // namespace Ior +namespace Or { + + static ASR::expr_t *eval_Or(Allocator &al, const Location &loc, + ASR::ttype_t* t1, Vec &args, diag::Diagnostics& /*diag*/) { + if(ASR::is_a(*args[0])){ + int64_t val1 = ASR::down_cast(args[0])->m_n; + int64_t val2 = ASR::down_cast(args[1])->m_n; + int64_t result; + result = val1 | val2; + return make_ConstantWithType(make_IntegerConstant_t, result, t1, loc); + } else { + bool val1 = ASR::down_cast(args[0])->m_value; + bool val2 = ASR::down_cast(args[1])->m_value; + bool result; + result = val1 || val2; + return make_ConstantWithType(make_LogicalConstant_t, result, t1, loc); + } + } + + static inline ASR::expr_t* instantiate_Or(Allocator &al, const Location &loc, + SymbolTable *scope, Vec& arg_types, ASR::ttype_t *return_type, + Vec& new_args, int64_t /*overload_id*/) { + declare_basic_variables("_lcompilers_or_" + type_to_str_python(arg_types[0])); + fill_func_arg("x", arg_types[0]); + fill_func_arg("y", arg_types[1]); + auto result = declare(fn_name, return_type, ReturnVar); + /* + * r = or(x, y) + * r = x | y + */ + body.push_back(al, b.Assignment(result, b.Or(args[0], args[1]))); + + ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, + body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); + scope->add_symbol(fn_name, f_sym); + return b.Call(f_sym, new_args, return_type, nullptr); + } + +} // namespace Or + namespace Ieor { static ASR::expr_t *eval_Ieor(Allocator &al, const Location &loc, @@ -1662,7 +2278,7 @@ namespace Ieor { * r = ieor(x, y) * r = x ^ y */ - body.push_back(al, b.Assignment(result, b.i_BitXor(args[0], args[1], return_type))); + body.push_back(al, b.Assignment(result, b.Xor(args[0], args[1]))); ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); @@ -1672,13 +2288,56 @@ namespace Ieor { } // namespace Ieor +namespace Xor { + + static ASR::expr_t *eval_Xor(Allocator &al, const Location &loc, + ASR::ttype_t* t1, Vec &args, diag::Diagnostics& /*diag*/) { + if(ASR::is_a(*args[0])){ + int64_t val1 = ASR::down_cast(args[0])->m_n; + int64_t val2 = ASR::down_cast(args[1])->m_n; + int64_t result; + result = val1 ^ val2; + return make_ConstantWithType(make_IntegerConstant_t, result, t1, loc); + } else { + bool val1 = ASR::down_cast(args[0])->m_value; + bool val2 = ASR::down_cast(args[1])->m_value; + bool result; + result = val1 ^ val2; + return make_ConstantWithType(make_LogicalConstant_t, result, t1, loc); + } + } + + static inline ASR::expr_t* instantiate_Xor(Allocator &al, const Location &loc, + SymbolTable *scope, Vec& arg_types, ASR::ttype_t *return_type, + Vec& new_args, int64_t /*overload_id*/) { + declare_basic_variables("_lcompilers_xor_" + type_to_str_python(arg_types[0])); + fill_func_arg("x", arg_types[0]); + fill_func_arg("y", arg_types[1]); + auto result = declare(fn_name, return_type, ReturnVar); + /* + * r = xor(x, y) + * r = x ^ y + */ + body.push_back(al, b.Assignment(result, b.Xor(args[0], args[1]))); + + ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, + body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); + scope->add_symbol(fn_name, f_sym); + return b.Call(f_sym, new_args, return_type, nullptr); + } + +} // namespace Xor + namespace Ibclr { static ASR::expr_t *eval_Ibclr(Allocator &al, const Location &loc, - ASR::ttype_t* t1, Vec &args, diag::Diagnostics& /*diag*/) { + ASR::ttype_t* t1, Vec &args, diag::Diagnostics& diag) { int64_t val1 = ASR::down_cast(args[0])->m_n; int64_t val2 = ASR::down_cast(args[1])->m_n; int64_t result; + if ( val2 < 0 ) { + diag.semantic_error_label("`pos` argument of `ibclr` intrinsic must be non-negative", {loc}, ""); + } result = val1 & ~(1 << val2); return make_ConstantWithType(make_IntegerConstant_t, result, t1, loc); } @@ -1694,7 +2353,7 @@ namespace Ibclr { * r = ibclr(x, y) * r = x & ~( 1 << y ) */ - body.push_back(al, b.Assignment(result, b.i_BitAnd(args[0], b.i_BitNot(b.i_BitLshift(b.i(1, arg_types[0]), args[1], return_type), return_type), return_type))); + body.push_back(al, b.Assignment(result, b.And(args[0], b.Not(b.BitLshift(b.i_t(1, arg_types[0]), b.i2i_t(args[1], arg_types[0]), return_type))))); ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); @@ -1707,10 +2366,13 @@ namespace Ibclr { namespace Ibset { static ASR::expr_t *eval_Ibset(Allocator &al, const Location &loc, - ASR::ttype_t* t1, Vec &args, diag::Diagnostics& /*diag*/) { + ASR::ttype_t* t1, Vec &args, diag::Diagnostics& diag) { int64_t val1 = ASR::down_cast(args[0])->m_n; int64_t val2 = ASR::down_cast(args[1])->m_n; int64_t result; + if ( val2 < 0 ) { + diag.semantic_error_label("`pos` argument of `ibset` intrinsic must be non-negative", {loc}, ""); + } result = val1 | (1 << val2); return make_ConstantWithType(make_IntegerConstant_t, result, t1, loc); } @@ -1726,7 +2388,7 @@ namespace Ibset { * r = ibset(x, y) * r = x | ( 1 << y ) */ - body.push_back(al, b.Assignment(result, b.i_BitOr(args[0], b.i_BitLshift(b.i(1, arg_types[0]), args[1], return_type), return_type))); + body.push_back(al, b.Assignment(result, b.Or(args[0], b.BitLshift(b.i_t(1, arg_types[0]), b.i2i_t(args[1], arg_types[0]), return_type)))); ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); @@ -1739,10 +2401,13 @@ namespace Ibset { namespace Btest { static ASR::expr_t *eval_Btest(Allocator &al, const Location &loc, - ASR::ttype_t* t1, Vec &args, diag::Diagnostics& /*diag*/) { + ASR::ttype_t* t1, Vec &args, diag::Diagnostics& diag) { int64_t val1 = ASR::down_cast(args[0])->m_n; int64_t val2 = ASR::down_cast(args[1])->m_n; bool result; + if ( val2 < 0 ) { + diag.semantic_error_label("`pos` argument of `btest` intrinsic must be non-negative", {loc}, ""); + } if ((val1 & (1 << val2)) == 0) result = false; else result = true; return make_ConstantWithType(make_LogicalConstant_t, result, t1, loc); @@ -1759,10 +2424,10 @@ namespace Btest { * r = btest(x, y) * r = (( x & ( 1 << y )) == 0) ? .false. : .true. */ - body.push_back(al, b.If(b.iEq(b.i_BitAnd(args[0], b.i_BitLshift(b.i(1, arg_types[0]), args[1], arg_types[0]), arg_types[0]), b.i(0, arg_types[0])), { - b.Assignment(result, b.bool32(0)) + body.push_back(al, b.If(b.Eq(b.And(args[0], b.BitLshift(b.i_t(1, arg_types[0]), b.i2i_t(args[1], arg_types[0]), arg_types[0])), b.i_t(0, arg_types[0])), { + b.Assignment(result, b.bool_t(0, return_type)) }, { - b.Assignment(result, b.bool32(1)) + b.Assignment(result, b.bool_t(1, return_type)) })); ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, @@ -1776,10 +2441,16 @@ namespace Btest { namespace Ibits { static ASR::expr_t *eval_Ibits(Allocator &al, const Location &loc, - ASR::ttype_t* t1, Vec &args, diag::Diagnostics& /*diag*/) { + ASR::ttype_t* t1, Vec &args, diag::Diagnostics& diag) { int64_t val1 = ASR::down_cast(args[0])->m_n; int64_t val2 = ASR::down_cast(args[1])->m_n; int64_t val3 = ASR::down_cast(args[2])->m_n; + if ( val2 < 0 ) { + diag.semantic_error_label("`pos` argument of `ibits` intrinsic must be non-negative", {loc}, ""); + } + if ( val3 < 0 ) { + diag.semantic_error_label("`len` argument of `ibits` intrinsic must be non-negative", {loc}, ""); + } int64_t result; result = (val1 >> val2) & ((1 << val3) - 1); return make_ConstantWithType(make_IntegerConstant_t, result, t1, loc); @@ -1797,7 +2468,7 @@ namespace Ibits { * r = ibits(x, y, z) * r = ( x >> y ) & ( ( 1 << z ) - 1 ) */ - body.push_back(al, b.Assignment(result, b.i_BitAnd(b.i_BitRshift(args[0], b.i2i(args[1], arg_types[0]), return_type), b.iSub(b.i_BitLshift(b.i(1, arg_types[0]), b.i2i(args[2], arg_types[0]), return_type), b.i(1, arg_types[0])), return_type))); + body.push_back(al, b.Assignment(result, b.And(b.BitRshift(args[0], b.i2i_t(args[1], arg_types[0]), return_type), b.Sub(b.BitLshift(b.i_t(1, arg_types[0]), b.i2i_t(args[2], arg_types[0]), return_type), b.i_t(1, arg_types[0]))))); ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); @@ -1811,9 +2482,9 @@ namespace Aint { static ASR::expr_t *eval_Aint(Allocator &al, const Location &loc, ASR::ttype_t* arg_type, Vec &args, diag::Diagnostics& /*diag*/) { - double rv = ASR::down_cast(expr_value(args[0]))->m_r; + double rv = ASR::down_cast(args[0])->m_r; ASRUtils::ASRBuilder b(al, loc); - return b.f(std::trunc(rv), arg_type); + return b.f_t(std::trunc(rv), arg_type); } static inline ASR::expr_t* instantiate_Aint(Allocator &al, const Location &loc, @@ -1825,7 +2496,7 @@ namespace Aint { // Cast: Real -> Integer -> Real // TODO: this approach doesn't work for numbers > i64_max - body.push_back(al, b.Assignment(result, b.i2r(b.r2i64(args[0]), return_type))); + body.push_back(al, b.Assignment(result, b.i2r_t(b.r2i_t(args[0], int64), return_type))); ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); @@ -1839,9 +2510,9 @@ namespace Anint { static ASR::expr_t *eval_Anint(Allocator &al, const Location &loc, ASR::ttype_t* arg_type, Vec &args, diag::Diagnostics& /*diag*/) { - double rv = ASR::down_cast(expr_value(args[0]))->m_r; + double rv = ASR::down_cast(args[0])->m_r; ASRUtils::ASRBuilder b(al, loc); - return b.f(std::round(rv), arg_type); + return b.f_t(std::round(rv), arg_type); } static inline ASR::expr_t* instantiate_Anint(Allocator &al, const Location &loc, @@ -1857,11 +2528,11 @@ namespace Anint { * r = aint(x-0.5) * end if */ - body.push_back(al, b.If(b.fGt(args[0], b.f(0, arg_types[0])), { - b.Assignment(result, b.CallIntrinsic(scope, {arg_types[0]}, {b.rAdd(args[0], b.f(0.5, arg_types[0]), arg_types[0])}, + body.push_back(al, b.If(b.Gt(args[0], b.f_t(0, arg_types[0])), { + b.Assignment(result, b.CallIntrinsic(scope, {arg_types[0]}, {b.Add(args[0], b.f_t(0.5, arg_types[0]))}, return_type, 0, Aint::instantiate_Aint)) }, { - b.Assignment(result, b.CallIntrinsic(scope, {arg_types[0]}, {b.rSub(args[0], b.f(0.5, arg_types[0]), arg_types[0])}, + b.Assignment(result, b.CallIntrinsic(scope, {arg_types[0]}, {b.Sub(args[0], b.f_t(0.5, arg_types[0]))}, return_type, 0, Aint::instantiate_Aint)) })); @@ -1876,9 +2547,25 @@ namespace Anint { namespace Nint { static ASR::expr_t *eval_Nint(Allocator &al, const Location &loc, - ASR::ttype_t* arg_type, Vec &args, diag::Diagnostics& /*diag*/) { - double rv = ASR::down_cast(expr_value(args[0]))->m_r; + ASR::ttype_t* arg_type, Vec &args, diag::Diagnostics& diag) { + int kind = ASRUtils::extract_kind_from_ttype_t(arg_type); + double rv = ASR::down_cast(args[0])->m_r; double near_integer = std::round(rv); + + if (kind == 4) { + if (near_integer < static_cast(std::numeric_limits::min()) || + near_integer > static_cast(std::numeric_limits::max())) { + diag.semantic_error_label("Result of `nint` overflows its kind(" + std::to_string(kind) + ")", {loc}, ""); + } + } else if (kind == 8) { + if (near_integer < static_cast(std::numeric_limits::min()) || + near_integer > static_cast(std::numeric_limits::max())) { + diag.semantic_error_label("Result of `nint` overflows its kind(" + std::to_string(kind) + ")", {loc}, ""); + } + } else { + diag.semantic_error_label("Unsupported integer kind", {loc}, ""); + } + int64_t result = int64_t(near_integer); return make_ConstantWithType(make_IntegerConstant_t, result, arg_type, loc); } @@ -1893,7 +2580,7 @@ namespace Nint { * r = nint(x) * r = int(anint(x)) */ - body.push_back(al,b.Assignment(result, b.r2i(b.CallIntrinsic(scope, {arg_types[0]}, {args[0]}, arg_types[0], 0, Anint::instantiate_Anint), return_type))); + body.push_back(al,b.Assignment(result, b.r2i_t(b.CallIntrinsic(scope, {arg_types[0]}, {args[0]}, arg_types[0], 0, Anint::instantiate_Anint), return_type))); ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); @@ -1902,6 +2589,70 @@ namespace Nint { } } // namespace Nint +namespace Idnint { + + static ASR::expr_t *eval_Idnint(Allocator &al, const Location &loc, + ASR::ttype_t* arg_type, Vec &args, diag::Diagnostics& diag) { + if (ASRUtils::extract_kind_from_ttype_t(expr_type(args[0])) != 8 ) { + diag.semantic_error_label("`idnint` takes argument of kind 8", {loc}, ""); + } + double rv = ASR::down_cast(args[0])->m_r; + double near_integer = std::round(rv); + + if (near_integer < static_cast(std::numeric_limits::min()) || + near_integer > static_cast(std::numeric_limits::max())) { + diag.semantic_error_label("Result of `idnint` overflows its kind 4", {loc}, ""); + } + + int32_t result = int32_t(near_integer); + return make_ConstantWithType(make_IntegerConstant_t, result, arg_type, loc); + } + + static inline ASR::expr_t* instantiate_Idnint(Allocator &al, const Location &loc, + SymbolTable *scope, Vec& arg_types, ASR::ttype_t *return_type, + Vec& new_args, int64_t /*overload_id*/) { + declare_basic_variables("_lcompilers_idnint_" + type_to_str_python(arg_types[0])); + fill_func_arg("x", arg_types[0]); + auto result = declare(fn_name, return_type, ReturnVar); + if (ASRUtils::extract_kind_from_ttype_t(arg_types[0]) != 8) { + throw LCompilersException("argument of `idnint` must have kind equals to 8"); + return nullptr; + } + /* + * r = idnint(x) + * r = int(anint(x)) + */ + body.push_back(al,b.Assignment(result, b.r2i_t(b.CallIntrinsic(scope, {arg_types[0]}, {args[0]}, arg_types[0], 0, Anint::instantiate_Anint), return_type))); + + ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, + body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); + scope->add_symbol(fn_name, f_sym); + return b.Call(f_sym, new_args, return_type, nullptr); + } +} // namespace Idnint + +namespace Logical { + + static ASR::expr_t *eval_Logical(Allocator &al, const Location &loc, + ASR::ttype_t* arg_type, Vec &args, diag::Diagnostics& /*diag*/) { + bool result = ASR::down_cast(args[0])->m_value; + return make_ConstantWithType(make_LogicalConstant_t, result, arg_type, loc); + } + + static inline ASR::expr_t* instantiate_Logical(Allocator &al, const Location &loc, + SymbolTable *scope, Vec& arg_types, ASR::ttype_t *return_type, + Vec& new_args, int64_t /*overload_id*/) { + declare_basic_variables("_lcompilers_logical_" + type_to_str_python(arg_types[0])); + fill_func_arg("x", arg_types[0]); + auto result = declare(fn_name, return_type, ReturnVar); + body.push_back(al,b.Assignment(result, b.bool_t(args[0], return_type))); + + ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, + body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); + scope->add_symbol(fn_name, f_sym); + return b.Call(f_sym, new_args, return_type, nullptr); + } +} // namespace Logical namespace Floor { @@ -1928,10 +2679,10 @@ namespace Floor { * r = int(x) - 1 * } */ - body.push_back(al, b.Assignment(result, b.r2i(args[0], return_type))); - body.push_back(al, b.If(b.And(b.fLtE(args[0], b.f(0, arg_types[0])), b.fNotEq(b.i2r(b.r2i(args[0], return_type), return_type), b.r2r(args[0], return_type))), + body.push_back(al, b.Assignment(result, b.r2i_t(args[0], return_type))); + body.push_back(al, b.If(b.And(b.LtE(args[0], b.f_t(0, arg_types[0])), b.NotEq(b.i2r_t(b.r2i_t(args[0], return_type), arg_types[0]), args[0])), { - b.Assignment(result, b.i_tSub(b.r2i(args[0], return_type), b.i(1, return_type), return_type)) + b.Assignment(result, b.Sub(b.r2i_t(args[0], return_type), b.i_t(1, return_type))) }, {})); ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); @@ -1939,6 +2690,9 @@ namespace Floor { return b.Call(f_sym, new_args, return_type, nullptr); } + static inline ASR::expr_t* FLOOR(ASRBuilder &b, ASR::expr_t* x, ASR::ttype_t* t, SymbolTable* scope) { + return b.CallIntrinsic(scope, {expr_type(x)}, {x}, t, 0, Floor::instantiate_Floor); + } } // namespace Floor @@ -1977,18 +2731,18 @@ namespace Ceiling { * r = int(x) * } */ - body.push_back(al, b.If(b.fGtE(args[0], b.f(0, arg_types[0])), + body.push_back(al, b.If(b.GtE(args[0], b.f_t(0, arg_types[0])), { - b.If(b.fEq(b.r2r(args[0], return_type), - b.i2r(b.r2i(args[0], return_type), return_type) + b.If(b.Eq(args[0], + b.i2r_t(b.r2i_t(args[0], return_type), arg_types[0]) ), { - b.Assignment(result, b.r2i(args[0], return_type)) + b.Assignment(result, b.r2i_t(args[0], return_type)) }, { - b.Assignment(result, b.i_tAdd(b.r2i(args[0], return_type), b.i(1, return_type), return_type)) + b.Assignment(result, b.Add(b.r2i_t(args[0], return_type), b.i_t(1, return_type))) }) }, { - b.Assignment(result, b.r2i(args[0], return_type)) + b.Assignment(result, b.r2i_t(args[0], return_type)) })); ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); @@ -2043,16 +2797,16 @@ namespace Dim { * } */ if (is_real(*arg_types[0])) { - body.push_back(al, b.If(b.fGt(args[0], args[1]), { - b.Assignment(result, b.r_tSub(args[0], args[1], arg_types[0])) + body.push_back(al, b.If(b.Gt(args[0], b.r2r_t(args[1], arg_types[0])), { + b.Assignment(result, b.Sub(args[0], b.r2r_t(args[1], arg_types[0]))) }, { - b.Assignment(result, b.f(0.0, arg_types[0])) + b.Assignment(result, b.f_t(0.0, arg_types[0])) })); } else { - body.push_back(al, b.If(b.iGt(args[0], args[1]), { - b.Assignment(result, b.i_tSub(args[0], args[1], arg_types[0])) + body.push_back(al, b.If(b.Gt(args[0], b.i2i_t(args[1], arg_types[0])), { + b.Assignment(result, b.Sub(args[0], b.i2i_t(args[1], arg_types[0]))) }, { - b.Assignment(result, b.i(0, arg_types[0])) + b.Assignment(result, b.i_t(0, arg_types[0])) })); } @@ -2068,11 +2822,15 @@ namespace Dim { namespace Sqrt { static ASR::expr_t *eval_Sqrt(Allocator &al, const Location &loc, - ASR::ttype_t* arg_type, Vec &args, diag::Diagnostics& /*diag*/) { + ASR::ttype_t* arg_type, Vec &args, diag::Diagnostics& diag) { ASRUtils::ASRBuilder b(al, loc); if (is_real(*arg_type)) { - double val = ASR::down_cast(expr_value(args[0]))->m_r; - return b.f(std::sqrt(val), arg_type); + double val = ASR::down_cast(args[0])->m_r; + if (val < 0.0) { + append_error(diag, "Argument of `sqrt` has a negative argument", loc); + return nullptr; + } + return b.f_t(std::sqrt(val), arg_type); } else { std::complex crv; if( ASRUtils::extract_value(args[0], crv) ) { @@ -2147,18 +2905,18 @@ namespace Exponent { end if */ if (kind == 8) { - body.push_back(al, b.If(b.fEq(args[0], b.f(0.0, arg_types[0])), { + body.push_back(al, b.If(b.Eq(args[0], b.f_t(0.0, arg_types[0])), { b.Assignment(result, b.i32(0)) }, { - b.Assignment(result, b.i2i32(b.i_tSub(b.i_tAnd(b.i_BitRshift(ASRUtils::EXPR(ASR::make_BitCast_t(al, loc, args[0], b.i64(0), nullptr, int64, nullptr)), - b.i64(52), int64), b.i64(0x7FF), int64), b.i64(1022), int64))) + b.Assignment(result, b.i2i_t(b.Sub(b.And(b.BitRshift(ASRUtils::EXPR(ASR::make_BitCast_t(al, loc, args[0], b.i64(0), nullptr, int64, nullptr)), + b.i64(52), int64), b.i64(0x7FF)), b.i64(1022)), int32)) })); } else { - body.push_back(al, b.If(b.fEq(args[0], b.f(0.0, arg_types[0])), { + body.push_back(al, b.If(b.Eq(args[0], b.f_t(0.0, arg_types[0])), { b.Assignment(result, b.i32(0)) }, { - b.Assignment(result, b.i_tSub(b.i_tAnd(b.i_BitRshift(ASRUtils::EXPR(ASR::make_BitCast_t(al, loc, args[0], b.i32(0), nullptr, int32, nullptr)), - b.i32(23), int32), b.i32(0x0FF), int32), b.i32(126), int32)) + b.Assignment(result, b.Sub(b.And(b.BitRshift(ASRUtils::EXPR(ASR::make_BitCast_t(al, loc, args[0], b.i32(0), nullptr, int32, nullptr)), + b.i32(23), int32), b.i32(0x0FF)), b.i32(126))) })); } @@ -2220,7 +2978,7 @@ namespace Fraction { * r = x * radix(x)**(-exp(x)) */ ASR::expr_t* func_call_exponent = b.CallIntrinsic(scope, {arg_types[0]}, {args[0]}, int32, 0, Exponent::instantiate_Exponent); - body.push_back(al, b.Assignment(result, b.r_tMul(args[0], b.rPow(b.i2r(b.i(2, int32),return_type), b.r_tMul(b.i2r(b.i(-1,int32), return_type),b.i2r(func_call_exponent, return_type), return_type), return_type), return_type))); + body.push_back(al, b.Assignment(result, b.Mul(args[0], b.Pow(b.i2r_t(b.i32(2),return_type), b.Mul(b.i2r_t(b.i32(-1), return_type),b.i2r_t(func_call_exponent, return_type)))))); ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); scope->add_symbol(fn_name, f_sym); return b.Call(f_sym, new_args, return_type, nullptr); @@ -2284,7 +3042,7 @@ namespace SetExponent { * r = fraction(x) * radix(x)**(I) */ ASR::expr_t* func_call_fraction = b.CallIntrinsic(scope, {arg_types[0]}, {args[0]}, return_type, 0, Fraction::instantiate_Fraction); - body.push_back(al, b.Assignment(result, b.r_tMul(func_call_fraction, b.rPow(b.i2r(b.i32(2),return_type),b.i2r(args[1], return_type), return_type), return_type))); + body.push_back(al, b.Assignment(result, b.Mul(func_call_fraction, b.Pow(b.i2r_t(b.i32(2),return_type),b.i2r_t(args[1], return_type))))); ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); scope->add_symbol(fn_name, f_sym); return b.Call(f_sym, new_args, return_type, nullptr); @@ -2297,7 +3055,7 @@ namespace Sngl { ASR::ttype_t* arg_type, Vec &args, diag::Diagnostics& /*diag*/) { ASRUtils::ASRBuilder b(al, loc); double val = ASR::down_cast(expr_value(args[0]))->m_r; - return b.f(val, arg_type); + return b.f_t(val, arg_type); } static inline ASR::expr_t* instantiate_Sngl(Allocator &al, const Location &loc, @@ -2306,7 +3064,7 @@ namespace Sngl { declare_basic_variables("_lcompilers_sngl_" + type_to_str_python(arg_types[0])); fill_func_arg("a", arg_types[0]); auto result = declare(fn_name, return_type, ReturnVar); - body.push_back(al, b.Assignment(result, b.r2r32(args[0]))); + body.push_back(al, b.Assignment(result, b.r2r_t(args[0], real32))); ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); @@ -2319,18 +3077,26 @@ namespace Sngl { namespace Ifix { static ASR::expr_t *eval_Ifix(Allocator &al, const Location &loc, - ASR::ttype_t* /*arg_type*/, Vec &args, diag::Diagnostics& /*diag*/) { + ASR::ttype_t* /*arg_type*/, Vec &args, diag::Diagnostics& diag) { int val = ASR::down_cast(expr_value(args[0]))->m_r; - return make_ConstantWithType(make_IntegerConstant_t, val, ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)), loc); + if (ASRUtils::extract_kind_from_ttype_t(expr_type(args[0])) != 4) { + append_error(diag, "first argument of `ifix` must have kind equals to 4", loc); + return nullptr; + } + return make_ConstantWithType(make_IntegerConstant_t, val, int32, loc); } static inline ASR::expr_t* instantiate_Ifix(Allocator &al, const Location &loc, SymbolTable *scope, Vec& arg_types, ASR::ttype_t *return_type, Vec& new_args, int64_t /*overload_id*/) { declare_basic_variables("_lcompilers_ifix_" + type_to_str_python(arg_types[0])); + if (ASRUtils::extract_kind_from_ttype_t(arg_types[0]) != 4) { + throw LCompilersException("first argument of `ifix` must have kind equals to 4"); + return nullptr; + } fill_func_arg("a", arg_types[0]); auto result = declare(fn_name, return_type, ReturnVar); - body.push_back(al, b.Assignment(result, b.r2i32(args[0]))); + body.push_back(al, b.Assignment(result, b.r2i_t(args[0], int32))); ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); @@ -2343,9 +3109,14 @@ namespace Ifix { namespace Idint { static ASR::expr_t *eval_Idint(Allocator &al, const Location &loc, - ASR::ttype_t* /*arg_type*/, Vec &args, diag::Diagnostics& /*diag*/) { + ASR::ttype_t* /*arg_type*/, Vec &args, diag::Diagnostics& diag) { int val = ASR::down_cast(expr_value(args[0]))->m_r; - return make_ConstantWithType(make_IntegerConstant_t, val, ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)), loc); + int kind = ASRUtils::extract_kind_from_ttype_t(expr_type(args[0])); + if(kind == 4) { + append_error(diag, "first argument of `idint` must have kind equals to 8", loc); + return nullptr; + } + return make_ConstantWithType(make_IntegerConstant_t, val, int32, loc); } static inline ASR::expr_t* instantiate_Idint(Allocator &al, const Location &loc, @@ -2354,7 +3125,13 @@ namespace Idint { declare_basic_variables("_lcompilers_idint_" + type_to_str_python(arg_types[0])); fill_func_arg("a", arg_types[0]); auto result = declare(fn_name, return_type, ReturnVar); - body.push_back(al, b.Assignment(result, b.r2i32(args[0]))); + + int kind = ASRUtils::extract_kind_from_ttype_t(arg_types[0]); + if(kind == 4) { + throw LCompilersException("first argument of `idint` must have kind equals to 8"); + return nullptr; + } + body.push_back(al, b.Assignment(result, b.r2i_t(args[0], int32))); ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); @@ -2386,7 +3163,7 @@ namespace FMA { * result = a + b*c */ body.push_back(al, b.Assignment(result, - b.ElementalAdd(args[0], b.ElementalMul(args[1], args[2], loc), loc))); + b.Add(args[0], b.Mul(args[1], args[2])))); ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); @@ -2428,14 +3205,14 @@ namespace SignFromValue { end function */ if (is_real(*arg_types[0])) { - body.push_back(al, b.If(b.fLt(args[1], b.f(0.0, arg_types[1])), { - b.Assignment(result, b.f32_neg(args[0], arg_types[0])) + body.push_back(al, b.If(b.Lt(args[1], b.f_t(0.0, arg_types[1])), { + b.Assignment(result, b.f_neg(args[0], arg_types[0])) }, { b.Assignment(result, args[0]) })); } else { - body.push_back(al, b.If(b.iLt(args[1], b.i(0, arg_types[1])), { - b.Assignment(result, b.i32_neg(args[0], arg_types[0])) + body.push_back(al, b.If(b.Lt(args[1], b.i_t(0, arg_types[1])), { + b.Assignment(result, b.i_neg(args[0], arg_types[0])) }, { b.Assignment(result, args[0]) })); @@ -2477,8 +3254,8 @@ namespace FlipSign { end subroutine */ - body.push_back(al, b.If(b.iEq(b.iSub(args[0], b.iMul(b.i(2, arg_types[0]), b.iDiv(args[0], b.i(2, arg_types[0])))), b.i(1, arg_types[0])), { - b.Assignment(result, b.f32_neg(args[1], arg_types[1])) + body.push_back(al, b.If(b.Eq(b.Sub(args[0], b.Mul(b.i_t(2, arg_types[0]), b.Div(args[0], b.i_t(2, arg_types[0])))), b.i_t(1, arg_types[0])), { + b.Assignment(result, b.f_neg(args[1], arg_types[1])) }, { b.Assignment(result, args[1]) })); @@ -2570,11 +3347,11 @@ namespace FloorDiv { result = i32(tmp) return result */ - body.push_back(al, b.Assignment(r, b.r64Div(CastingUtil::perform_casting(args[0], real64, al, loc), + body.push_back(al, b.Assignment(r, b.Div(CastingUtil::perform_casting(args[0], real64, al, loc), CastingUtil::perform_casting(args[1], real64, al, loc)))); - body.push_back(al, b.Assignment(tmp, b.r2i64(r))); - body.push_back(al, b.If(b.And(b.fLt(r, b.f(0.0, real64)), b.fNotEq(b.i2r64(tmp), r)), { - b.Assignment(tmp, b.i64Sub(tmp, b.i(1, int64))) + body.push_back(al, b.Assignment(tmp, b.r2i_t(r, int64))); + body.push_back(al, b.If(b.And(b.Lt(r, b.f_t(0.0, real64)), b.NotEq(b.i2r_t(tmp, real64), r)), { + b.Assignment(tmp, b.Sub(tmp, b.i64(1))) }, {})); body.push_back(al, b.Assignment(result, CastingUtil::perform_casting(tmp, return_type, al, loc))); ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, @@ -2622,24 +3399,24 @@ namespace Mod { end function */ int kind = ASRUtils::extract_kind_from_ttype_t(arg_types[1]); + int kind2 = ASRUtils::extract_kind_from_ttype_t(arg_types[0]); + int upper_kind = std::max(kind, kind2); if (is_real(*arg_types[1])) { - if (kind == 4) { - body.push_back(al, b.Assignment(result, b.r32Sub(args[0], b.r32Mul(args[1], b.i2r32(b.r2i32(b.r32Div(args[0], args[1]))))))); + ASR::ttype_t* new_type = ASRUtils::TYPE(ASR::make_Real_t(al, loc, upper_kind)); + ASR::expr_t* arg0 = b.r2r_t(args[0], new_type); + ASR::expr_t* arg1 = b.r2r_t(args[1], new_type); + + if (upper_kind == 4) { + body.push_back(al, b.Assignment(result, b.Sub(arg0, b.Mul(arg1, b.i2r_t(b.r2i_t(b.Div(arg0, arg1), real32), real32))))); } else { - body.push_back(al, b.Assignment(result, b.r64Sub(args[0], b.r64Mul(args[1], b.i2r64(b.r2i64(b.r64Div(args[0], args[1]))))))); + body.push_back(al, b.Assignment(result, b.Sub(arg0, b.Mul(arg1, b.i2r_t(b.r2i_t(b.Div(arg0, arg1), real64), real64))))); } } else { - if (kind == 1) { - body.push_back(al, b.Assignment(result, b.i8Sub(args[0], b.i8Mul(args[1], b.i8Div(args[0], args[1]))))); - } else if (kind == 2) { - body.push_back(al, b.Assignment(result, b.i16Sub(args[0], b.i16Mul(args[1], b.i16Div(args[0], args[1]))))); - } else if (kind == 4) { - body.push_back(al, b.Assignment(result, b.iSub(args[0], b.iMul(args[1], b.iDiv(args[0], args[1]))))); - } else if (kind == 8) { - body.push_back(al, b.Assignment(result, b.i64Sub(args[0], b.i64Mul(args[1], b.i64Div(args[0], args[1]))))); - } else { - LCOMPILERS_ASSERT(false); - } + ASR::ttype_t* new_type = ASRUtils::TYPE(ASR::make_Integer_t(al, loc, upper_kind)); + ASR::expr_t* arg0 = b.i2i_t(args[0], new_type); + ASR::expr_t* arg1 = b.i2i_t(args[1], new_type); + + body.push_back(al, b.Assignment(result, b.Sub(arg0, b.Mul(arg1, b.Div(arg0, arg1))))); } ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, @@ -2716,22 +3493,22 @@ namespace Popcnt { r = count end function popcnt */ - body.push_back(al, b.Assignment(count, b.i(0,arg_types[0]))); + body.push_back(al, b.Assignment(count, b.i_t(0,arg_types[0]))); body.push_back(al, b.Assignment(val, args[0])); - body.push_back(al, b.Assignment(mask, b.i(1,arg_types[0]))); - body.push_back(al, b.If(b.iGtE(args[0], b.i(0,arg_types[0])), { - b.While(b.iNotEq(val, b.i(0, arg_types[0])), { - b.Assignment(count, b.i_tAdd(count, Mod::MOD(b, val, b.i(2, arg_types[0]), scope), arg_types[0])), - b.Assignment(val, b.i_tDiv(val, b.i(2, arg_types[0]), arg_types[0])) + body.push_back(al, b.Assignment(mask, b.i_t(1,arg_types[0]))); + body.push_back(al, b.If(b.GtE(args[0], b.i_t(0,arg_types[0])), { + b.While(b.NotEq(val, b.i_t(0, arg_types[0])), { + b.Assignment(count, b.Add(count, Mod::MOD(b, val, b.i_t(2, arg_types[0]), scope))), + b.Assignment(val, b.Div(val, b.i_t(2, arg_types[0]))) }) }, { - b.While(b.iNotEq(mask, b.i(0, arg_types[0])), { - b.If(b.iNotEq(b.i(0,arg_types[0]), (b.i_BitAnd(val,mask, arg_types[0]))), {b.Assignment(count, b.i_tAdd(count, b.i(1, arg_types[0]), arg_types[0]))}, + b.While(b.NotEq(mask, b.i_t(0, arg_types[0])), { + b.If(b.NotEq(b.i_t(0,arg_types[0]), (b.And(val,mask))), {b.Assignment(count, b.Add(count, b.i_t(1, arg_types[0])))}, {}), - b.Assignment(mask, b.i_BitLshift(mask, b.i(1, arg_types[0]), arg_types[0])) + b.Assignment(mask, b.BitLshift(mask, b.i_t(1, arg_types[0]), arg_types[0])) }) })); - body.push_back(al, b.Assignment(result, b.i2i(count, return_type))); + body.push_back(al, b.Assignment(result, b.i2i_t(count, return_type))); ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); scope->add_symbol(fn_name, f_sym); return b.Call(f_sym, new_args, return_type, nullptr); @@ -2743,16 +3520,24 @@ namespace Popcnt { namespace Maskl { static ASR::expr_t* eval_Maskl(Allocator& al, const Location& loc, - ASR::ttype_t* t1, Vec& args, diag::Diagnostics& /*diag*/) { + ASR::ttype_t* t1, Vec& args, diag::Diagnostics& diag) { int32_t kind = ASRUtils::extract_kind_from_ttype_t(t1); int64_t i = ASR::down_cast(args[0])->m_n; - if (((kind == 4) && i > 32) || (kind == 8 && i > 64) || i < 0) { - return nullptr; + if ((kind == 4 && i > 32) || (kind == 8 && i > 64)) { + diag.semantic_error_label(" first argument of `maskl` must be less than or equal to the BIT_SIZE of INTEGER(KIND=" + + std::to_string(kind) + ")", {loc}, ""); + return nullptr; + } else if (i < 0) { + diag.semantic_error_label("first argument of `maskl` must be nonnegative", {loc}, ""); + return nullptr; } else { - int64_t one = 1; - int64_t minus_one = -1; - int64_t sixty_four = 64; - int64_t result = (i == 64) ? minus_one : ((one << i) - one) << (sixty_four - i); + int64_t bit_size = (kind == 4) ? 32 : 64; + int64_t result; + if (i == 0) { + result = 0; + } else { + result = (i == bit_size) ? -1 : ((~0ULL) << (bit_size - i)); + } return make_ConstantWithType(make_IntegerConstant_t, result, t1, loc); } } @@ -2760,18 +3545,18 @@ namespace Maskl { static inline ASR::expr_t* instantiate_Maskl(Allocator &al, const Location &loc, SymbolTable *scope, Vec& arg_types, ASR::ttype_t *return_type, Vec& new_args, int64_t /*overload_id*/) { - declare_basic_variables(""); + declare_basic_variables("_lcompilers_maskl_" + type_to_str_python(arg_types[0])); fill_func_arg("x", arg_types[0]); auto result = declare(fn_name, return_type, ReturnVar); /* * r = Maskl(x) * r = (x == 64) ? -1 : ((1 << x) - 1) << (64 - x) */ - body.push_back(al, b.If((b.iEq(b.i2i(args[0], return_type), b.i(64, return_type))), { - b.Assignment(result, b.i(-1, return_type)) + body.push_back(al, b.If((b.Eq(b.i2i_t(args[0], return_type), b.i_t(64, return_type))), { + b.Assignment(result, b.i_t(-1, return_type)) }, { - b.Assignment(result, b.i_BitLshift(b.i_tSub(b.i_BitLshift(b.i(1, return_type), b.i2i(args[0], return_type), return_type), b.i(1, return_type), return_type), - b.i_tSub(b.i(64, return_type), b.i2i(args[0], return_type), return_type), return_type)) + b.Assignment(result, b.BitLshift(b.Sub(b.BitLshift(b.i_t(1, return_type), b.i2i_t(args[0], return_type), return_type), b.i_t(1, return_type)), + b.Sub(b.i_t(64, return_type), b.i2i_t(args[0], return_type)), return_type)) })); ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); scope->add_symbol(fn_name, f_sym); @@ -2782,11 +3567,16 @@ namespace Maskl { namespace Maskr { static ASR::expr_t* eval_Maskr(Allocator& al, const Location& loc, - ASR::ttype_t* t1, Vec& args, diag::Diagnostics& /*diag*/) { + ASR::ttype_t* t1, Vec& args, diag::Diagnostics& diag) { int32_t kind = ASRUtils::extract_kind_from_ttype_t(t1); int64_t i = ASR::down_cast(args[0])->m_n; - if (((kind == 4) && i > 32) || (kind == 8 && i > 64) || i < 0) { - return nullptr; + if (((kind == 4) && i > 32) || (kind == 8 && i > 64)) { + diag.semantic_error_label("first argument of `maskr` must be less than or equal to the BIT_SIZE of INTEGER(KIND=" + + std::to_string(kind) + ")", {loc}, ""); + return nullptr; + } else if (i < 0) { + diag.semantic_error_label("first argument of `maskr` must be nonnegative", {loc}, ""); + return nullptr; } if(i == 64){ return make_ConstantWithType(make_IntegerConstant_t, -1, t1, loc); @@ -2799,17 +3589,17 @@ namespace Maskr { static inline ASR::expr_t* instantiate_Maskr(Allocator &al, const Location &loc, SymbolTable *scope, Vec& arg_types, ASR::ttype_t *return_type, Vec& new_args, int64_t /*overload_id*/) { - declare_basic_variables(""); + declare_basic_variables("_lcompilers_maskr_" + type_to_str_python(arg_types[0])); fill_func_arg("x", arg_types[0]); auto result = declare(fn_name, return_type, ReturnVar); /* * r = Maskr(x) * r = (1 << x) - 1 */ - body.push_back(al, b.If((b.iEq(b.i2i(args[0], return_type), b.i(64, return_type))), { - b.Assignment(result, b.i(-1, return_type)) + body.push_back(al, b.If((b.Eq(b.i2i_t(args[0], return_type), b.i_t(64, return_type))), { + b.Assignment(result, b.i_t(-1, return_type)) }, { - b.Assignment(result, b.i_tSub(b.i_BitLshift(b.i(1, return_type), b.i2i(args[0], return_type), return_type), b.i(1, return_type), return_type)) + b.Assignment(result, b.Sub(b.BitLshift(b.i_t(1, return_type), b.i2i_t(args[0], return_type), return_type), b.i_t(1, return_type))) })); ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); scope->add_symbol(fn_name, f_sym); @@ -2818,6 +3608,114 @@ namespace Maskr { } // namespace Maskr +namespace Merge { + + static inline ASR::expr_t* eval_Merge(Allocator &, const Location &, + ASR::ttype_t *, Vec& args, diag::Diagnostics &) { + bool mask = ASR::down_cast(args[2])->m_value; + ASR::expr_t *tsource = args[0], *fsource = args[1]; + if (mask) { + return tsource; + } else { + return fsource; + } + } + + static inline ASR::expr_t* instantiate_Merge(Allocator &al, + const Location &loc, SymbolTable *scope, + Vec& arg_types, ASR::ttype_t *return_type, + Vec& new_args, int64_t /*overload_id*/) { + ASR::ttype_t *tsource_type = nullptr, *fsource_type = nullptr, *mask_type = nullptr; + tsource_type = ASRUtils::duplicate_type(al, + ASRUtils::extract_type(arg_types[0])); + fsource_type = ASRUtils::duplicate_type(al, + ASRUtils::extract_type(arg_types[1])); + mask_type = ASRUtils::duplicate_type(al, + ASRUtils::extract_type(arg_types[2])); + if( ASR::is_a(*tsource_type) ) { + ASR::String_t* tsource_char = ASR::down_cast(tsource_type); + ASR::String_t* fsource_char = ASR::down_cast(fsource_type); + tsource_char->m_len_expr = nullptr; fsource_char->m_len_expr = nullptr; + tsource_char->m_len = -2; fsource_char->m_len = -2; + ASR::String_t* return_char = ASR::down_cast( + ASRUtils::type_get_past_allocatable(return_type)); + return_char->m_len = -2; return_char->m_len_expr = nullptr; + + } + std::string new_name = "_lcompilers_merge_" + get_type_code(tsource_type); + + declare_basic_variables(new_name); + if (scope->get_symbol(new_name)) { + ASR::symbol_t *s = scope->get_symbol(new_name); + ASR::Function_t *f = ASR::down_cast(s); + return b.Call(s, new_args, expr_type(f->m_return_var), nullptr); + } + + auto tsource_arg = declare("tsource", tsource_type, In); + args.push_back(al, tsource_arg); + auto fsource_arg = declare("fsource", fsource_type, In); + args.push_back(al, fsource_arg); + auto mask_arg = declare("mask", mask_type, In); + args.push_back(al, mask_arg); + // TODO: In case of String type, set len of ReturnVar to len(tsource) expression + auto result = declare("merge", type_get_past_allocatable(return_type), ReturnVar); + + { + Vec if_body; if_body.reserve(al, 1); + if_body.push_back(al, b.Assignment(result, tsource_arg)); + Vec else_body; else_body.reserve(al, 1); + else_body.push_back(al, b.Assignment(result, fsource_arg)); + body.push_back(al, STMT(ASR::make_If_t(al, loc, mask_arg, + if_body.p, if_body.n, else_body.p, else_body.n))); + } + + ASR::symbol_t *new_symbol = make_ASR_Function_t(fn_name, fn_symtab, dep, args, + body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); + scope->add_symbol(fn_name, new_symbol); + return b.Call(new_symbol, new_args, return_type, nullptr); + } + +} // namespace Merge + +namespace Spacing { + + static ASR::expr_t *eval_Spacing(Allocator &al, const Location &loc, + ASR::ttype_t* t1, Vec &args, diag::Diagnostics& /*diag*/) { + int64_t kind = ASRUtils::extract_kind_from_ttype_t(ASRUtils::expr_type(args[0])); + if (kind == 4) { + float x = ASR::down_cast(args[0])->m_r; + float result = std::fabs(std::nextafterf(x, std::numeric_limits::infinity()) - x); + return make_ConstantWithType(make_RealConstant_t, result, t1, loc); + } else { + double x = ASR::down_cast(args[0])->m_r; + double result = std::fabs(std::nextafter(x, std::numeric_limits::infinity()) - x); + return make_ConstantWithType(make_RealConstant_t, result, t1, loc); + } + } + + static inline ASR::expr_t* instantiate_Spacing(Allocator &al, const Location &loc, + SymbolTable *scope, Vec& arg_types, ASR::ttype_t *return_type, + Vec& new_args, int64_t /*overload_id*/) { + declare_basic_variables("_lcompilers_spacing_" + type_to_str_python(arg_types[0])); + fill_func_arg("x", arg_types[0]); + auto result = declare(fn_name, arg_types[0], ReturnVar); + /* + function spacing(x) result(result) + real :: x + real :: result + result = abs(nextafter(x, infinity) - x) + end function + */ + throw LCompilersException("`Spacing` intrinsic is not yet implemented for runtime values"); + + ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, + body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); + scope->add_symbol(fn_name, f_sym); + return b.Call(f_sym, new_args, return_type, nullptr); + } + +} // namespace Spacing + namespace Trailz { static ASR::expr_t *eval_Trailz(Allocator &al, const Location &loc, @@ -2825,14 +3723,17 @@ namespace Trailz { int64_t a = ASR::down_cast(args[0])->m_n; int64_t kind = ASRUtils::extract_kind_from_ttype_t(t1); int64_t trailing_zeros = ASRUtils::compute_trailing_zeros(a, kind); + set_kind_to_ttype_t(t1, 4); return make_ConstantWithType(make_IntegerConstant_t, trailing_zeros, t1, loc); } static inline ASR::expr_t* instantiate_Trailz(Allocator &al, const Location &loc, SymbolTable *scope, Vec& arg_types, ASR::ttype_t *return_type, Vec& new_args, int64_t /*overload_id*/) { - declare_basic_variables("_lcompilers_optimization_trailz_" + type_to_str_python(arg_types[0])); + declare_basic_variables("_lcompilers_trailz_" + type_to_str_python(arg_types[0])); fill_func_arg("n", arg_types[0]); + ASR::expr_t* n_val = declare("n_val", arg_types[0], Local); + body.push_back(al, b.Assignment(n_val, args[0])); auto result = declare(fn_name, arg_types[0], ReturnVar); // This is not the most efficient way to do this, but it works for now. /* @@ -2856,16 +3757,16 @@ namespace Trailz { end if end function */ - body.push_back(al, b.Assignment(result, b.i(0, arg_types[0]))); - body.push_back(al, b.If(b.iEq(args[0], b.i(0, arg_types[0])), { - b.Assignment(result, b.i(8*ASRUtils::extract_kind_from_ttype_t(arg_types[0]), arg_types[0])) + body.push_back(al, b.Assignment(result, b.i_t(0, arg_types[0]))); + body.push_back(al, b.If(b.Eq(n_val, b.i_t(0, arg_types[0])), { + b.Assignment(result, b.i_t(8*ASRUtils::extract_kind_from_ttype_t(arg_types[0]), arg_types[0])) }, { - b.While(b.iEq(b.CallIntrinsic(scope, {arg_types[0], arg_types[0] + b.While(b.Eq(b.CallIntrinsic(scope, {arg_types[0], arg_types[0] }, { - args[0], b.i(2, arg_types[0])}, return_type, 0, Mod::instantiate_Mod), b.i(0, arg_types[0])), + n_val, b.i_t(2, arg_types[0])}, return_type, 0, Mod::instantiate_Mod), b.i_t(0, arg_types[0])), { - b.Assignment(args[0], b.i_tDiv(args[0], b.i(2, arg_types[0]), arg_types[0])), - b.Assignment(result, b.i_tAdd(result, b.i(1, arg_types[0]), arg_types[0])) + b.Assignment(n_val, b.Div(n_val, b.i_t(2, arg_types[0]))), + b.Assignment(result, b.Add(result, b.i_t(1, arg_types[0]))) }) })); @@ -2877,27 +3778,73 @@ namespace Trailz { } // namespace Trailz +namespace Nearest { + + static ASR::expr_t *eval_Nearest(Allocator &al, const Location &loc, + ASR::ttype_t* t1, Vec &args, diag::Diagnostics& diag) { + int64_t kind = ASRUtils::extract_kind_from_ttype_t(ASRUtils::expr_type(args[0])); + double s = ASR::down_cast(args[1])->m_r; + if (s == 0.0) { + append_error(diag, "`S` argument of nearest() must be non-zero", loc); + return nullptr; + } + if (kind == 4) { + float x = ASR::down_cast(args[0])->m_r; + float result = 0.0; + if (s > 0) result = x + std::fabs(std::nextafterf(x, std::numeric_limits::infinity()) - x); + else result = x - std::fabs(std::nextafterf(x, -std::numeric_limits::infinity()) - x); + return make_ConstantWithType(make_RealConstant_t, result, t1, loc); + } else { + double x = ASR::down_cast(args[0])->m_r; + double result = 0.0; + if (s > 0) result = x + std::fabs(std::nextafter(x, std::numeric_limits::infinity()) - x); + else result = x - std::fabs(std::nextafter(x, -std::numeric_limits::infinity()) - x); + return make_ConstantWithType(make_RealConstant_t, result, t1, loc); + } + } + + static inline ASR::expr_t* instantiate_Nearest(Allocator &al, const Location &loc, + SymbolTable *scope, Vec& arg_types, ASR::ttype_t *return_type, + Vec& new_args, int64_t /*overload_id*/) { + declare_basic_variables("_lcompilers_optimization_nearest_" + type_to_str_python(arg_types[0])); + fill_func_arg("x", arg_types[0]); + fill_func_arg("s", arg_types[1]); + auto result = declare(fn_name, arg_types[0], ReturnVar); + /* + function nearest(x, s) result(result) + real :: x, s + real :: result + result = ? + end function + */ + throw LCompilersException("`Nearest` intrinsic is not yet implemented for runtime values"); + + ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, + body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); + scope->add_symbol(fn_name, f_sym); + return b.Call(f_sym, new_args, return_type, nullptr); + } + +} // namespace Nearest + namespace Modulo { static ASR::expr_t *eval_Modulo(Allocator &al, const Location &loc, - ASR::ttype_t* t1, Vec &args, diag::Diagnostics& /*diag*/) { - + ASR::ttype_t* t1, Vec &args, diag::Diagnostics& diag) { if (is_integer(*ASRUtils::expr_type(args[0])) && is_integer(*ASRUtils::expr_type(args[1]))) { int64_t a = ASR::down_cast(args[0])->m_n; int64_t b = ASR::down_cast(args[1])->m_n; - if ( a*b >= 0 ) { - return make_ConstantWithType(make_IntegerConstant_t, a % b, t1, loc); - } else { - return make_ConstantWithType(make_IntegerConstant_t, a % b + b, t1, loc); + if (b == 0) { + append_error(diag, "Second argument of modulo cannot be 0", loc); } + return make_ConstantWithType(make_IntegerConstant_t, a - b * std::floor(std::real(a)/b), t1, loc); } else if (is_real(*ASRUtils::expr_type(args[0])) && is_real(*ASRUtils::expr_type(args[1]))) { double a = ASR::down_cast(args[0])->m_r; double b = ASR::down_cast(args[1])->m_r; - if ( a*b > 0 ) { - return make_ConstantWithType(make_RealConstant_t, std::fmod(a, b), t1, loc); - } else { - return make_ConstantWithType(make_RealConstant_t, std::fmod(a, b) + b, t1, loc); + if (b == 0) { + append_error(diag, "Second argument of modulo cannot be 0", loc); } + return make_ConstantWithType(make_RealConstant_t, a - b * std::floor(a/b), t1, loc); } return nullptr; } @@ -2911,26 +3858,13 @@ namespace Modulo { auto result = declare(fn_name, return_type, ReturnVar); /* function modulo(a, p) result(d) - if ( a*p >= 0 ) then - d = mod(a, p) - else - d = mod(a, p) + p - end if + d = a - p * floor(a/p) end function */ - if (is_real(*arg_types[0])) { - body.push_back(al, b.If(b.fGtE(b.r_tMul(args[0], args[1], arg_types[0]), b.f(0.0, arg_types[0])), { - b.Assignment(result, Mod::MOD(b, args[0], args[1], scope)) - }, { - b.Assignment(result, b.r_tAdd(Mod::MOD(b, args[0], args[1], scope), args[1], arg_types[0])) - })); + body.push_back(al, b.Assignment(result, b.Sub(args[0], b.Mul(b.r2r_t(args[1], arg_types[0]) , b.i2r_t(Floor::FLOOR(b, b.Div(args[0], b.r2r_t(args[1], arg_types[0])), int32, scope), arg_types[1]))))); } else { - body.push_back(al, b.If(b.iGtE(b.i_tMul(args[0], args[1], arg_types[0]), b.i(0, arg_types[0])), { - b.Assignment(result, Mod::MOD(b, args[0], args[1], scope)) - }, { - b.Assignment(result, b.i_tAdd(Mod::MOD(b, args[0], args[1], scope), args[1], arg_types[0])) - })); + body.push_back(al, b.Assignment(result, b.Sub(args[0], b.Mul(b.i2i_t(args[1], arg_types[0]), Floor::FLOOR(b, b.Div(b.i2r_t(args[0], real32), b.i2r_t(args[1], real32)), int32, scope))))); } ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, @@ -2941,23 +3875,23 @@ namespace Modulo { } // namespace Modulo -namespace BesselJ0 { +namespace BesselJN { - static ASR::expr_t *eval_BesselJ0(Allocator &/*al*/, const Location &/*loc*/, - ASR::ttype_t* /*t1*/, Vec &/*args*/, diag::Diagnostics& /*diag*/) { - return nullptr; + static ASR::expr_t *eval_BesselJN(Allocator& al, const Location& loc, + ASR::ttype_t* t1, Vec& args, diag::Diagnostics& /*diag*/) { + return make_ConstantWithType(make_RealConstant_t, jn(ASR::down_cast(args[0])->m_n, ASR::down_cast(args[1])->m_r), t1, loc); } - static inline ASR::expr_t* instantiate_BesselJ0(Allocator &al, const Location &loc, + static inline ASR::expr_t* instantiate_BesselJN(Allocator &al, const Location &loc, SymbolTable *scope, Vec& arg_types, ASR::ttype_t *return_type, Vec& new_args, int64_t /*overload_id*/) { std::string c_func_name; - if (ASRUtils::extract_kind_from_ttype_t(arg_types[0]) == 4) { - c_func_name = "_lfortran_sbesselj0"; + if (ASRUtils::extract_kind_from_ttype_t(arg_types[1]) == 4) { + c_func_name = "_lfortran_sbesseljn"; } else { - c_func_name = "_lfortran_dbesselj0"; + c_func_name = "_lfortran_dbesseljn"; } - std::string new_name = "_lcompilers_bessel_j0_"+ type_to_str_python(arg_types[0]); + std::string new_name = "_lcompilers_bessel_jn_"+ type_to_str_python(arg_types[1]); declare_basic_variables(new_name); if (scope->get_symbol(new_name)) { @@ -2965,25 +3899,11 @@ namespace BesselJ0 { ASR::Function_t *f = ASR::down_cast(s); return b.Call(s, new_args, expr_type(f->m_return_var)); } - fill_func_arg("x", arg_types[0]); + fill_func_arg("n", arg_types[0]); + fill_func_arg("x", arg_types[1]); auto result = declare(new_name, return_type, ReturnVar); { - SymbolTable *fn_symtab_1 = al.make_new(fn_symtab); - Vec args_1; - { - args_1.reserve(al, 1); - ASR::expr_t *arg = b.Variable(fn_symtab_1, "x", arg_types[0], - ASR::intentType::In, ASR::abiType::BindC, true); - args_1.push_back(al, arg); - } - - ASR::expr_t *return_var_1 = b.Variable(fn_symtab_1, c_func_name, - return_type, ASRUtils::intent_return_var, ASR::abiType::BindC, false); - - SetChar dep_1; dep_1.reserve(al, 1); - Vec body_1; body_1.reserve(al, 1); - ASR::symbol_t *s = make_ASR_Function_t(c_func_name, fn_symtab_1, dep_1, args_1, - body_1, return_var_1, ASR::abiType::BindC, ASR::deftypeType::Interface, s2c(al, c_func_name)); + ASR::symbol_t *s = b.create_c_func(c_func_name, fn_symtab, return_type, 2, arg_types); fn_symtab->add_symbol(c_func_name, s); dep.push_back(al, s2c(al, c_func_name)); body.push_back(al, b.Assignment(result, b.Call(s, args, return_type))); @@ -2995,81 +3915,25 @@ namespace BesselJ0 { return b.Call(new_symbol, new_args, return_type); } -} // namespace BesselJ0 - -namespace BesselJ1 { - - static ASR::expr_t *eval_BesselJ1(Allocator &/*al*/, const Location &/*loc*/, - ASR::ttype_t* /*t1*/, Vec &/*args*/, diag::Diagnostics& /*diag*/) { - return nullptr; - } - - static inline ASR::expr_t* instantiate_BesselJ1(Allocator &al, const Location &loc, - SymbolTable *scope, Vec& arg_types, ASR::ttype_t *return_type, - Vec& new_args, int64_t /*overload_id*/) { - std::string c_func_name; - if (ASRUtils::extract_kind_from_ttype_t(arg_types[0]) == 4) { - c_func_name = "_lfortran_sbesselj1"; - } else { - c_func_name = "_lfortran_dbesselj1"; - } - std::string new_name = "_lcompilers_bessel_j1_"+ type_to_str_python(arg_types[0]); - - declare_basic_variables(new_name); - if (scope->get_symbol(new_name)) { - ASR::symbol_t *s = scope->get_symbol(new_name); - ASR::Function_t *f = ASR::down_cast(s); - return b.Call(s, new_args, expr_type(f->m_return_var)); - } - fill_func_arg("x", arg_types[0]); - auto result = declare(new_name, return_type, ReturnVar); - { - SymbolTable *fn_symtab_1 = al.make_new(fn_symtab); - Vec args_1; - { - args_1.reserve(al, 1); - ASR::expr_t *arg = b.Variable(fn_symtab_1, "x", arg_types[0], - ASR::intentType::In, ASR::abiType::BindC, true); - args_1.push_back(al, arg); - } +} // namespace BesselJN - ASR::expr_t *return_var_1 = b.Variable(fn_symtab_1, c_func_name, - return_type, ASRUtils::intent_return_var, ASR::abiType::BindC, false); +namespace BesselYN { - SetChar dep_1; dep_1.reserve(al, 1); - Vec body_1; body_1.reserve(al, 1); - ASR::symbol_t *s = make_ASR_Function_t(c_func_name, fn_symtab_1, dep_1, args_1, - body_1, return_var_1, ASR::abiType::BindC, ASR::deftypeType::Interface, s2c(al, c_func_name)); - fn_symtab->add_symbol(c_func_name, s); - dep.push_back(al, s2c(al, c_func_name)); - body.push_back(al, b.Assignment(result, b.Call(s, args, return_type))); - } - - ASR::symbol_t *new_symbol = make_ASR_Function_t(fn_name, fn_symtab, dep, args, - body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); - scope->add_symbol(fn_name, new_symbol); - return b.Call(new_symbol, new_args, return_type); - } - -} // namespace BesselJ1 - -namespace BesselY0 { - - static ASR::expr_t *eval_BesselY0(Allocator &/*al*/, const Location &/*loc*/, - ASR::ttype_t* /*t1*/, Vec &/*args*/, diag::Diagnostics& /*diag*/) { - return nullptr; + static ASR::expr_t *eval_BesselYN(Allocator& al, const Location& loc, + ASR::ttype_t* t1, Vec& args, diag::Diagnostics& /*diag*/) { + return make_ConstantWithType(make_RealConstant_t, yn(ASR::down_cast(args[0])->m_n, ASR::down_cast(args[1])->m_r), t1, loc); } - static inline ASR::expr_t* instantiate_BesselY0(Allocator &al, const Location &loc, + static inline ASR::expr_t* instantiate_BesselYN(Allocator &al, const Location &loc, SymbolTable *scope, Vec& arg_types, ASR::ttype_t *return_type, Vec& new_args, int64_t /*overload_id*/) { std::string c_func_name; - if (ASRUtils::extract_kind_from_ttype_t(arg_types[0]) == 4) { - c_func_name = "_lfortran_sbessely0"; + if (ASRUtils::extract_kind_from_ttype_t(arg_types[1]) == 4) { + c_func_name = "_lfortran_sbesselyn"; } else { - c_func_name = "_lfortran_dbessely0"; + c_func_name = "_lfortran_dbesselyn"; } - std::string new_name = "_lcompilers_bessel_y0_"+ type_to_str_python(arg_types[0]); + std::string new_name = "_lcompilers_bessel_yn_"+ type_to_str_python(arg_types[1]); declare_basic_variables(new_name); if (scope->get_symbol(new_name)) { @@ -3077,25 +3941,11 @@ namespace BesselY0 { ASR::Function_t *f = ASR::down_cast(s); return b.Call(s, new_args, expr_type(f->m_return_var)); } - fill_func_arg("x", arg_types[0]); + fill_func_arg("n", arg_types[0]); + fill_func_arg("x", arg_types[1]); auto result = declare(new_name, return_type, ReturnVar); { - SymbolTable *fn_symtab_1 = al.make_new(fn_symtab); - Vec args_1; - { - args_1.reserve(al, 1); - ASR::expr_t *arg = b.Variable(fn_symtab_1, "x", arg_types[0], - ASR::intentType::In, ASR::abiType::BindC, true); - args_1.push_back(al, arg); - } - - ASR::expr_t *return_var_1 = b.Variable(fn_symtab_1, c_func_name, - return_type, ASRUtils::intent_return_var, ASR::abiType::BindC, false); - - SetChar dep_1; dep_1.reserve(al, 1); - Vec body_1; body_1.reserve(al, 1); - ASR::symbol_t *s = make_ASR_Function_t(c_func_name, fn_symtab_1, dep_1, args_1, - body_1, return_var_1, ASR::abiType::BindC, ASR::deftypeType::Interface, s2c(al, c_func_name)); + ASR::symbol_t *s = b.create_c_func(c_func_name, fn_symtab, return_type, 2, arg_types); fn_symtab->add_symbol(c_func_name, s); dep.push_back(al, s2c(al, c_func_name)); body.push_back(al, b.Assignment(result, b.Call(s, args, return_type))); @@ -3107,7 +3957,7 @@ namespace BesselY0 { return b.Call(new_symbol, new_args, return_type); } -} // namespace BesselY0 +} // namespace BesselYN namespace Poppar { @@ -3135,14 +3985,63 @@ namespace Poppar { end function */ ASR::expr_t *func_call_poppar =Popcnt::POPCNT(b, args[0], return_type, scope); - body.push_back(al, b.Assignment(result, Mod::MOD(b, func_call_poppar, b.i(2, return_type), scope))); - ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); + body.push_back(al, b.Assignment(result, Mod::MOD(b, func_call_poppar, b.i_t(2, return_type), scope))); + ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, + body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); scope->add_symbol(fn_name, f_sym); return b.Call(f_sym, new_args, return_type, nullptr); } } // namespace Poppar +namespace Real { + + static ASR::expr_t *eval_Real(Allocator &al, const Location &loc, + ASR::ttype_t* t1, Vec &args, diag::Diagnostics& diag) { + if (ASR::is_a(*args[0])) { + double i = ASR::down_cast(ASRUtils::expr_value(args[0]))->m_n; + return make_ConstantWithType(make_RealConstant_t, i, t1, loc); + } else if (ASR::is_a(*args[0])) { + ASR::RealConstant_t *r = ASR::down_cast(ASRUtils::expr_value(args[0])); + return make_ConstantWithType(make_RealConstant_t, r->m_r, t1, loc); + } else if (ASR::is_a(*args[0])) { + ASR::ComplexConstant_t *c = ASR::down_cast(ASRUtils::expr_value(args[0])); + return make_ConstantWithType(make_RealConstant_t, c->m_re, t1, loc); + } else { + append_error(diag, "Invalid argument to `real` intrinsic", loc); + return nullptr; + } + } + + static inline ASR::expr_t* instantiate_Real(Allocator &al, const Location &loc, + SymbolTable *scope, Vec& arg_types, ASR::ttype_t *return_type, + Vec& new_args, int64_t /*overload_id*/) { + declare_basic_variables("_lcompilers_real_" + type_to_str_python(arg_types[0])); + fill_func_arg("x", arg_types[0]); + auto result = declare(fn_name, return_type, ReturnVar); + /* + function real(a) result(result) + real :: a + real :: result + result = a + end function + */ + if (is_integer(*arg_types[0])) { + body.push_back(al, b.Assignment(result, b.i2r_t(args[0], return_type))); + } else if (is_real(*arg_types[0])) { + body.push_back(al, b.Assignment(result, b.r2r_t(args[0], return_type))); + } else if (is_complex(*arg_types[0])) { + body.push_back(al, b.Assignment(result, EXPR(ASR::make_ComplexRe_t(al, loc, + args[0], return_type, nullptr)))); + } + ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, + body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); + scope->add_symbol(fn_name, f_sym); + return b.Call(f_sym, new_args, return_type, nullptr); + } + +} // namespace Real + namespace Mvbits { static ASR::expr_t *eval_Mvbits(Allocator &/*al*/, const Location &/*loc*/, @@ -3215,6 +4114,99 @@ namespace Mvbits { } // namespace Mvbits +namespace MoveAlloc { + + static ASR::expr_t *eval_MoveAlloc(Allocator &/*al*/, const Location &/*loc*/, + ASR::ttype_t* /*t1*/, Vec &/*args*/, diag::Diagnostics& /*diag*/) { + return nullptr; + } + + static inline ASR::expr_t* instantiate_MoveAlloc(Allocator &al, const Location &loc, + SymbolTable *scope, Vec& arg_types, ASR::ttype_t *return_type, + Vec& new_args, int64_t /*overload_id*/) { + + std::string new_name = "_lcompilers_move_alloc_" + type_to_str_python(arg_types[0]); + declare_basic_variables(new_name); + fill_func_arg("from", arg_types[0]); + fill_func_arg("to", arg_types[1]); + auto result = declare(new_name, arg_types[0], ReturnVar); + body.push_back(al, b.Assignment(result, args[0])); + + ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, + body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); + scope->add_symbol(fn_name, f_sym); + return b.Call(f_sym, new_args, return_type, nullptr); + } + +} // namespace MoveAlloc + +namespace Mergebits { + + static int compute_merge_bits(int a, int b, int mask, int total_bits) { + int result = 0; + int k = 0; + while (k < total_bits) { + if (mask & (1 << k)) { + result |= (a & (1 << k)); + } else { + result |= (b & (1 << k)); + } + k++; + } + return result; + } + + static ASR::expr_t *eval_Mergebits(Allocator &al, const Location &loc, + ASR::ttype_t* t1, Vec &args, diag::Diagnostics& /*diag*/) { + int kind = ASRUtils::extract_kind_from_ttype_t(ASR::down_cast(args[0])->m_type); + int a = ASR::down_cast(args[0])->m_n; + int b = ASR::down_cast(args[1])->m_n; + int mask = ASR::down_cast(args[2])->m_n; + int result = 0; + result = compute_merge_bits(a, b, mask, kind * 8); + return make_ConstantWithType(make_IntegerConstant_t, result, t1, loc); + } + + static inline ASR::expr_t* instantiate_Mergebits(Allocator &al, const Location &loc, + SymbolTable *scope, Vec& arg_types, ASR::ttype_t *return_type, + Vec& new_args, int64_t /*overload_id*/) { + declare_basic_variables("_lcompilers_mergebits_" + type_to_str_python(arg_types[0])); + fill_func_arg("a", arg_types[0]); + fill_func_arg("b", arg_types[1]); + fill_func_arg("mask", arg_types[2]); + auto result = declare(fn_name, return_type, ReturnVar); + auto itr = declare("i", arg_types[0], Local); + auto mask = declare("m", arg_types[0], Local); + auto numberofbits = declare("n", arg_types[0], Local); + + if(ASRUtils::extract_kind_from_ttype_t(arg_types[0]) != ASRUtils::extract_kind_from_ttype_t(arg_types[1])){ + throw LCompilersException("The second argument of 'merge_bits' intrinsic must be the same type and kind as first argument"); + } + if(ASRUtils::extract_kind_from_ttype_t(arg_types[0]) != ASRUtils::extract_kind_from_ttype_t(arg_types[2])){ + throw LCompilersException("The third argument of 'merge_bits' intrinsic must be the same type and kind as first argument"); + } + + body.push_back(al, b.Assignment(result, b.i_t(0, arg_types[0]))); + body.push_back(al, b.Assignment(itr, b.i_t(0, arg_types[0]))); + body.push_back(al, b.Assignment(mask, args[2])); + body.push_back(al, b.Assignment(numberofbits, b.Mul(b.i_t(8, arg_types[0]), + b.i_t(ASRUtils::extract_kind_from_ttype_t(arg_types[0]), arg_types[0])))); + body.push_back(al, b.While(b.Lt(itr, numberofbits), { + b.If(b.NotEq(b.i_t(0, arg_types[0]), b.And(mask, b.BitLshift(b.i_t(1, arg_types[0]), itr, arg_types[0]))), { + b.Assignment(result, b.Or(result, b.And(args[0], b.BitLshift(b.i_t(1, arg_types[0]), itr, arg_types[0])))) + }, { + b.Assignment(result, b.Or(result, b.And(args[1], b.BitLshift(b.i_t(1, arg_types[0]), itr, arg_types[0])))) + }), + b.Assignment(itr, b.Add(itr, b.i_t(1, arg_types[0]))), + })); + ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, + body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); + scope->add_symbol(fn_name, f_sym); + return b.Call(f_sym, new_args, return_type, nullptr); + } + +} // namespace Mergebits + namespace Leadz { static ASR::expr_t *eval_Leadz(Allocator &al, const Location &loc, @@ -3222,13 +4214,14 @@ namespace Leadz { int64_t a = ASR::down_cast(args[0])->m_n; int64_t kind = ASRUtils::extract_kind_from_ttype_t(t1); int64_t leading_zeros = ASRUtils::compute_leading_zeros(a, kind); + set_kind_to_ttype_t(t1, 4); return make_ConstantWithType(make_IntegerConstant_t, leading_zeros, t1, loc); } static inline ASR::expr_t* instantiate_Leadz(Allocator &al, const Location &loc, SymbolTable *scope, Vec& arg_types, ASR::ttype_t *return_type, Vec& new_args, int64_t /*overload_id*/) { - declare_basic_variables("_lcompilers_optimization_leadz_" + type_to_str_python(arg_types[0])); + declare_basic_variables("_lcompilers_leadz_" + type_to_str_python(arg_types[0])); fill_func_arg("n", arg_types[0]); auto result = declare(fn_name, arg_types[0], ReturnVar); auto total_bits = declare("r", arg_types[0], Local); @@ -3255,21 +4248,21 @@ namespace Leadz { end if end function */ - body.push_back(al, b.Assignment(result, b.i(0, arg_types[0]))); + body.push_back(al, b.Assignment(result, b.i_t(0, arg_types[0]))); body.push_back(al, b.Assignment(number, args[0])); - body.push_back(al, b.Assignment(total_bits, b.i(8*ASRUtils::extract_kind_from_ttype_t(arg_types[0]), arg_types[0]))); - body.push_back(al, b.If(b.iLt(number, b.i(0, arg_types[0])), { - b.Assignment(result, b.i(0, arg_types[0])) + body.push_back(al, b.Assignment(total_bits, b.i_t(8*ASRUtils::extract_kind_from_ttype_t(arg_types[0]), arg_types[0]))); + body.push_back(al, b.If(b.Lt(number, b.i_t(0, arg_types[0])), { + b.Assignment(result, b.i_t(0, arg_types[0])) }, { - b.While(b.iGt(total_bits, b.i(0, arg_types[0])), { - b.If(b.iEq(b.CallIntrinsic(scope, {arg_types[0], arg_types[0]}, - {number, b.i(2, arg_types[0])}, return_type, 0, Mod::instantiate_Mod), b.i(0, arg_types[0])), { - b.Assignment(result, b.i_tAdd(result, b.i(1, arg_types[0]), arg_types[0])) + b.While(b.Gt(total_bits, b.i_t(0, arg_types[0])), { + b.If(b.Eq(b.CallIntrinsic(scope, {arg_types[0], arg_types[0]}, + {number, b.i_t(2, arg_types[0])}, return_type, 0, Mod::instantiate_Mod), b.i_t(0, arg_types[0])), { + b.Assignment(result, b.Add(result, b.i_t(1, arg_types[0]))) }, { - b.Assignment(result, b.i(0, arg_types[0])) + b.Assignment(result, b.i_t(0, arg_types[0])) }), - b.Assignment(number, b.i_tDiv(number, b.i(2, arg_types[0]), arg_types[0])), - b.Assignment(total_bits, b.i_tSub(total_bits, b.i(1, arg_types[0]), arg_types[0])), + b.Assignment(number, b.Div(number, b.i_t(2, arg_types[0]))), + b.Assignment(total_bits, b.Sub(total_bits, b.i_t(1, arg_types[0]))), }), })); @@ -3295,14 +4288,24 @@ namespace Ishftc { uint64_t val = (uint64_t)ASR::down_cast(args[0])->m_n; int64_t shift_signed = ASR::down_cast(args[1])->m_n; int kind = ASRUtils::extract_kind_from_ttype_t(ASR::down_cast(args[0])->m_type); + uint32_t bits_size = (uint32_t)ASR::down_cast(args[2])->m_n; + uint32_t max_bits_size = 64; + if (bits_size > (uint32_t)(8 * kind)) { + append_error(diag, "The SIZE argument must be greater than zero and less than or equal to BIT_SIZE('I')", loc); + return nullptr; + } + if(std::abs(shift_signed) > bits_size){ + append_error(diag, "The SHIFT argument must be less than or equal to the of SIZE argument", loc); + return nullptr; + } bool negative_shift = (shift_signed < 0); uint32_t shift = abs(shift_signed); - uint32_t bits_size = 8u * (uint32_t)kind; - uint32_t max_bits_size = 64; - if (bits_size < shift) { - append_error(diag, "The absolute value of SHIFT argument must be less than or equal to BIT_SIZE('I')", loc); + + if (shift > max_bits_size) { + append_error(diag, "The absolute value of SHIFT argument must be less than SIZE", loc); return nullptr; } + val = cutoff_extra_bits(val, bits_size, max_bits_size); uint64_t result; if (negative_shift) { @@ -3313,11 +4316,38 @@ namespace Ishftc { return make_ConstantWithType(make_IntegerConstant_t, result, t1, loc); } - static inline ASR::expr_t* instantiate_Ishftc(Allocator & /*al*/, const Location & /*loc*/, - SymbolTable */*scope*/, Vec& /*arg_types*/, ASR::ttype_t */*return_type*/, - Vec& /*new_args*/, int64_t /*overload_id*/) { - // TO DO: Implement the runtime function for ISHFTC - throw LCompilersException("Runtime implementation for `ishftc` is not yet implemented."); + static inline ASR::expr_t* instantiate_Ishftc(Allocator & al, const Location & loc, + SymbolTable *scope, Vec& arg_types, ASR::ttype_t *return_type, + Vec& new_args, int64_t /*overload_id*/) { + std::string c_func_name; + if(ASRUtils::extract_kind_from_ttype_t(arg_types[1]) == 4){ + c_func_name = "_lfortran_sishftc"; + } else { + c_func_name = "_lfortran_dishftc"; + } + std::string new_name = "_lcompilers_ishftc_"+ type_to_str_python(arg_types[1]); + + declare_basic_variables(new_name); + if (scope->get_symbol(new_name)) { + ASR::symbol_t *s = scope->get_symbol(new_name); + ASR::Function_t *f = ASR::down_cast(s); + return b.Call(s, new_args, expr_type(f->m_return_var)); + } + fill_func_arg("n", arg_types[0]); + fill_func_arg("x", arg_types[1]); + fill_func_arg("size", arg_types[2]); + auto result = declare(new_name, return_type, ReturnVar); + { + ASR::symbol_t *s = b.create_c_func(c_func_name, fn_symtab, return_type, 3, arg_types); + fn_symtab->add_symbol(c_func_name, s); + dep.push_back(al, s2c(al, c_func_name)); + body.push_back(al, b.Assignment(result, b.Call(s, args, return_type))); + } + + ASR::symbol_t *new_symbol = make_ASR_Function_t(fn_name, fn_symtab, dep, args, + body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); + scope->add_symbol(fn_name, new_symbol); + return b.Call(new_symbol, new_args, return_type); } } // namespace Ishftc @@ -3352,9 +4382,9 @@ namespace Hypot { end function */ body.push_back(al, b.Assignment(result, b.CallIntrinsic(scope, { - ASRUtils::expr_type(b.r_tAdd(b.r_tMul(args[0], args[0], arg_types[0]), b.r_tMul(args[1], args[1], arg_types[0]), arg_types[0])) + ASRUtils::expr_type(b.Add(b.Mul(args[0], args[0]), b.Mul(args[1], args[1]))) }, { - b.r_tAdd(b.r_tMul(args[0], args[0], arg_types[0]), b.r_tMul(args[1], args[1], arg_types[0]), arg_types[0]) + b.Add(b.Mul(args[0], args[0]), b.Mul(args[1], args[1])) }, return_type, 0, Sqrt::instantiate_Sqrt))); ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, @@ -3380,9 +4410,9 @@ namespace ToLowerCase { Vec& new_args, int64_t /*overload_id*/) { declare_basic_variables(""); fill_func_arg("s", arg_types[0]); - ASR::ttype_t* char_type = ASRUtils::TYPE(ASR::make_Character_t(al, loc, 1, 0, nullptr)); + ASR::ttype_t* char_type = ASRUtils::TYPE(ASR::make_String_t(al, loc, 1, 0, nullptr, ASR::string_physical_typeType::PointerString)); auto result = declare(fn_name, char_type, ReturnVar); - auto itr = declare("i", ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)), Local); + auto itr = declare("i", int32, Local); /* function toLowerCase(str) result(result) @@ -3403,16 +4433,16 @@ namespace ToLowerCase { */ body.push_back(al, b.Assignment(itr, b.i32(1))); - body.push_back(al, b.While(b.iLtE(itr, b.StringLen(args[0])), { - b.If(b.And(b.iGtE(ASRUtils::EXPR(ASR::make_Ichar_t(al, loc, ASRUtils::EXPR(ASR::make_StringItem_t(al, loc, args[0], itr, char_type, nullptr)), int32, nullptr)), b.Ichar("A", arg_types[0], int32)), - b.iLtE(ASRUtils::EXPR(ASR::make_Ichar_t(al, loc, ASRUtils::EXPR(ASR::make_StringItem_t(al, loc, args[0], itr, char_type, nullptr)), int32, nullptr)), b.Ichar("Z", arg_types[0], int32))), { + body.push_back(al, b.While(b.LtE(itr, b.StringLen(args[0])), { + b.If(b.And(b.GtE(ASRUtils::EXPR(ASR::make_Ichar_t(al, loc, ASRUtils::EXPR(ASR::make_StringItem_t(al, loc, args[0], itr, char_type, nullptr)), int32, nullptr)), b.Ichar("A", arg_types[0], int32)), + b.LtE(ASRUtils::EXPR(ASR::make_Ichar_t(al, loc, ASRUtils::EXPR(ASR::make_StringItem_t(al, loc, args[0], itr, char_type, nullptr)), int32, nullptr)), b.Ichar("Z", arg_types[0], int32))), { b.Assignment(result, b.StringConcat(result, ASRUtils::EXPR(ASR::make_StringChr_t(al, loc, - b.iSub(b.iAdd(ASRUtils::EXPR(ASR::make_Ichar_t(al, loc, ASRUtils::EXPR(ASR::make_StringItem_t(al, loc, args[0], itr, char_type, nullptr)), int32, nullptr)), b.Ichar("a", arg_types[0], int32)), + b.Sub(b.Add(ASRUtils::EXPR(ASR::make_Ichar_t(al, loc, ASRUtils::EXPR(ASR::make_StringItem_t(al, loc, args[0], itr, char_type, nullptr)), int32, nullptr)), b.Ichar("a", arg_types[0], int32)), b.Ichar("A", arg_types[0], int32)), return_type, nullptr)), char_type)) }, { b.Assignment(result, b.StringConcat(result, ASRUtils::EXPR(ASR::make_StringItem_t(al, loc, args[0], itr, char_type, nullptr)), char_type)) }), - b.Assignment(itr, b.i_tAdd(itr, b.i32(1), int32)), + b.Assignment(itr, b.Add(itr, b.i32(1))), })); ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); @@ -3449,16 +4479,16 @@ namespace SelectedIntKind { auto result = declare(fn_name, int32, ReturnVar); auto number = declare("num", arg_types[0], Local); body.push_back(al, b.Assignment(number, args[0])); - body.push_back(al, b.If(b.iLtE(number, b.i(2, arg_types[0])), { - b.Assignment(result, b.i(1, int32)) + body.push_back(al, b.If(b.LtE(number, b.i_t(2, arg_types[0])), { + b.Assignment(result, b.i32(1)) }, { - b.If(b.iLtE(number, b.i(4, arg_types[0])), { - b.Assignment(result, b.i(2, int32)) + b.If(b.LtE(number, b.i_t(4, arg_types[0])), { + b.Assignment(result, b.i32(2)) }, { - b.If(b.iLtE(number, b.i(9, arg_types[0])), { - b.Assignment(result, b.i(4, int32)) + b.If(b.LtE(number, b.i_t(9, arg_types[0])), { + b.Assignment(result, b.i32(4)) }, { - b.Assignment(result, b.i(8, int32)) + b.Assignment(result, b.i32(8)) }) }) })); @@ -3508,16 +4538,16 @@ namespace SelectedRealKind { body.push_back(al, b.Assignment(p, args[0])); body.push_back(al, b.Assignment(r, args[1])); body.push_back(al, b.Assignment(radix, args[2])); - body.push_back(al, b.If(b.And(b.And(b.iLt(p, b.i(7, arg_types[0])), b.iLt(r, b.i(38, arg_types[1]))), b.iEq(radix, b.i(2, arg_types[2]))), { - b.Assignment(result, b.i(4, int32)) + body.push_back(al, b.If(b.And(b.And(b.Lt(p, b.i_t(7, arg_types[0])), b.Lt(r, b.i_t(38, arg_types[1]))), b.Eq(radix, b.i_t(2, arg_types[2]))), { + b.Assignment(result, b.i32(4)) }, { - b.If( b.And(b.And(b.iLt(p, b.i(15, arg_types[0])), b.iLt(r, b.i(308, arg_types[1]))), b.iEq(radix, b.i(2, arg_types[2]))), { - b.Assignment(result, b.i(8, int32)) + b.If( b.And(b.And(b.Lt(p, b.i_t(15, arg_types[0])), b.Lt(r, b.i_t(308, arg_types[1]))), b.Eq(radix, b.i_t(2, arg_types[2]))), { + b.Assignment(result, b.i32(8)) }, { - b.If(b.iNotEq(radix, b.i(2, arg_types[2])), { - b.Assignment(result, b.i(-5, int32)) + b.If(b.NotEq(radix, b.i_t(2, arg_types[2])), { + b.Assignment(result, b.i32(-5)) }, { - b.Assignment(result, b.i(-1, int32)) + b.Assignment(result, b.i32(-1)) }) }) })); @@ -3557,14 +4587,14 @@ namespace SelectedCharKind { ASR::expr_t* func_call_lowercase = b.CallIntrinsic(scope, {arg_types[0]}, {args[0]}, arg_types[0], 0, ToLowerCase::instantiate_ToLowerCase); - body.push_back(al, b.If(b.Or(b.sEq(func_call_lowercase, b.StringConstant("ascii", arg_types[0])), - b.sEq(func_call_lowercase, b.StringConstant("default", arg_types[0]))), { - b.Assignment(result, b.i(1, return_type)) + body.push_back(al, b.If(b.Or(b.Eq(func_call_lowercase, b.StringConstant("ascii", arg_types[0])), + b.Eq(func_call_lowercase, b.StringConstant("default", arg_types[0]))), { + b.Assignment(result, b.i_t(1, return_type)) }, { - b.If(b.sEq(func_call_lowercase, b.StringConstant("iso_10646", arg_types[0])), { - b.Assignment(result, b.i(4, return_type)) + b.If(b.Eq(func_call_lowercase, b.StringConstant("iso_10646", arg_types[0])), { + b.Assignment(result, b.i_t(4, return_type)) }, { - b.Assignment(result, b.i(-1, return_type)) + b.Assignment(result, b.i_t(-1, return_type)) }) })); @@ -3584,20 +4614,6 @@ namespace Kind { return make_ConstantWithType(make_IntegerConstant_t, result, int32, loc); } - static inline ASR::expr_t* instantiate_Kind(Allocator &al, const Location &loc, - SymbolTable *scope, Vec& arg_types, ASR::ttype_t *return_type, - Vec& new_args, int64_t /*overload_id*/) { - declare_basic_variables("_lcompilers_optimization_kind_" + type_to_str_python(arg_types[0])); - fill_func_arg("x", arg_types[0]); - auto result = declare(fn_name, int32, ReturnVar); - body.push_back(al, b.Assignment(result, b.i32(ASRUtils::extract_kind_from_ttype_t(arg_types[0])))); - - ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, - body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); - scope->add_symbol(fn_name, f_sym); - return b.Call(f_sym, new_args, return_type, nullptr); - } - } // namespace Kind namespace Rank { @@ -3605,11 +4621,31 @@ namespace Rank { static ASR::expr_t *eval_Rank(Allocator &al, const Location &loc, ASR::ttype_t* /*t1*/, Vec &args, diag::Diagnostics& /*diag*/) { ASRUtils::ASRBuilder b(al, loc); - return b.i32(extract_n_dims_from_ttype(expr_type(args[0]))); + return b.i_t(extract_n_dims_from_ttype(expr_type(args[0])), int32); } } // namespace Rank +namespace BitSize { + + static ASR::expr_t *eval_BitSize(Allocator &al, const Location &loc, + ASR::ttype_t* t1, Vec &args, diag::Diagnostics& /*diag*/) { + int kind = ASRUtils::extract_kind_from_ttype_t(ASRUtils::expr_type(args[0])); + return make_ConstantWithType(make_IntegerConstant_t, 8*kind, t1, loc); + } + +} // namespace BitSize + +namespace NewLine { + + static ASR::expr_t *eval_NewLine(Allocator &al, const Location &loc, + ASR::ttype_t* /*t1*/, Vec &/*args*/, diag::Diagnostics& /*diag*/) { + char* new_line_str = (char*)"\n"; + return make_ConstantWithType(make_StringConstant_t, new_line_str, ASRUtils::TYPE(ASR::make_String_t(al, loc, 1, 1, nullptr, ASR::string_physical_typeType::PointerString)), loc); + } + +} // namespace NewLine + namespace Adjustl { static ASR::expr_t *eval_Adjustl(Allocator &al, const Location &loc, @@ -3629,12 +4665,12 @@ namespace Adjustl { static inline ASR::expr_t* instantiate_Adjustl(Allocator &al, const Location &loc, SymbolTable *scope, Vec& arg_types, ASR::ttype_t *return_type, Vec& new_args, int64_t /*overload_id*/) { - declare_basic_variables("_lcompilers_optimization_adjustl_" + type_to_str_python(arg_types[0])); - fill_func_arg("str", ASRUtils::TYPE(ASR::make_Character_t(al, loc, 1, -1, nullptr))); - return_type = TYPE(ASR::make_Character_t(al, loc, 1, -3, EXPR(ASR::make_StringLen_t(al, loc, args[0], int32, nullptr)))); + declare_basic_variables("_lcompilers_adjustl_" + type_to_str_python(arg_types[0])); + fill_func_arg("str", ASRUtils::TYPE(ASR::make_String_t(al, loc, 1, -1, nullptr, ASR::string_physical_typeType::PointerString))); + return_type = TYPE(ASR::make_String_t(al, loc, 1, -3, EXPR(ASR::make_StringLen_t(al, loc, args[0], int32, nullptr)), ASR::string_physical_typeType::PointerString)); auto result = declare("result", return_type, ReturnVar); - auto itr = declare("i", ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)), Local); - auto tmp = declare("tmp", ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)), Local); + auto itr = declare("i", int32, Local); + auto tmp = declare("tmp", int32, Local); /* function adjustl_(s) result(r) @@ -3657,26 +4693,26 @@ namespace Adjustl { */ body.push_back(al, b.Assignment(itr, b.i32(1))); - body.push_back(al, b.While(b.iLtE(itr, b.StringLen(args[0])), { - b.If(b.iEq(ASRUtils::EXPR(ASR::make_Ichar_t(al, loc, + body.push_back(al, b.While(b.LtE(itr, b.StringLen(args[0])), { + b.If(b.Eq(ASRUtils::EXPR(ASR::make_Ichar_t(al, loc, ASRUtils::EXPR(ASR::make_StringItem_t(al, loc, args[0], itr, - ASRUtils::TYPE(ASR::make_Character_t(al, loc, 1, -1, nullptr)), nullptr)), int32, nullptr)), - b.Ichar(" ", ASRUtils::TYPE(ASR::make_Character_t(al, loc, 1, 1, nullptr)), int32)), { - b.Assignment(itr, b.i_tAdd(itr, b.i32(1), int32)) + ASRUtils::TYPE(ASR::make_String_t(al, loc, 1, -1, nullptr, ASR::string_physical_typeType::PointerString)), nullptr)), int32, nullptr)), + b.Ichar(" ", ASRUtils::TYPE(ASR::make_String_t(al, loc, 1, 1, nullptr, ASR::string_physical_typeType::PointerString)), int32)), { + b.Assignment(itr, b.Add(itr, b.i32(1))) }, { - b.Exit(nullptr) + b.Exit() }), })); - body.push_back(al, b.If(b.iLtE(itr, b.StringLen(args[0])), { - b.Assignment(tmp, b.iAdd(b.iSub(b.StringLen(args[0]), itr), b.i32(1))), - b.Assignment(b.StringSection(result, b.i32(0), tmp), b.StringSection(args[0], b.i_tSub(itr, b.i32(1), int32), b.StringLen(args[0]))) + body.push_back(al, b.If(b.LtE(itr, b.StringLen(args[0])), { + b.Assignment(tmp, b.Add(b.Sub(b.StringLen(args[0]), itr), b.i32(1))), + b.Assignment(b.StringSection(result, b.i32(0), tmp), b.StringSection(args[0], b.Sub(itr, b.i32(1)), b.StringLen(args[0]))) }, {})); ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); scope->add_symbol(fn_name, f_sym); - return_type = TYPE(ASR::make_Character_t(al, loc, 1, -3, EXPR(ASR::make_StringLen_t(al, loc, new_args[0].m_value, int32, nullptr)))); + return_type = TYPE(ASR::make_String_t(al, loc, 1, -3, EXPR(ASR::make_StringLen_t(al, loc, new_args[0].m_value, int32, nullptr)), ASR::string_physical_typeType::PointerString)); return b.Call(f_sym, new_args, return_type, nullptr); } @@ -3706,12 +4742,12 @@ namespace Adjustr { static inline ASR::expr_t* instantiate_Adjustr(Allocator &al, const Location &loc, SymbolTable *scope, Vec& arg_types, ASR::ttype_t *return_type, Vec& new_args, int64_t /*overload_id*/) { - declare_basic_variables("_lcompilers_optimization_adjustr_" + type_to_str_python(arg_types[0])); - fill_func_arg("str", ASRUtils::TYPE(ASR::make_Character_t(al, loc, 1, -1, nullptr))); - return_type = TYPE(ASR::make_Character_t(al, loc, 1, -3, EXPR(ASR::make_StringLen_t(al, loc, args[0], int32, nullptr)))); + declare_basic_variables("_lcompilers_adjustr_" + type_to_str_python(arg_types[0])); + fill_func_arg("str", ASRUtils::TYPE(ASR::make_String_t(al, loc, 1, -1, nullptr, ASR::string_physical_typeType::PointerString))); + return_type = TYPE(ASR::make_String_t(al, loc, 1, -3, EXPR(ASR::make_StringLen_t(al, loc, args[0], int32, nullptr)), ASR::string_physical_typeType::PointerString)); auto result = declare("result", return_type, ReturnVar); - auto itr = declare("i", ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)), Local); - auto tmp = declare("tmp", ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)), Local); + auto itr = declare("i", int32, Local); + auto tmp = declare("tmp", int32, Local); /* function adjustr_(s) result(r) @@ -3734,38 +4770,141 @@ namespace Adjustr { */ body.push_back(al, b.Assignment(itr, b.StringLen(args[0]))); - body.push_back(al, b.While(b.iGtE(itr, b.i32(1)), { - b.If(b.iEq(ASRUtils::EXPR(ASR::make_Ichar_t(al, loc, + body.push_back(al, b.While(b.GtE(itr, b.i32(1)), { + b.If(b.Eq(ASRUtils::EXPR(ASR::make_Ichar_t(al, loc, ASRUtils::EXPR(ASR::make_StringItem_t(al, loc, args[0], itr, - ASRUtils::TYPE(ASR::make_Character_t(al, loc, 1, -1, nullptr)), nullptr)), int32, nullptr)), - b.Ichar(" ", ASRUtils::TYPE(ASR::make_Character_t(al, loc, 1, 1, nullptr)), int32)), { - b.Assignment(itr, b.i_tSub(itr, b.i32(1), int32)) + ASRUtils::TYPE(ASR::make_String_t(al, loc, 1, -1, nullptr, ASR::string_physical_typeType::PointerString)), nullptr)), int32, nullptr)), + b.Ichar(" ", ASRUtils::TYPE(ASR::make_String_t(al, loc, 1, 1, nullptr, ASR::string_physical_typeType::PointerString)), int32)), { + b.Assignment(itr, b.Sub(itr, b.i32(1))) }, { - b.Exit(nullptr) + b.Exit() }), })); - body.push_back(al, b.If(b.iNotEq(itr, b.i32(0)), { - b.Assignment(tmp, b.iAdd(b.iSub(b.StringLen(args[0]), itr), b.i32(1))), - b.Assignment(b.StringSection(result, b.iSub(tmp, b.i32(1)), b.StringLen(args[0])), + body.push_back(al, b.If(b.NotEq(itr, b.i32(0)), { + b.Assignment(tmp, b.Add(b.Sub(b.StringLen(args[0]), itr), b.i32(1))), + b.Assignment(b.StringSection(result, b.Sub(tmp, b.i32(1)), b.StringLen(args[0])), b.StringSection(args[0], b.i32(0), itr)) }, {})); ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); scope->add_symbol(fn_name, f_sym); - return_type = TYPE(ASR::make_Character_t(al, loc, 1, -3, EXPR(ASR::make_StringLen_t(al, loc, new_args[0].m_value, int32, nullptr)))); + return_type = TYPE(ASR::make_String_t(al, loc, 1, -3, EXPR(ASR::make_StringLen_t(al, loc, new_args[0].m_value, int32, nullptr)), ASR::string_physical_typeType::PointerString)); return b.Call(f_sym, new_args, return_type, nullptr); } } // namespace Adjustr +namespace StringLenTrim { + + static ASR::expr_t *eval_StringLenTrim(Allocator &al, const Location &loc, + ASR::ttype_t* t1, Vec &args, diag::Diagnostics& /*diag*/) { + char* str = ASR::down_cast(args[0])->m_s; + size_t len = std::strlen(str); + for (int i = len - 1; i >= 0; i--) { + if (!std::isspace(str[i])) { + return make_ConstantWithType(make_IntegerConstant_t, i + 1, t1, loc); + } + } + return make_ConstantWithType(make_IntegerConstant_t, 0, t1, loc); + } + + static inline ASR::expr_t* instantiate_StringLenTrim(Allocator &al, const Location &loc, + SymbolTable *scope, Vec& arg_types, ASR::ttype_t *return_type, + Vec& new_args, int64_t /*overload_id*/) { + declare_basic_variables("_lcompilers_len_trim_" + type_to_str_python(arg_types[0])); + fill_func_arg("str", ASRUtils::TYPE(ASR::make_String_t(al, loc, 1, -1, nullptr, ASR::string_physical_typeType::PointerString))); + auto result = declare("result", return_type, ReturnVar); + + /* + function len_trim(string) result(r) + character(len=*), intent(in) :: string + r = len(string) + if (r/= 0) then + do while(string(r:r) == " ") + r = r - 1 + if (r == 0) exit + end do + end if + end function + */ + + body.push_back(al, b.Assignment(result, b.StringLen(args[0]))); + body.push_back(al, b.If(b.NotEq(result, b.i32(0)), { + b.While(b.Eq(b.StringItem(args[0], result), b.StringConstant(" ", arg_types[0])), { + b.Assignment(result, b.Sub(result, b.i32(1))), + b.If(b.Eq(result, b.i32(0)), { + b.Exit() + }, {}) + }) + }, {})); + + ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, + body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); + scope->add_symbol(fn_name, f_sym); + return b.Call(f_sym, new_args, return_type, nullptr); + } + static inline ASR::expr_t* StringLenTrim(ASRBuilder &b, ASR::expr_t* a, ASR::ttype_t *return_type, SymbolTable* scope) { + return b.CallIntrinsic(scope, {expr_type(a)}, {a}, return_type, 0, StringLenTrim::instantiate_StringLenTrim); + } + +} // namespace StringLenTrim + +namespace StringTrim { + + static ASR::expr_t *eval_StringTrim(Allocator &al, const Location &loc, + ASR::ttype_t* t1, Vec &args, diag::Diagnostics& /*diag*/) { + char* str = ASR::down_cast(args[0])->m_s; + size_t len = strlen(str); + if (len > 0) { + char* endptr = str + len - 1; + while (endptr >= str && std::isspace(*endptr)) { + *endptr = '\0'; + --endptr; + } + } + return make_ConstantWithType(make_StringConstant_t, str, t1, loc); + } + + static inline ASR::expr_t* instantiate_StringTrim(Allocator &al, const Location &loc, + SymbolTable *scope, Vec& arg_types, ASR::ttype_t *return_type, + Vec& new_args, int64_t /*overload_id*/) { + declare_basic_variables("_lcompilers_trim_" + type_to_str_python(arg_types[0])); + fill_func_arg("str", ASRUtils::TYPE(ASR::make_String_t(al, loc, 1, -1, nullptr, ASR::string_physical_typeType::PointerString))); + ASR::expr_t* func_call_lentrim = StringLenTrim::StringLenTrim(b, args[0], int32, scope); + return_type = TYPE(ASR::make_String_t(al, loc, 1, -3, func_call_lentrim, ASR::string_physical_typeType::PointerString)); + auto result = declare("result", return_type, ReturnVar); + + /* + function trim(string) result(r) + character(len=*), intent(in) :: string + l = len_trim(string) + r = x(1:l) + end function + */ + + body.push_back(al, b.Assignment(result, b.StringSection(args[0], b.i32(0), func_call_lentrim))); + + ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, + body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); + return_type = TYPE(ASR::make_String_t(al, loc, 1, -3, EXPR(ASR::make_StringLen_t(al, loc, new_args[0].m_value, int32, nullptr)), ASR::string_physical_typeType::PointerString)); + scope->add_symbol(fn_name, f_sym); + return b.Call(f_sym, new_args, return_type, nullptr); + } + +} // namespace StringTrim namespace Ichar { static ASR::expr_t *eval_Ichar(Allocator &al, const Location &loc, - ASR::ttype_t* t1, Vec &args, diag::Diagnostics& /*diag*/) { + ASR::ttype_t* t1, Vec &args, diag::Diagnostics& diag) { char* str = ASR::down_cast(args[0])->m_s; + int64_t len = std::strlen(str); + if (len != 1) { + append_error(diag, "Argument to Ichar must have length one", loc); + return nullptr; + } char first_char = str[0]; int result = (int)first_char; return make_ConstantWithType(make_IntegerConstant_t, result, t1, loc); @@ -3774,15 +4913,14 @@ namespace Ichar { static inline ASR::expr_t* instantiate_Ichar(Allocator &al, const Location &loc, SymbolTable *scope, Vec& arg_types, ASR::ttype_t *return_type, Vec& new_args, int64_t /*overload_id*/) { - declare_basic_variables("_lcompilers_optimization_ichar_" + type_to_str_python(arg_types[0])); - fill_func_arg("str", ASRUtils::TYPE(ASR::make_Character_t(al, loc, 1, -1, nullptr))); + declare_basic_variables("_lcompilers_ichar_" + type_to_str_python(arg_types[0])); + fill_func_arg("str", ASRUtils::TYPE(ASR::make_String_t(al, loc, 1, -1, nullptr, ASR::string_physical_typeType::PointerString))); auto result = declare("result", return_type, ReturnVar); - auto itr = declare("i", ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)), Local); + auto itr = declare("i", int32, Local); body.push_back(al, b.Assignment(itr, b.i32(1))); - body.push_back(al, b.Assignment(result, b.i2i( + body.push_back(al, b.Assignment(result, b.i2i_t( ASRUtils::EXPR(ASR::make_Ichar_t(al, loc, ASRUtils::EXPR(ASR::make_StringItem_t(al, loc, args[0], itr, - ASRUtils::TYPE(ASR::make_Character_t(al, loc, 1, -1, nullptr)), nullptr)), int32, nullptr)), - return_type))); + ASRUtils::TYPE(ASR::make_String_t(al, loc, 1, -1, nullptr, ASR::string_physical_typeType::PointerString)), nullptr)), int32, nullptr)), return_type))); ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); @@ -3809,11 +4947,11 @@ namespace Char { static inline ASR::expr_t* instantiate_Char(Allocator &al, const Location &loc, SymbolTable *scope, Vec& arg_types, ASR::ttype_t *return_type, Vec& new_args, int64_t /*overload_id*/) { - declare_basic_variables(""); + declare_basic_variables("_lcompilers_char_" + type_to_str_python(arg_types[0])); fill_func_arg("i", arg_types[0]); auto result = declare("result", return_type, ReturnVar); - body.push_back(al, b.Assignment(result, ASRUtils::EXPR(ASR::make_StringChr_t(al, loc, b.i2i(args[0], int32), return_type, nullptr)))); + body.push_back(al, b.Assignment(result, ASRUtils::EXPR(ASR::make_StringChr_t(al, loc, b.i2i_t(args[0], int32), return_type, nullptr)))); ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); scope->add_symbol(fn_name, f_sym); @@ -3822,6 +4960,31 @@ namespace Char { } // namespace Char +namespace Achar { + + static ASR::expr_t *eval_Achar(Allocator &al, const Location &loc, + ASR::ttype_t* t1, Vec &args, diag::Diagnostics& /*diag*/) { + int64_t i = ASR::down_cast(args[0])->m_n; + std::string svalue(1, static_cast(i)); + return make_ConstantWithType(make_StringConstant_t, s2c(al, svalue), t1, loc); + } + + static inline ASR::expr_t* instantiate_Achar(Allocator &al, const Location &loc, + SymbolTable *scope, Vec& arg_types, ASR::ttype_t *return_type, + Vec& new_args, int64_t /*overload_id*/) { + declare_basic_variables("_lcompilers_achar_" + type_to_str_python(arg_types[0])); + fill_func_arg("i", arg_types[0]); + auto result = declare("result", return_type, ReturnVar); + body.push_back(al, b.Assignment(result, ASRUtils::EXPR(ASR::make_StringChr_t(al, loc, args[0], return_type, nullptr)))); + + ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, + body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); + scope->add_symbol(fn_name, f_sym); + return b.Call(f_sym, new_args, return_type, nullptr); + } + +} // namespace Achar + namespace Digits { static ASR::expr_t *eval_Digits(Allocator &al, const Location &loc, @@ -3829,7 +4992,11 @@ namespace Digits { ASR::ttype_t *type1 = ASRUtils::expr_type(args[0]); int kind = ASRUtils::extract_kind_from_ttype_t(ASRUtils::expr_type(args[0])); if (is_integer(*type1)) { - if (kind == 4) { + if (kind == 1) { + return make_ConstantWithType(make_IntegerConstant_t, 7, int32, loc); + } else if (kind == 2) { + return make_ConstantWithType(make_IntegerConstant_t, 15, int32, loc); + } else if (kind == 4) { return make_ConstantWithType(make_IntegerConstant_t, 31, int32, loc); } else if (kind == 8) { return make_ConstantWithType(make_IntegerConstant_t, 63, int32, loc); @@ -3931,11 +5098,11 @@ namespace Rrspacing { * r = rrspacing(X) * r = abs(fraction(X)) * (radix(X)**digits(X)) */ - body.push_back(al, b.Assignment(result, b.r_tMul(b.CallIntrinsic(scope, {arg_types[0]}, { + body.push_back(al, b.Assignment(result, b.Mul(b.CallIntrinsic(scope, {arg_types[0]}, { b.CallIntrinsic(scope, {arg_types[0]}, {args[0]}, return_type, 0, Fraction::instantiate_Fraction)}, - return_type, 0, Abs::instantiate_Abs), b.rPow(b.i2r(b.i32(2),return_type), - b.i2r(b.CallIntrinsic(scope, {arg_types[0]}, {args[0]}, int32, 0, Digits::instantiate_Digits), - return_type), return_type), return_type))); + return_type, 0, Abs::instantiate_Abs), b.Pow(b.i2r_t(b.i32(2), return_type), + b.i2r_t(b.CallIntrinsic(scope, {arg_types[0]}, {args[0]}, int32, 0, Digits::instantiate_Digits), + return_type))))); ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); @@ -3972,12 +5139,12 @@ namespace Repeat { ASR::symbol_t *s = scope->get_symbol(func_name); return b.Call(s, new_args, return_type, nullptr); } - fill_func_arg("x", ASRUtils::TYPE(ASR::make_Character_t(al, loc, 1, -10, nullptr))); + fill_func_arg("x", ASRUtils::TYPE(ASR::make_String_t(al, loc, 1, -10, nullptr, ASR::string_physical_typeType::PointerString))); fill_func_arg("y", arg_types[1]); - auto result = declare(fn_name, ASRUtils::TYPE(ASR::make_Character_t(al, loc, 1, -3, + auto result = declare(fn_name, ASRUtils::TYPE(ASR::make_String_t(al, loc, 1, -3, ASRUtils::EXPR(ASR::make_IntegerBinOp_t(al, loc, ASRUtils::EXPR(ASR::make_StringLen_t(al, loc, args[0], ASRUtils::expr_type(args[1]), nullptr)), - ASR::binopType::Mul, args[1], ASRUtils::expr_type(args[1]), nullptr)))), ReturnVar); + ASR::binopType::Mul, args[1], ASRUtils::expr_type(args[1]), nullptr)), ASR::string_physical_typeType::PointerString)), ReturnVar); auto i = declare("i", int32, Local); auto j = declare("j", int32, Local); auto m = declare("m", int32, Local); @@ -4005,12 +5172,12 @@ namespace Repeat { body.push_back(al, b.Assignment(i, b.i32(1))); body.push_back(al, b.Assignment(j, m)); body.push_back(al, b.Assignment(cnt, b.i32(0))); - body.push_back(al, b.While(b.iLt(cnt, CastingUtil::perform_casting(args[1], int32, al, loc)), { - b.Assignment(b.StringSection(result, b.iSub(i, b.i32(1)), j), + body.push_back(al, b.While(b.Lt(cnt, CastingUtil::perform_casting(args[1], int32, al, loc)), { + b.Assignment(b.StringSection(result, b.Sub(i, b.i32(1)), j), b.StringSection(args[0], b.i32(0), b.StringLen(args[0]))), - b.Assignment(i, b.iAdd(j, b.i32(1))), - b.Assignment(j, b.iSub(b.iAdd(i, m), b.i32(1))), - b.Assignment(cnt, b.iAdd(cnt, b.i32(1))), + b.Assignment(i, b.Add(j, b.i32(1))), + b.Assignment(j, b.Sub(b.Add(i, m), b.i32(1))), + b.Assignment(cnt, b.Add(cnt, b.i32(1))), })); ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, @@ -4024,11 +5191,10 @@ namespace Repeat { namespace StringContainsSet { static ASR::expr_t *eval_StringContainsSet(Allocator &al, const Location &loc, - ASR::ttype_t* /*t1*/, Vec &args, diag::Diagnostics& /*diag*/) { + ASR::ttype_t* t1, Vec &args, diag::Diagnostics& /*diag*/) { char* string = ASR::down_cast(args[0])->m_s; char* set = ASR::down_cast(args[1])->m_s; bool back = ASR::down_cast(args[2])->m_value; - int64_t kind = ASR::down_cast(args[3])->m_n; size_t len = std::strlen(string); int64_t result = 0; if (back) { @@ -4046,23 +5212,21 @@ namespace StringContainsSet { } } } - - ASR::ttype_t* return_type = ASRUtils::TYPE(ASR::make_Integer_t(al, loc, kind)); - return make_ConstantWithType(make_IntegerConstant_t, result, return_type, loc); + return make_ConstantWithType(make_IntegerConstant_t, result, t1, loc); } static inline ASR::expr_t* instantiate_StringContainsSet(Allocator &al, const Location &loc, SymbolTable* scope, Vec& arg_types, ASR::ttype_t *return_type, Vec& new_args, int64_t /*overload_id*/) { declare_basic_variables("_lcompilers_verify_" + type_to_str_python(arg_types[0])); - fill_func_arg("str", ASRUtils::TYPE(ASR::make_Character_t(al, loc, 1, -1, nullptr))); - fill_func_arg("set", ASRUtils::TYPE(ASR::make_Character_t(al, loc, 1, -1, nullptr))); + fill_func_arg("str", ASRUtils::TYPE(ASR::make_String_t(al, loc, 1, -1, nullptr, ASR::string_physical_typeType::PointerString))); + fill_func_arg("set", ASRUtils::TYPE(ASR::make_String_t(al, loc, 1, -1, nullptr, ASR::string_physical_typeType::PointerString))); fill_func_arg("back", ASRUtils::TYPE(ASR::make_Logical_t(al, loc, 4))); - fill_func_arg("kind", ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4))); + fill_func_arg("kind", int32); auto result = declare(fn_name, return_type, ReturnVar); - auto matched = declare("matched", arg_types[2], Local); - auto i = declare("i", ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)), Local); - auto j = declare("j", ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)), Local); + auto matched = declare("matched", logical, Local); + auto i = declare("i", int32, Local); + auto j = declare("j", int32, Local); /* function StringContainsSet_(string, set, back, kind) result(result) character(len=*) :: string @@ -4108,42 +5272,42 @@ namespace StringContainsSet { end if end function */ - body.push_back(al, b.Assignment(result, b.i(0, return_type))); - body.push_back(al, b.If(b.boolEq(args[2], b.bool32(1)), { + body.push_back(al, b.Assignment(result, b.i_t(0, return_type))); + body.push_back(al, b.If(b.Eq(args[2], b.bool_t(1, logical)), { b.Assignment(i, b.StringLen(args[0])), - b.While(b.iGtE(i, b.i(1, return_type)), { - b.Assignment(matched, b.bool32(0)), - b.Assignment(j, b.i(1, return_type)), - b.While(b.iLtE(j, b.StringLen(args[1])), { - b.If(b.sEq(b.StringSection(args[0], b.i_tSub(i, b.i(1, return_type), return_type), i), - b.StringSection(args[1], b.i_tSub(j, b.i(1, return_type), return_type), j)), { - b.Assignment(matched, b.bool32(1)) + b.While(b.GtE(i, b.i_t(1, return_type)), { + b.Assignment(matched, b.bool_t(0, logical)), + b.Assignment(j, b.i_t(1, return_type)), + b.While(b.LtE(j, b.StringLen(args[1])), { + b.If(b.Eq(b.StringSection(args[0], b.Sub(i, b.i_t(1, return_type)), i), + b.StringSection(args[1], b.Sub(j, b.i_t(1, return_type)), j)), { + b.Assignment(matched, b.bool_t(1, logical)) }, {}), - b.Assignment(j, b.i_tAdd(j, b.i(1, return_type), return_type)), + b.Assignment(j, b.Add(j, b.i_t(1, return_type))), }), - b.If(b.boolEq(matched, b.bool32(0)), { + b.If(b.Eq(matched, b.bool_t(0, logical)), { b.Assignment(result, i), - b.Exit(nullptr) + b.Exit() }, {}), - b.Assignment(i, b.i_tSub(i, b.i(1, return_type), return_type)), + b.Assignment(i, b.Sub(i, b.i_t(1, return_type))), }), }, { - b.Assignment(i, b.i(1, return_type)), - b.While(b.iLtE(i, b.StringLen(args[0])), { - b.Assignment(matched, b.bool32(0)), - b.Assignment(j, b.i(1, return_type)), - b.While(b.iLtE(j, b.StringLen(args[1])), { - b.If(b.sEq(b.StringSection(args[0], b.i_tSub(i, b.i(1, return_type), return_type), i), - b.StringSection(args[1], b.i_tSub(j, b.i(1, return_type), return_type), j)), { - b.Assignment(matched, b.bool32(1)) + b.Assignment(i, b.i_t(1, return_type)), + b.While(b.LtE(i, b.StringLen(args[0])), { + b.Assignment(matched, b.bool_t(0, logical)), + b.Assignment(j, b.i_t(1, return_type)), + b.While(b.LtE(j, b.StringLen(args[1])), { + b.If(b.Eq(b.StringSection(args[0], b.Sub(i, b.i_t(1, return_type)), i), + b.StringSection(args[1], b.Sub(j, b.i_t(1, return_type)), j)), { + b.Assignment(matched, b.bool_t(1, logical)) }, {}), - b.Assignment(j, b.i_tAdd(j, b.i(1, return_type), return_type)), + b.Assignment(j, b.Add(j, b.i_t(1, return_type))), }), - b.If(b.boolEq(matched, b.bool32(0)), { + b.If(b.Eq(matched, b.bool_t(0, logical)), { b.Assignment(result, i), - b.Exit(nullptr) + b.Exit() }, {}), - b.Assignment(i, b.i_tAdd(i, b.i(1, return_type), return_type)) + b.Assignment(i, b.Add(i, b.i_t(1, return_type))) }), })); @@ -4158,11 +5322,10 @@ namespace StringContainsSet { namespace StringFindSet { static ASR::expr_t *eval_StringFindSet(Allocator &al, const Location &loc, - ASR::ttype_t* /*t1*/, Vec &args, diag::Diagnostics& /*diag*/) { + ASR::ttype_t* t1, Vec &args, diag::Diagnostics& /*diag*/) { char* string = ASR::down_cast(args[0])->m_s; char* set = ASR::down_cast(args[1])->m_s; bool back = ASR::down_cast(args[2])->m_value; - int64_t kind = ASR::down_cast(args[3])->m_n; size_t len = std::strlen(string); int64_t result = 0; if (back) { @@ -4180,22 +5343,20 @@ namespace StringFindSet { } } } - - ASR::ttype_t* return_type = ASRUtils::TYPE(ASR::make_Integer_t(al, loc, kind)); - return make_ConstantWithType(make_IntegerConstant_t, result, return_type, loc); + return make_ConstantWithType(make_IntegerConstant_t, result, t1, loc); } static inline ASR::expr_t* instantiate_StringFindSet(Allocator &al, const Location &loc, SymbolTable* scope, Vec& arg_types, ASR::ttype_t *return_type, Vec& new_args, int64_t /*overload_id*/) { declare_basic_variables("_lcompilers_scan_" + type_to_str_python(arg_types[0])); - fill_func_arg("str", ASRUtils::TYPE(ASR::make_Character_t(al, loc, 1, -1, nullptr))); - fill_func_arg("set", ASRUtils::TYPE(ASR::make_Character_t(al, loc, 1, -1, nullptr))); + fill_func_arg("str", ASRUtils::TYPE(ASR::make_String_t(al, loc, 1, -1, nullptr, ASR::string_physical_typeType::PointerString))); + fill_func_arg("set", ASRUtils::TYPE(ASR::make_String_t(al, loc, 1, -1, nullptr, ASR::string_physical_typeType::PointerString))); fill_func_arg("back", ASRUtils::TYPE(ASR::make_Logical_t(al, loc, 4))); - fill_func_arg("kind", ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4))); + fill_func_arg("kind", int32); auto result = declare(fn_name, return_type, ReturnVar); - auto i = declare("i", ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)), Local); - auto j = declare("j", ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)), Local); + auto i = declare("i", int32, Local); + auto j = declare("j", int32, Local); /* function StringFindSet_(string, set, back, kind) result(r) character(len=*) :: string @@ -4235,40 +5396,40 @@ namespace StringFindSet { end function */ - body.push_back(al, b.Assignment(result, b.i(0, return_type))); - body.push_back(al, b.If(b.boolEq(args[2], b.bool32(1)), { + body.push_back(al, b.Assignment(result, b.i_t(0, return_type))); + body.push_back(al, b.If(b.Eq(args[2], b.bool_t(1, arg_types[2])), { b.Assignment(i, b.StringLen(args[0])), - b.While(b.iGtE(i, b.i(1, return_type)), { - b.Assignment(j, b.i(1, return_type)), - b.While(b.iLtE(j, b.StringLen(args[1])), { - b.If(b.sEq(b.StringSection(args[0], b.i_tSub(i, b.i(1, return_type), return_type), i), - b.StringSection(args[1], b.i_tSub(j, b.i(1, return_type), return_type), j)), { + b.While(b.GtE(i, b.i_t(1, return_type)), { + b.Assignment(j, b.i_t(1, return_type)), + b.While(b.LtE(j, b.StringLen(args[1])), { + b.If(b.Eq(b.StringSection(args[0], b.Sub(i, b.i_t(1, return_type)), i), + b.StringSection(args[1], b.Sub(j, b.i_t(1, return_type)), j)), { b.Assignment(result, i), - b.Exit(nullptr) + b.Exit() }, {}), - b.Assignment(j, b.i_tAdd(j, b.i(1, return_type), return_type)), + b.Assignment(j, b.Add(j, b.i_t(1, return_type))), }), - b.If(b.iNotEq(result, b.i(0, return_type)), { - b.Exit(nullptr) + b.If(b.NotEq(result, b.i_t(0, return_type)), { + b.Exit() }, {}), - b.Assignment(i, b.i_tSub(i, b.i(1, return_type), return_type)) + b.Assignment(i, b.Sub(i, b.i_t(1, return_type))) }), }, { - b.Assignment(i, b.i(1, return_type)), - b.While(b.iLtE(i, b.StringLen(args[0])), { - b.Assignment(j, b.i(1, return_type)), - b.While(b.iLtE(j, b.StringLen(args[1])), { - b.If(b.sEq(b.StringSection(args[0], b.i_tSub(i, b.i(1, return_type), return_type), i), - b.StringSection(args[1], b.i_tSub(j, b.i(1, return_type), return_type), j)), { + b.Assignment(i, b.i_t(1, return_type)), + b.While(b.LtE(i, b.StringLen(args[0])), { + b.Assignment(j, b.i_t(1, return_type)), + b.While(b.LtE(j, b.StringLen(args[1])), { + b.If(b.Eq(b.StringSection(args[0], b.Sub(i, b.i_t(1, return_type)), i), + b.StringSection(args[1], b.Sub(j, b.i_t(1, return_type)), j)), { b.Assignment(result, i), - b.Exit(nullptr) + b.Exit() }, {}), - b.Assignment(j, b.i_tAdd(j, b.i(1, return_type), return_type)), + b.Assignment(j, b.Add(j, b.i_t(1, return_type))), }), - b.If(b.iNotEq(result, b.i(0, return_type)), { - b.Exit(nullptr) + b.If(b.NotEq(result, b.i_t(0, return_type)), { + b.Exit() }, {}), - b.Assignment(i, b.i_tAdd(i, b.i(1, return_type), return_type)) + b.Assignment(i, b.Add(i, b.i_t(1, return_type))) }), })); @@ -4314,16 +5475,16 @@ namespace SubstrIndex { SymbolTable* scope, Vec& arg_types, ASR::ttype_t *return_type, Vec& new_args, int64_t /*overload_id*/) { declare_basic_variables("_lcompilers_index_" + type_to_str_python(arg_types[0])); - fill_func_arg("str", ASRUtils::TYPE(ASR::make_Character_t(al, loc, 1, -1, nullptr))); - fill_func_arg("substr", ASRUtils::TYPE(ASR::make_Character_t(al, loc, 1, -1, nullptr))); + fill_func_arg("str", ASRUtils::TYPE(ASR::make_String_t(al, loc, 1, -1, nullptr, ASR::string_physical_typeType::PointerString))); + fill_func_arg("substr", ASRUtils::TYPE(ASR::make_String_t(al, loc, 1, -1, nullptr, ASR::string_physical_typeType::PointerString))); fill_func_arg("back", ASRUtils::TYPE(ASR::make_Logical_t(al, loc, 4))); - fill_func_arg("kind", ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4))); + fill_func_arg("kind", int32); auto idx = declare(fn_name, return_type, ReturnVar); auto found = declare("found", arg_types[2], Local); - auto i = declare("i", ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)), Local); - auto j = declare("j", ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)), Local); - auto k = declare("k", ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)), Local); - auto pos = declare("pos", ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)), Local); + auto i = declare("i", int32, Local); + auto j = declare("j", int32, Local); + auto k = declare("k", int32, Local); + auto pos = declare("pos", int32, Local); /* function SubstrIndex_(string, substring, back, kind) result(r) @@ -4366,33 +5527,33 @@ namespace SubstrIndex { end do end function */ - body.push_back(al, b.Assignment(idx, b.i(0, return_type))); - body.push_back(al, b.Assignment(i, b.i(1, return_type))); - body.push_back(al, b.Assignment(found, b.bool32(1))); - body.push_back(al, b.If(b.iLt(b.StringLen(args[0]), b.StringLen(args[1])), { - b.Assignment(found, b.bool32(0)) + body.push_back(al, b.Assignment(idx, b.i_t(0, return_type))); + body.push_back(al, b.Assignment(i, b.i_t(1, return_type))); + body.push_back(al, b.Assignment(found, b.bool_t(1, arg_types[2]))); + body.push_back(al, b.If(b.Lt(b.StringLen(args[0]), b.StringLen(args[1])), { + b.Assignment(found, b.bool_t(0, arg_types[2])) }, {})); - body.push_back(al, b.While(b.And(b.iLt(i, b.StringLen(args[0])), b.boolEq(found, b.bool32(1))), { - b.Assignment(k, b.i(0, return_type)), - b.Assignment(j, b.i(1, return_type)), - b.While(b.And(b.iLtE(j, b.StringLen(args[1])), b.boolEq(found, b.bool32(1))), { - b.Assignment(pos, b.i_tAdd(i, k, return_type)), - b.If(b.sNotEq( - b.StringSection(args[0], b.i_tSub(pos, b.i(1, return_type), return_type), pos), - b.StringSection(args[1], b.i_tSub(j, b.i(1, return_type), return_type), j)), { - b.Assignment(found, b.bool32(0)) + body.push_back(al, b.While(b.And(b.Lt(i, b.Add(b.StringLen(args[0]), b.i32(1))), b.Eq(found, b.bool_t(1, arg_types[2]))), { + b.Assignment(k, b.i_t(0, return_type)), + b.Assignment(j, b.i_t(1, return_type)), + b.While(b.And(b.LtE(j, b.StringLen(args[1])), b.Eq(found, b.bool_t(1, arg_types[2]))), { + b.Assignment(pos, b.Add(i, k)), + b.If(b.NotEq( + b.StringSection(args[0], b.Sub(pos, b.i_t(1, return_type)), pos), + b.StringSection(args[1], b.Sub(j, b.i_t(1, return_type)), j)), { + b.Assignment(found, b.bool_t(0, arg_types[2])) }, {}), - b.Assignment(j, b.i_tAdd(j, b.i(1, return_type), return_type)), - b.Assignment(k, b.i_tAdd(k, b.i(1, return_type), return_type)), + b.Assignment(j, b.Add(j, b.i_t(1, return_type))), + b.Assignment(k, b.Add(k, b.i_t(1, return_type))), }), - b.If(b.boolEq(found, b.bool32(1)), { + b.If(b.Eq(found, b.bool_t(1, arg_types[2])), { b.Assignment(idx, i), b.Assignment(found, args[2]) }, { - b.Assignment(found, b.bool32(1)) + b.Assignment(found, b.bool_t(1, arg_types[2])) }), - b.Assignment(i, b.i_tAdd(i, b.i(1, return_type), return_type)), + b.Assignment(i, b.Add(i, b.i_t(1, return_type))), })); ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, @@ -4407,8 +5568,7 @@ namespace MinExponent { static ASR::expr_t *eval_MinExponent(Allocator &al, const Location &loc, ASR::ttype_t* /*t1*/, Vec &args, diag::Diagnostics& /*diag*/) { - ASR::RealConstant_t* a = ASR::down_cast(args[0]); - int m_kind = ASRUtils::extract_kind_from_ttype_t(a->m_type); + int m_kind = ASRUtils::extract_kind_from_ttype_t(ASRUtils::expr_type(args[0])); int result; if (m_kind == 4) { result = std::numeric_limits::min_exponent; @@ -4416,27 +5576,6 @@ namespace MinExponent { result = std::numeric_limits::min_exponent; } return make_ConstantWithType(make_IntegerConstant_t, result, int32, loc); - - } - - static inline ASR::expr_t* instantiate_MinExponent(Allocator &al, const Location &loc, - SymbolTable *scope, Vec& arg_types, ASR::ttype_t *return_type, - Vec& new_args, int64_t /*overload_id*/) { - declare_basic_variables("_lcompilers_optimization_minexponent_" + type_to_str_python(arg_types[0])); - fill_func_arg("x", arg_types[0]); - auto result = declare(fn_name, int32, ReturnVar); - - int m_kind = ASRUtils::extract_kind_from_ttype_t(arg_types[0]); - if (m_kind == 4) { - body.push_back(al, b.Assignment(result, b.i32(-125))); - } else { - body.push_back(al, b.Assignment(result, b.i32(-1021))); - } - - ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, - body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); - scope->add_symbol(fn_name, f_sym); - return b.Call(f_sym, new_args, return_type, nullptr); } } // namespace MinExponent @@ -4445,8 +5584,7 @@ namespace MaxExponent { static ASR::expr_t *eval_MaxExponent(Allocator &al, const Location &loc, ASR::ttype_t* /*t1*/, Vec &args, diag::Diagnostics& /*diag*/) { - ASR::RealConstant_t* a = ASR::down_cast(args[0]); - int m_kind = ASRUtils::extract_kind_from_ttype_t(a->m_type); + int m_kind = ASRUtils::extract_kind_from_ttype_t(ASRUtils::expr_type(args[0])); int result; if (m_kind == 4) { result = std::numeric_limits::max_exponent; @@ -4454,27 +5592,6 @@ namespace MaxExponent { result = std::numeric_limits::max_exponent; } return make_ConstantWithType(make_IntegerConstant_t, result, int32, loc); - - } - - static inline ASR::expr_t* instantiate_MaxExponent(Allocator &al, const Location &loc, - SymbolTable *scope, Vec& arg_types, ASR::ttype_t *return_type, - Vec& new_args, int64_t /*overload_id*/) { - declare_basic_variables("_lcompilers_optimization_maxexponent_" + type_to_str_python(arg_types[0])); - fill_func_arg("x", arg_types[0]); - auto result = declare(fn_name, int32, ReturnVar); - - int m_kind = ASRUtils::extract_kind_from_ttype_t(arg_types[0]); - if (m_kind == 4) { - body.push_back(al, b.Assignment(result, b.i32(128))); - } else { - body.push_back(al, b.Assignment(result, b.i32(1024))); - } - - ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, - body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); - scope->add_symbol(fn_name, f_sym); - return b.Call(f_sym, new_args, return_type, nullptr); } } // namespace MaxExponent @@ -4491,23 +5608,6 @@ namespace X { } \ return nullptr; \ } \ - static inline ASR::asr_t* create_##X(Allocator& al, const Location& loc, \ - Vec& args, \ - diag::Diagnostics& diag) { \ - if (args.size() != 1) { \ - append_error(diag, "Intrinsic function `"#X"` accepts exactly 1 argument", \ - loc); \ - return nullptr; \ - } \ - ASR::ttype_t *type = ASRUtils::expr_type(args[0]); \ - if (!ASRUtils::is_real(*type)) { \ - append_error(diag, "Argument of the `"#X"` function must be either Real", \ - args[0]->base.loc); \ - return nullptr; \ - } \ - return UnaryIntrinsicFunction::create_UnaryFunction(al, loc, args, eval_##X, \ - static_cast(IntrinsicElementalFunctions::X), 0, type, diag); \ - } \ } // namespace X create_exp_macro(Exp2, exp2) @@ -4533,24 +5633,6 @@ namespace Exp { return nullptr; } - static inline ASR::asr_t* create_Exp(Allocator& al, const Location& loc, - Vec& args, - diag::Diagnostics& diag) { - if (args.size() != 1) { - append_error(diag, "Intrinsic function `exp` accepts exactly 1 argument", loc); - return nullptr; - } - ASR::ttype_t *type = ASRUtils::expr_type(args[0]); - if (!ASRUtils::is_real(*type) && !is_complex(*type)) { - append_error(diag, "Argument of the `exp` function must be either Real or Complex", - args[0]->base.loc); - return nullptr; - } - return UnaryIntrinsicFunction::create_UnaryFunction(al, loc, args, - eval_Exp, static_cast(IntrinsicElementalFunctions::Exp), - 0, type, diag); - } - static inline ASR::expr_t* instantiate_Exp(Allocator &al, const Location &loc, SymbolTable *scope, Vec& arg_types, ASR::ttype_t *return_type, Vec& new_args, int64_t overload_id) { @@ -4568,6 +5650,39 @@ namespace Exp { } // namespace Exp +namespace ErfcScaled { + + static inline ASR::expr_t* eval_ErfcScaled(Allocator &al, const Location &loc, + ASR::ttype_t *t, Vec &args, diag::Diagnostics& /*diag*/) { + LCOMPILERS_ASSERT(ASRUtils::all_args_evaluated(args)); + double val = ASR::down_cast(args[0])->m_r; + double result = std::exp(std::pow(val, 2)) * std::erfc(val); + return make_ConstantWithType(make_RealConstant_t, result, t, loc); + } + + static inline ASR::expr_t* instantiate_ErfcScaled(Allocator &al, const Location &loc, + SymbolTable *scope, Vec& arg_types, ASR::ttype_t *return_type, + Vec& new_args, int64_t /*overload_id*/) { + declare_basic_variables("_lcompilers_erfc_scaled_" + type_to_str_python(arg_types[0])); + fill_func_arg("x", arg_types[0]); + auto result = declare(fn_name, return_type, ReturnVar); + /* + * r = erfc_scaled(x) + * r = exp(x**2) * erfc(x) + */ + + body.push_back(al, b.Assignment(result, b.Mul( + b.CallIntrinsic(scope, {arg_types[0]}, {b.Pow(args[0], b.f_t(2, arg_types[0]))}, arg_types[0], 0, Exp::instantiate_Exp), + b.CallIntrinsic(scope, {arg_types[0]}, {args[0]}, arg_types[0], 0, Erfc::instantiate_Erfc)))); + + ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); + scope->add_symbol(fn_name, f_sym); + return b.Call(f_sym, new_args, return_type, nullptr); + + } + +} // namespace ErfcScaled + namespace ListIndex { static inline void verify_args(const ASR::IntrinsicElementalFunction_t& x, diag::Diagnostics& diagnostics) { @@ -4681,24 +5796,9 @@ static inline void verify_args(const ASR::IntrinsicElementalFunction_t& x, diag: } static inline ASR::expr_t *eval_list_pop(Allocator &/*al*/, - const Location &/*loc*/, ASR::ttype_t */*t*/, Vec& args, diag::Diagnostics& /*diag*/) { - if (args.n == 0 || args[0] == nullptr) { - return nullptr; - } - ASR::ListConstant_t* clist = ASR::down_cast(args[0]); - int64_t index; - - if (args.n == 1) { - index = clist->n_args - 1; - return clist->m_args[index]; - } else { - if (args[1] == nullptr) { - return nullptr; - } - index = ASR::down_cast(ASRUtils::expr_value(args[1]))->m_n; - return clist->m_args[index]; - } - + const Location &/*loc*/, ASR::ttype_t */*t*/, Vec& /*args*/, diag::Diagnostics& /*diag*/) { + // TODO: To be implemented for ListConstant expression + return nullptr; } static inline ASR::asr_t* create_ListPop(Allocator& al, const Location& loc, @@ -4758,15 +5858,10 @@ static inline void verify_args(const ASR::IntrinsicElementalFunction_t& x, diag: x.base.base.loc, diagnostics); } -static inline ASR::expr_t *eval_dict_keys(Allocator &al, - const Location &loc, ASR::ttype_t *t, Vec& args, diag::Diagnostics& /*diag*/) { - if (args[0] == nullptr) { - return nullptr; - } - ASR::DictConstant_t* cdict = ASR::down_cast(args[0]); - - return ASRUtils::EXPR(ASR::make_ListConstant_t(al, loc, - cdict->m_keys, cdict->n_keys, t)); +static inline ASR::expr_t *eval_dict_keys(Allocator &/*al*/, + const Location &/*loc*/, ASR::ttype_t *, Vec& /*args*/, diag::Diagnostics& /*diag*/) { + // TODO: To be implemented for DictConstant expression + return nullptr; } static inline ASR::asr_t* create_DictKeys(Allocator& al, const Location& loc, @@ -4810,15 +5905,10 @@ static inline void verify_args(const ASR::IntrinsicElementalFunction_t& x, diag: x.base.base.loc, diagnostics); } -static inline ASR::expr_t *eval_dict_values(Allocator &al, - const Location &loc, ASR::ttype_t *t, Vec& args, diag::Diagnostics& /*diag*/) { - if (args[0] == nullptr) { - return nullptr; - } - ASR::DictConstant_t* cdict = ASR::down_cast(args[0]); - - return ASRUtils::EXPR(ASR::make_ListConstant_t(al, loc, - cdict->m_values, cdict->n_values, t)); +static inline ASR::expr_t *eval_dict_values(Allocator &/*al*/, + const Location &/*loc*/, ASR::ttype_t *, Vec& /*args*/, diag::Diagnostics& /*diag*/) { + // TODO: To be implemented for DictConstant expression + return nullptr; } static inline ASR::asr_t* create_DictValues(Allocator& al, const Location& loc, @@ -5005,18 +6095,16 @@ namespace Max { static inline void verify_args(const ASR::IntrinsicElementalFunction_t& x, diag::Diagnostics& diagnostics) { ASRUtils::require_impl(x.n_args > 1, "Call to max0 must have at least two arguments", x.base.base.loc, diagnostics); - ASR::ttype_t* arg0_type = ASRUtils::type_get_past_array(ASRUtils::expr_type(x.m_args[0])); + ASR::ttype_t* arg0_type = ASRUtils::extract_type(ASRUtils::expr_type(x.m_args[0])); ASRUtils::require_impl(ASR::is_a(*arg0_type) || - ASR::is_a(*arg0_type) || ASR::is_a(*arg0_type), + ASR::is_a(*arg0_type) || ASR::is_a(*arg0_type), "Arguments to max0 must be of real, integer or character type", x.base.base.loc, diagnostics); for(size_t i=0;i(*ASRUtils::expr_type(x.m_args[i])) && - ASR::is_a(*ASRUtils::expr_type(x.m_args[0]))) || - (ASR::is_a(*ASRUtils::expr_type(x.m_args[i])) && - ASR::is_a(*ASRUtils::expr_type(x.m_args[0]))) || - (ASR::is_a(*ASRUtils::expr_type(x.m_args[i])) && - ASR::is_a(*ASRUtils::expr_type(x.m_args[0]))), + ASR::ttype_t* arg_type = ASRUtils::extract_type(ASRUtils::expr_type(x.m_args[i])); + ASRUtils::require_impl((ASR::is_a(*arg_type) && ASR::is_a(*arg0_type)) || + (ASR::is_a(*arg_type) && ASR::is_a(*arg0_type)) || + (ASR::is_a(*arg_type) && ASR::is_a(*arg0_type) ), "All arguments must be of the same type", x.base.base.loc, diagnostics); } @@ -5039,7 +6127,7 @@ namespace Max { max_val = std::fmax(max_val, val); } return ASR::down_cast(ASR::make_IntegerConstant_t(al, loc, max_val, arg_type)); - } else if (ASR::is_a(*arg_type)) { + } else if (ASR::is_a(*arg_type)) { char* max_val = ASR::down_cast(args[0])->m_s; for (size_t i = 1; i < args.size(); i++) { char* val = ASR::down_cast(args[i])->m_s; @@ -5053,8 +6141,7 @@ namespace Max { } } - static inline ASR::asr_t* create_Max( - Allocator& al, const Location& loc, Vec& args, + static inline ASR::asr_t* create_Max(Allocator& al, const Location& loc, Vec& args, diag::Diagnostics& diag) { bool is_compile_time = true; for(size_t i=0; i<100;i++){ @@ -5065,12 +6152,24 @@ namespace Max { return nullptr; } ASR::ttype_t *arg_type = ASRUtils::expr_type(args[0]); - for(size_t i=0;itype != ASRUtils::extract_type(ASRUtils::expr_type(args[i]))->type) { + append_error(diag, "All arguments to max0 must be of the same type", loc); return nullptr; } } + + if (!all_args_same_kind){ + promote_arguments_kinds(al, loc, args, diag); + } + Vec arg_values; arg_values.reserve(al, args.size()); ASR::expr_t *arg_value; @@ -5083,11 +6182,11 @@ namespace Max { } if (is_compile_time) { ASR::expr_t *value = eval_Max(al, loc, expr_type(args[0]), arg_values, diag); - return ASR::make_IntrinsicElementalFunction_t(al, loc, + return ASRUtils::make_IntrinsicElementalFunction_t_util(al, loc, static_cast(IntrinsicElementalFunctions::Max), args.p, args.n, 0, ASRUtils::expr_type(args[0]), value); } else { - return ASR::make_IntrinsicElementalFunction_t(al, loc, + return ASRUtils::make_IntrinsicElementalFunction_t_util(al, loc, static_cast(IntrinsicElementalFunctions::Max), args.p, args.n, 0, ASRUtils::expr_type(args[0]), nullptr); } @@ -5098,11 +6197,11 @@ namespace Max { Vec& new_args, int64_t /*overload_id*/) { declare_basic_variables("_lcompilers_max0_" + type_to_str_python(arg_types[0])); int64_t kind = extract_kind_from_ttype_t(arg_types[0]); - if (ASR::is_a(*arg_types[0])) { + if (ASR::is_a(*arg_types[0])) { for (size_t i = 0; i < new_args.size(); i++) { - fill_func_arg("x" + std::to_string(i), ASRUtils::TYPE(ASR::make_Character_t(al, loc, 1, -1, nullptr))); + fill_func_arg("x" + std::to_string(i), ASRUtils::TYPE(ASR::make_String_t(al, loc, 1, -1, nullptr, ASR::string_physical_typeType::PointerString))); } - return_type = TYPE(ASR::make_Character_t(al, loc, 1, -3, EXPR(ASR::make_StringLen_t(al, loc, args[0], int32, nullptr)))); + return_type = TYPE(ASR::make_String_t(al, loc, 1, -3, EXPR(ASR::make_StringLen_t(al, loc, args[0], int32, nullptr)), ASR::string_physical_typeType::PointerString)); } else if (ASR::is_a(*arg_types[0])) { for (size_t i = 0; i < new_args.size(); i++) { fill_func_arg("x" + std::to_string(i), ASRUtils::TYPE(ASR::make_Real_t(al, loc, kind))); @@ -5114,28 +6213,28 @@ namespace Max { } else { throw LCompilersException("Arguments to max0 must be of real, integer or character type"); } - + return_type = ASRUtils::extract_type(return_type); auto result = declare(fn_name, return_type, ReturnVar); body.push_back(al, b.Assignment(result, args[0])); if (ASR::is_a(*return_type)) { for (size_t i = 1; i < args.size(); i++) { - body.push_back(al, b.If(b.iGt(args[i], result), { + body.push_back(al, b.If(b.Gt(args[i], result), { b.Assignment(result, args[i]) }, {})); } } else if (ASR::is_a(*return_type)) { for (size_t i = 1; i < args.size(); i++) { - body.push_back(al, b.If(b.fGt(args[i], result), { + body.push_back(al, b.If(b.Gt(args[i], result), { b.Assignment(result, args[i]) }, {})); } - } else if (ASR::is_a(*return_type)) { + } else if (ASR::is_a(*return_type)) { for (size_t i = 1; i < args.size(); i++) { - body.push_back(al, b.If(b.sGt(args[i], result), { + body.push_back(al, b.If(b.Gt(args[i], result), { b.Assignment(result, args[i]) }, {})); } - return_type = TYPE(ASR::make_Character_t(al, loc, 1, -3, EXPR(ASR::make_StringLen_t(al, loc, new_args[0].m_value, int32, nullptr)))); + return_type = TYPE(ASR::make_String_t(al, loc, 1, -3, EXPR(ASR::make_StringLen_t(al, loc, new_args[0].m_value, int32, nullptr)), ASR::string_physical_typeType::PointerString)); } else { throw LCompilersException("Arguments to max0 must be of real, integer or character type"); } @@ -5153,16 +6252,16 @@ namespace Min { static inline void verify_args(const ASR::IntrinsicElementalFunction_t& x, diag::Diagnostics& diagnostics) { ASRUtils::require_impl(x.n_args > 1, "Call to min0 must have at least two arguments", x.base.base.loc, diagnostics); - ASR::ttype_t* arg0_type = ASRUtils::type_get_past_array(ASRUtils::expr_type(x.m_args[0])); + ASR::ttype_t* arg0_type = ASRUtils::extract_type(ASRUtils::expr_type(x.m_args[0])); ASRUtils::require_impl(ASR::is_a(*arg0_type) || - ASR::is_a(*arg0_type) || ASR::is_a(*arg0_type), + ASR::is_a(*arg0_type) || ASR::is_a(*arg0_type), "Arguments to min0 must be of real, integer or character type", x.base.base.loc, diagnostics); for(size_t i=0;i(*arg_type) && ASR::is_a(*arg0_type)) || (ASR::is_a(*arg_type) && ASR::is_a(*arg0_type)) || - (ASR::is_a(*arg_type) && ASR::is_a(*arg0_type) ), + (ASR::is_a(*arg_type) && ASR::is_a(*arg0_type) ), "All arguments must be of the same type", x.base.base.loc, diagnostics); } @@ -5185,7 +6284,7 @@ namespace Min { min_val = std::fmin(min_val, val); } return ASR::down_cast(ASR::make_IntegerConstant_t(al, loc, min_val, arg_type)); - } else if (ASR::is_a(*arg_type)) { + } else if (ASR::is_a(*arg_type)) { char* min_val = ASR::down_cast(args[0])->m_s; for (size_t i = 1; i < args.size(); i++) { char* val = ASR::down_cast(args[i])->m_s; @@ -5211,12 +6310,24 @@ namespace Min { return nullptr; } ASR::ttype_t *arg_type = ASRUtils::expr_type(args[0]); - for(size_t i=0;itype != ASRUtils::extract_type(ASRUtils::expr_type(args[i]))->type) { + append_error(diag, "All arguments to min0 must be of the same type", loc); return nullptr; } } + + if (!all_args_same_kind){ + promote_arguments_kinds(al, loc, args, diag); + } + Vec arg_values; arg_values.reserve(al, args.size()); ASR::expr_t *arg_value; @@ -5229,11 +6340,11 @@ namespace Min { } if (is_compile_time) { ASR::expr_t *value = eval_Min(al, loc, expr_type(args[0]), arg_values, diag); - return ASR::make_IntrinsicElementalFunction_t(al, loc, + return ASRUtils::make_IntrinsicElementalFunction_t_util(al, loc, static_cast(IntrinsicElementalFunctions::Min), args.p, args.n, 0, ASRUtils::expr_type(args[0]), value); } else { - return ASR::make_IntrinsicElementalFunction_t(al, loc, + return ASRUtils::make_IntrinsicElementalFunction_t_util(al, loc, static_cast(IntrinsicElementalFunctions::Min), args.p, args.n, 0, ASRUtils::expr_type(args[0]), nullptr); } @@ -5244,11 +6355,11 @@ namespace Min { Vec& new_args, int64_t /*overload_id*/) { declare_basic_variables("_lcompilers_min0_" + type_to_str_python(arg_types[0])); int64_t kind = extract_kind_from_ttype_t(arg_types[0]); - if (ASR::is_a(*arg_types[0])) { + if (ASR::is_a(*arg_types[0])) { for (size_t i = 0; i < new_args.size(); i++) { - fill_func_arg("x" + std::to_string(i), ASRUtils::TYPE(ASR::make_Character_t(al, loc, 1, -1, nullptr))); + fill_func_arg("x" + std::to_string(i), ASRUtils::TYPE(ASR::make_String_t(al, loc, 1, -1, nullptr, ASR::string_physical_typeType::PointerString))); } - return_type = TYPE(ASR::make_Character_t(al, loc, 1, -3, EXPR(ASR::make_StringLen_t(al, loc, args[0], int32, nullptr)))); + return_type = TYPE(ASR::make_String_t(al, loc, 1, -3, EXPR(ASR::make_StringLen_t(al, loc, args[0], int32, nullptr)), ASR::string_physical_typeType::PointerString)); } else if (ASR::is_a(*arg_types[0])) { for (size_t i = 0; i < new_args.size(); i++) { fill_func_arg("x" + std::to_string(i), ASRUtils::TYPE(ASR::make_Real_t(al, loc, kind))); @@ -5260,28 +6371,28 @@ namespace Min { } else { throw LCompilersException("Arguments to min0 must be of real, integer or character type"); } - + return_type = ASRUtils::extract_type(return_type); auto result = declare(fn_name, return_type, ReturnVar); body.push_back(al, b.Assignment(result, args[0])); if (ASR::is_a(*return_type)) { for (size_t i = 1; i < args.size(); i++) { - body.push_back(al, b.If(b.iLt(args[i], result), { + body.push_back(al, b.If(b.Lt(args[i], result), { b.Assignment(result, args[i]) }, {})); } } else if (ASR::is_a(*return_type)) { for (size_t i = 1; i < args.size(); i++) { - body.push_back(al, b.If(b.fLt(args[i], result), { + body.push_back(al, b.If(b.Lt(args[i], result), { b.Assignment(result, args[i]) }, {})); } - } else if (ASR::is_a(*return_type)) { + } else if (ASR::is_a(*return_type)) { for (size_t i = 1; i < args.size(); i++) { - body.push_back(al, b.If(b.sLt(args[i], result), { + body.push_back(al, b.If(b.Lt(args[i], result), { b.Assignment(result, args[i]) }, {})); } - return_type = TYPE(ASR::make_Character_t(al, loc, 1, -3, EXPR(ASR::make_StringLen_t(al, loc, new_args[0].m_value, int32, nullptr)))); + return_type = TYPE(ASR::make_String_t(al, loc, 1, -3, EXPR(ASR::make_StringLen_t(al, loc, new_args[0].m_value, int32, nullptr)), ASR::string_physical_typeType::PointerString)); } else { throw LCompilersException("Arguments to min0 must be of real, integer or character type"); } @@ -5378,7 +6489,7 @@ namespace Partition { auto index = declare("index", int32, Local); body.push_back(al, b.Assignment(index, b.Call(UnaryIntrinsicFunction:: create_KMP_function(al, loc, scope), args, int32))); - body.push_back(al, b.If(b.iEq(index, b.i32_n(-1)), { + body.push_back(al, b.If(b.Eq(index, b.i_neg(b.i32(-1), int32)), { b.Assignment(result, b.TupleConstant({ args[0], b.StringConstant("", character(0)), b.StringConstant("", character(0)) }, @@ -5386,10 +6497,10 @@ namespace Partition { }, { b.Assignment(result, b.TupleConstant({ b.StringSection(args[0], b.i32(0), index), args[1], - b.StringSection(args[0], b.iAdd(index, b.StringLen(args[1])), + b.StringSection(args[0], b.Add(index, b.StringLen(args[1])), b.StringLen(args[0]))}, return_type)) })); - body.push_back(al, Return()); + body.push_back(al, b.Return()); ASR::symbol_t *fn_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); scope->add_symbol(fn_name, fn_sym); @@ -5414,7 +6525,7 @@ namespace Epsilon { break; } } - return b.f(epsilon_val, arg_type); + return b.f_t(epsilon_val, arg_type); } } // namespace Epsilon @@ -5459,7 +6570,7 @@ namespace Tiny { return nullptr; } } - return b.f(tiny_value, arg_type); + return b.f_t(tiny_value, arg_type); } } // namespace Tiny @@ -5492,14 +6603,14 @@ namespace Conjg { auto result = declare(fn_name, arg_types[0], ReturnVar); // * r = real(x) - aimag(x)*(0,1) - body.push_back(al, b.Assignment(result, b.ElementalSub( + body.push_back(al, b.Assignment(result, b.Sub( EXPR(ASR::make_Cast_t(al, loc, EXPR(ASR::make_ComplexRe_t(al, loc, args[0], TYPE(ASR::make_Real_t(al, loc, extract_kind_from_ttype_t(arg_types[0]))), nullptr)), ASR::cast_kindType::RealToComplex, arg_types[0], nullptr)), - b.ElementalMul(EXPR(ASR::make_Cast_t(al, loc, EXPR(ASR::make_ComplexIm_t(al, loc, + b.Mul(EXPR(ASR::make_Cast_t(al, loc, EXPR(ASR::make_ComplexIm_t(al, loc, args[0], TYPE(ASR::make_Real_t(al, loc, extract_kind_from_ttype_t(arg_types[0]))), nullptr)), ASR::cast_kindType::RealToComplex, arg_types[0], nullptr)), EXPR(ASR::make_ComplexConstant_t(al, loc, - 0.0, 1.0, arg_types[0])), loc), loc))); + 0.0, 1.0, arg_types[0])))))); ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); @@ -5531,7 +6642,7 @@ namespace Huge { return nullptr; } } - return b.i(huge_value, arg_type); + return b.i_t(huge_value, arg_type); } else { double huge_value = -1; switch ( kind ) { @@ -5544,7 +6655,7 @@ namespace Huge { return nullptr; } } - return b.f(huge_value, arg_type); + return b.f_t(huge_value, arg_type); } } @@ -5559,7 +6670,7 @@ namespace SymbolicSymbol { loc, diagnostics); ASR::ttype_t* input_type = ASRUtils::expr_type(x.m_args[0]); - ASRUtils::require_impl(ASR::is_a(*input_type), + ASRUtils::require_impl(ASR::is_a(*input_type), "SymbolicSymbol intrinsic expects a character input argument", loc, diagnostics); } @@ -5580,7 +6691,7 @@ namespace SymbolicSymbol { ASR::ttype_t *type = ASRUtils::expr_type(args[0]); if (!ASRUtils::is_character(*type)) { - append_error(diag, "Argument of the Symbol function must be a Character", + append_error(diag, "Argument of the Symbol function must be a String", args[0]->base.loc); return nullptr; } diff --git a/src/libasr/pass/intrinsic_subroutine.cpp b/src/libasr/pass/intrinsic_subroutine.cpp index 61e9e9d305..fc681c41c0 100644 --- a/src/libasr/pass/intrinsic_subroutine.cpp +++ b/src/libasr/pass/intrinsic_subroutine.cpp @@ -38,12 +38,13 @@ class ReplaceIntrinsicSubroutines : public ASR::CallReplacerOnExpressionsVisitor ReplaceIntrinsicSubroutines(Allocator& al_) : al(al_), remove_original_statement(false) { + parent_body = nullptr; pass_result.n = 0; } void visit_IntrinsicImpureSubroutine(const ASR::IntrinsicImpureSubroutine_t &x) { Vec new_args; new_args.reserve(al, x.n_args); - // Replace any IntrinsicImpureSubroutinesin the argument first: + // Replace any IntrinsicImpureSubroutines in the argument first: for( size_t i = 0; i < x.n_args; i++ ) { ASR::call_arg_t arg0; arg0.loc = x.m_args[i]->base.loc; @@ -51,7 +52,7 @@ class ReplaceIntrinsicSubroutines : public ASR::CallReplacerOnExpressionsVisitor new_args.push_back(al, arg0); } ASRUtils::impl_subroutine instantiate_subroutine = - ASRUtils::IntrinsicImpureSubroutineRegistry::get_instantiate_subroutine(x.m_intrinsic_id); + ASRUtils::IntrinsicImpureSubroutineRegistry::get_instantiate_subroutine(x.m_sub_intrinsic_id); if( instantiate_subroutine == nullptr ) { return ; } diff --git a/src/libasr/pass/intrinsic_subroutine_registry.h b/src/libasr/pass/intrinsic_subroutine_registry.h index d84105d49d..79bc6a5399 100644 --- a/src/libasr/pass/intrinsic_subroutine_registry.h +++ b/src/libasr/pass/intrinsic_subroutine_registry.h @@ -20,6 +20,16 @@ namespace ASRUtils { inline std::string get_intrinsic_subroutine_name(int x) { switch (x) { INTRINSIC_SUBROUTINE_NAME_CASE(RandomNumber) + INTRINSIC_SUBROUTINE_NAME_CASE(RandomInit) + INTRINSIC_SUBROUTINE_NAME_CASE(RandomSeed) + INTRINSIC_SUBROUTINE_NAME_CASE(GetCommand) + INTRINSIC_SUBROUTINE_NAME_CASE(GetCommandArgument) + INTRINSIC_SUBROUTINE_NAME_CASE(GetEnvironmentVariable) + INTRINSIC_SUBROUTINE_NAME_CASE(ExecuteCommandLine) + INTRINSIC_SUBROUTINE_NAME_CASE(CpuTime) + INTRINSIC_SUBROUTINE_NAME_CASE(Srand) + INTRINSIC_SUBROUTINE_NAME_CASE(SystemClock) + INTRINSIC_SUBROUTINE_NAME_CASE(DateAndTime) default : { throw LCompilersException("pickle: intrinsic_id not implemented"); } @@ -35,17 +45,67 @@ namespace IntrinsicImpureSubroutineRegistry { verify_subroutine>>& intrinsic_subroutine_by_id_db = { {static_cast(IntrinsicImpureSubroutines::RandomNumber), {&RandomNumber::instantiate_RandomNumber, &RandomNumber::verify_args}}, + {static_cast(IntrinsicImpureSubroutines::RandomInit), + {&RandomInit::instantiate_RandomInit, &RandomInit::verify_args}}, + {static_cast(IntrinsicImpureSubroutines::RandomSeed), + {&RandomSeed::instantiate_RandomSeed, &RandomSeed::verify_args}}, + {static_cast(IntrinsicImpureSubroutines::Srand), + {&Srand::instantiate_Srand, &Srand::verify_args}}, + {static_cast(IntrinsicImpureSubroutines::GetCommand), + {&GetCommand::instantiate_GetCommand, &GetCommand::verify_args}}, + {static_cast(IntrinsicImpureSubroutines::GetCommandArgument), + {&GetCommandArgument::instantiate_GetCommandArgument, &GetCommandArgument::verify_args}}, + {static_cast(IntrinsicImpureSubroutines::SystemClock), + {&SystemClock::instantiate_SystemClock, &SystemClock::verify_args}}, + {static_cast(IntrinsicImpureSubroutines::DateAndTime), + {&DateAndTime::instantiate_DateAndTime, &DateAndTime::verify_args}}, + {static_cast(IntrinsicImpureSubroutines::GetEnvironmentVariable), + {&GetEnvironmentVariable::instantiate_GetEnvironmentVariable, &GetEnvironmentVariable::verify_args}}, + {static_cast(IntrinsicImpureSubroutines::ExecuteCommandLine), + {&ExecuteCommandLine::instantiate_ExecuteCommandLine, &ExecuteCommandLine::verify_args}}, + {static_cast(IntrinsicImpureSubroutines::CpuTime), + {&CpuTime::instantiate_CpuTime, &CpuTime::verify_args}}, }; static const std::map& intrinsic_subroutine_id_to_name = { {static_cast(IntrinsicImpureSubroutines::RandomNumber), "random_number"}, + {static_cast(IntrinsicImpureSubroutines::RandomInit), + "random_init"}, + {static_cast(IntrinsicImpureSubroutines::RandomSeed), + "random_seed"}, + {static_cast(IntrinsicImpureSubroutines::Srand), + "srand"}, + {static_cast(IntrinsicImpureSubroutines::GetCommand), + "get_command"}, + {static_cast(IntrinsicImpureSubroutines::GetCommandArgument), + "get_command_argument"}, + {static_cast(IntrinsicImpureSubroutines::SystemClock), + "system_clock"}, + {static_cast(IntrinsicImpureSubroutines::DateAndTime), + "date_and_time"}, + {static_cast(IntrinsicImpureSubroutines::GetEnvironmentVariable), + "get_environment_variable"}, + {static_cast(IntrinsicImpureSubroutines::ExecuteCommandLine), + "execute_command_line"}, + {static_cast(IntrinsicImpureSubroutines::CpuTime), + "cpu_time"}, }; static const std::map& intrinsic_subroutine_by_name_db = { {"random_number", &RandomNumber::create_RandomNumber}, + {"random_init", &RandomInit::create_RandomInit}, + {"random_seed", &RandomSeed::create_RandomSeed}, + {"srand", &Srand::create_Srand}, + {"get_command", &GetCommand::create_GetCommand}, + {"get_command_argument", &GetCommandArgument::create_GetCommandArgument}, + {"system_clock", &SystemClock::create_SystemClock}, + {"get_environment_variable", &GetEnvironmentVariable::create_GetEnvironmentVariable}, + {"execute_command_line", &ExecuteCommandLine::create_ExecuteCommandLine}, + {"cpu_time", &CpuTime::create_CpuTime}, + {"date_and_time", &DateAndTime::create_DateAndTime}, }; static inline bool is_intrinsic_subroutine(const std::string& name) { @@ -71,7 +131,7 @@ namespace IntrinsicImpureSubroutineRegistry { return std::get<0>(intrinsic_subroutine_by_id_db.at(id)); } - static inline std::string get_intrinsic_subroutine_name(int64_t id) { + inline std::string get_intrinsic_subroutine_name(int64_t id) { if( intrinsic_subroutine_id_to_name.find(id) == intrinsic_subroutine_id_to_name.end() ) { throw LCompilersException("IntrinsicSubroutine with ID " + std::to_string(id) + " has no name registered for it"); diff --git a/src/libasr/pass/intrinsic_subroutines.h b/src/libasr/pass/intrinsic_subroutines.h index f4b946b0b2..2360662344 100644 --- a/src/libasr/pass/intrinsic_subroutines.h +++ b/src/libasr/pass/intrinsic_subroutines.h @@ -20,6 +20,16 @@ the code size. enum class IntrinsicImpureSubroutines : int64_t { RandomNumber, + RandomInit, + RandomSeed, + GetCommand, + GetEnvironmentVariable, + ExecuteCommandLine, + GetCommandArgument, + CpuTime, + Srand, + SystemClock, + DateAndTime, // ... }; @@ -39,6 +49,210 @@ typedef void (*verify_subroutine)( typedef ASR::expr_t* (*get_initial_value_sub)(Allocator&, ASR::ttype_t*); +namespace RandomInit { + + static inline void verify_args(const ASR::IntrinsicImpureSubroutine_t& x, diag::Diagnostics& diagnostics) { + if (x.n_args == 2) { + ASRUtils::require_impl(x.m_overload_id == 0, "Overload Id for random_init expected to be 0, found " + std::to_string(x.m_overload_id), x.base.base.loc, diagnostics); + ASRUtils::require_impl(ASRUtils::is_logical(*ASRUtils::expr_type(x.m_args[0])), "First argument must be of logical type", x.base.base.loc, diagnostics); + ASRUtils::require_impl(ASRUtils::is_logical(*ASRUtils::expr_type(x.m_args[1])), "Second argument must be of logical type", x.base.base.loc, diagnostics); + } else { + ASRUtils::require_impl(false, "Unexpected number of args, random_init takes 2 arguments, found " + std::to_string(x.n_args), x.base.base.loc, diagnostics); + } + } + + static inline ASR::asr_t* create_RandomInit(Allocator& al, const Location& loc, Vec& args, diag::Diagnostics& /*diag*/) { + Vec m_args; m_args.reserve(al, 2); + m_args.push_back(al, args[0]); + m_args.push_back(al, args[1]); + return ASR::make_IntrinsicImpureSubroutine_t(al, loc, static_cast(IntrinsicImpureSubroutines::RandomInit), m_args.p, m_args.n, 0); + } + + static inline ASR::stmt_t* instantiate_RandomInit(Allocator &al, const Location &loc, + SymbolTable *scope, Vec& arg_types, + Vec& new_args, int64_t /*overload_id*/) { + + std::string c_func_name = "_lfortran_random_init"; + std::string new_name = "_lcompilers_random_init_"; + + declare_basic_variables(new_name); + fill_func_arg_sub("repeatable", arg_types[0], InOut); + fill_func_arg_sub("image_distinct", arg_types[1], InOut); + SymbolTable *fn_symtab_1 = al.make_new(fn_symtab); + Vec args_1; args_1.reserve(al, 0); + ASR::expr_t *return_var_1 = b.Variable(fn_symtab_1, c_func_name, + ASRUtils::type_get_past_array(ASRUtils::type_get_past_allocatable(arg_types[0])), + ASRUtils::intent_return_var, ASR::abiType::BindC, false); + SetChar dep_1; dep_1.reserve(al, 1); + Vec body_1; body_1.reserve(al, 1); + ASR::symbol_t *s = make_ASR_Function_t(c_func_name, fn_symtab_1, dep_1, args_1, + body_1, return_var_1, ASR::abiType::BindC, ASR::deftypeType::Interface, s2c(al, c_func_name)); + fn_symtab->add_symbol(c_func_name, s); + dep.push_back(al, s2c(al, c_func_name)); + Vec call_args; call_args.reserve(al, 0); + body.push_back(al, b.Assignment(args[0], b.Call(s, call_args, arg_types[0]))); + body.push_back(al, b.Assignment(args[1], b.Call(s, call_args, arg_types[1]))); + ASR::symbol_t *new_symbol = make_ASR_Function_t(fn_name, fn_symtab, dep, args, + body, nullptr, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); + scope->add_symbol(fn_name, new_symbol); + return b.SubroutineCall(new_symbol, new_args); + } +} // namespace RandomInit + +namespace RandomSeed { + + static inline void verify_args(const ASR::IntrinsicImpureSubroutine_t& x, diag::Diagnostics& diagnostics) { + ASRUtils::require_impl(x.n_args <= 3, "random_seed can have maximum 3 args", x.base.base.loc, diagnostics); + if (x.n_args == 1) { + ASRUtils::require_impl(ASRUtils::is_integer(*ASRUtils::expr_type(x.m_args[0])), "Arguments to random_seed must be of integer type", x.base.base.loc, diagnostics); + } else if (x.n_args == 2) { + ASRUtils::require_impl(ASRUtils::is_integer(*ASRUtils::expr_type(x.m_args[0])) && ASRUtils::is_integer(*ASRUtils::expr_type(x.m_args[0])), "Arguments to random_seed must be of integer type", x.base.base.loc, diagnostics); + } else if (x.n_args == 3) { + ASRUtils::require_impl(ASRUtils::is_integer(*ASRUtils::expr_type(x.m_args[0])) && ASRUtils::is_integer(*ASRUtils::expr_type(x.m_args[1])) && ASRUtils::is_integer(*ASRUtils::expr_type(x.m_args[2])), "Arguments to random_seed must be of integer type", x.base.base.loc, diagnostics); + } + } + + static inline ASR::asr_t* create_RandomSeed(Allocator& al, const Location& loc, Vec& args, diag::Diagnostics& /*diag*/) { + Vec m_args; m_args.reserve(al, 0); + ASRBuilder b(al, loc); + for (int i = 0; i < int(args.size()); i++) { + if(args[i]) { + m_args.push_back(al, args[i]); + } else { + m_args.push_back(al, b.f32(1)); + } + } + return ASR::make_IntrinsicImpureSubroutine_t(al, loc, static_cast(IntrinsicImpureSubroutines::RandomSeed), m_args.p, m_args.n, 0); + } + + static inline ASR::stmt_t* instantiate_RandomSeed(Allocator &al, const Location &loc, + SymbolTable *scope, Vec& arg_types, + Vec& new_args, int64_t /*overload_id*/) { + + std::string c_func_name_1 = "_lfortran_random_seed"; + std::string c_func_name_2 = "_lfortran_dp_rand_num"; + std::string new_name = "_lcompilers_random_seed_"; + declare_basic_variables(new_name); + int flag = 0; + if (!is_real(*arg_types[0])) { + fill_func_arg_sub("size", arg_types[0], InOut); + ASR::symbol_t *s_1 = b.create_c_func_subroutines(c_func_name_1, fn_symtab, 1, arg_types[0]); + fn_symtab->add_symbol(c_func_name_1, s_1); + dep.push_back(al, s2c(al, c_func_name_1)); + Vec call_args; call_args.reserve(al, 1); + call_args.push_back(al, b.i32(8)); + body.push_back(al, b.Assignment(args[0], b.Call(s_1, call_args, arg_types[0]))); + } else { + fill_func_arg_sub("size", real32, InOut); + body.push_back(al, b.Assignment(args[0], b.f32(0))); + } + if (!is_real(*arg_types[1])) { + flag = 1; + fill_func_arg_sub("put", arg_types[1], InOut); + body.push_back(al, b.Assignment(args[1], args[1])); + } else { + fill_func_arg_sub("put", real32, InOut); + body.push_back(al, b.Assignment(args[1], b.f32(0))); + } + if (!is_real(*arg_types[2])) { + fill_func_arg_sub("get", arg_types[2], InOut); + if (flag == 1) { + body.push_back(al, b.Assignment(args[2], args[1])); + } else { + std::vector vals; + std::string c_func = c_func_name_2; + int kind = ASRUtils::extract_kind_from_ttype_t(arg_types[2]); + if ( is_real(*arg_types[2]) ) { + if (kind == 4) { + c_func = "_lfortran_sp_rand_num"; + } else { + c_func = "_lfortran_dp_rand_num"; + } + } else if ( is_integer(*arg_types[2]) ) { + if (kind == 4) { + c_func = "_lfortran_int32_rand_num"; + } else { + c_func = "_lfortran_int64_rand_num"; + } + } + ASR::symbol_t *s_2 = b.create_c_func_subroutines(c_func, fn_symtab, 0, arg_types[2]); + fn_symtab->add_symbol(c_func, s_2); + dep.push_back(al, s2c(al, c_func)); + Vec call_args2; call_args2.reserve(al, 0); + ASR::ttype_t* elem_type = extract_type(arg_types[2]); + for (int i = 0; i < 8; i++) { + auto xx = declare("i_" + std::to_string(i), elem_type, Local); + body.push_back(al, b.Assignment(xx, b.Call(s_2, call_args2, int32))); + vals.push_back(xx); + } + body.push_back(al, b.Assignment(args[2], b.ArrayConstant(vals, extract_type(arg_types[2]), false))); + } + } else { + fill_func_arg_sub("get", real32, InOut); + body.push_back(al, b.Assignment(args[2], b.f32(0))); + } + + ASR::symbol_t *new_symbol = make_ASR_Function_t(fn_name, fn_symtab, dep, args, + body, nullptr, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); + scope->add_symbol(fn_name, new_symbol); + return b.SubroutineCall(new_symbol, new_args); + } + +} // namespace RandomSeed + +namespace Srand { + + static inline void verify_args(const ASR::IntrinsicImpureSubroutine_t& x, diag::Diagnostics& diagnostics) { + ASRUtils::require_impl(x.n_args == 1, "srand takes 1 argument only", x.base.base.loc, diagnostics); + if (x.n_args == 1) { + ASRUtils::require_impl(ASRUtils::is_integer(*ASRUtils::expr_type(x.m_args[0])), "Arguments to srand must be of integer type", x.base.base.loc, diagnostics); + } + } + + static inline ASR::asr_t* create_Srand(Allocator& al, const Location& loc, Vec& args, diag::Diagnostics& diag) { + diag.semantic_warning_label( + "`srand` is an LFortran extension", { loc }, "Use `random_init` instead"); + Vec m_args; m_args.reserve(al, 1); m_args.push_back(al, args[0]); + return ASR::make_IntrinsicImpureSubroutine_t(al, loc, static_cast(IntrinsicImpureSubroutines::Srand), m_args.p, m_args.n, 0); + } + + static inline ASR::stmt_t* instantiate_Srand(Allocator &al, const Location &loc, + SymbolTable *scope, Vec& arg_types, + Vec& new_args, int64_t /*overload_id*/) { + + std::string c_func_name = "_lfortran_init_random_seed"; + std::string new_name = "_lcompilers_srand_"; + declare_basic_variables(new_name); + fill_func_arg_sub("r", arg_types[0], InOut); + SymbolTable *fn_symtab_1 = al.make_new(fn_symtab); + Vec args_1; args_1.reserve(al, 1); + ASR::expr_t *arg = b.Variable(fn_symtab_1, "n", arg_types[0], + ASR::intentType::In, ASR::abiType::BindC, true); + args_1.push_back(al, arg); + + ASR::expr_t *return_var_1 = b.Variable(fn_symtab_1, c_func_name, + ASRUtils::type_get_past_array(ASRUtils::type_get_past_allocatable(arg_types[0])), + ASRUtils::intent_return_var, ASR::abiType::BindC, false); + + SetChar dep_1; dep_1.reserve(al, 1); + Vec body_1; body_1.reserve(al, 1); + ASR::symbol_t *s = make_ASR_Function_t(c_func_name, fn_symtab_1, dep_1, args_1, + body_1, return_var_1, ASR::abiType::BindC, ASR::deftypeType::Interface, s2c(al, c_func_name)); + fn_symtab->add_symbol(c_func_name, s); + dep.push_back(al, s2c(al, c_func_name)); + + Vec call_args; call_args.reserve(al, 1); + call_args.push_back(al, args[0]); + body.push_back(al, b.Assignment(args[0], b.Call(s, call_args, arg_types[0]))); + + ASR::symbol_t *new_symbol = make_ASR_Function_t(fn_name, fn_symtab, dep, args, + body, nullptr, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); + scope->add_symbol(fn_name, new_symbol); + return b.SubroutineCall(new_symbol, new_args); + } + +} // namespace Srand + namespace RandomNumber { static inline void verify_args(const ASR::IntrinsicImpureSubroutine_t& x, diag::Diagnostics& diagnostics) { @@ -68,7 +282,7 @@ namespace RandomNumber { std::string new_name = "_lcompilers_random_number_"; declare_basic_variables(new_name); - fill_func_arg_sub("r", arg_types[0], InOut); + fill_func_arg_sub("r", ASRUtils::duplicate_type_with_empty_dims(al, arg_types[0]), InOut); SymbolTable *fn_symtab_1 = al.make_new(fn_symtab); Vec args_1; args_1.reserve(al, 0); ASR::expr_t *return_var_1 = b.Variable(fn_symtab_1, c_func_name, @@ -115,6 +329,542 @@ namespace RandomNumber { } // namespace RandomNumber +namespace GetCommand { + + static inline void verify_args(const ASR::IntrinsicImpureSubroutine_t& x, diag::Diagnostics& diagnostics) { + ASRUtils::require_impl(x.m_overload_id == 0, "Overload Id for get_command expected to be 0, found " + std::to_string(x.m_overload_id), x.base.base.loc, diagnostics); + if( x.n_args > 0 ) { + ASRUtils::require_impl(ASRUtils::is_character(*ASRUtils::expr_type(x.m_args[0])), + "First argument must be of character type", x.base.base.loc, diagnostics); + } + if( x.n_args > 1 ) { + ASRUtils::require_impl(ASRUtils::is_integer(*ASRUtils::expr_type(x.m_args[1])), + "Second argument must be of integer type", x.base.base.loc, diagnostics); + } + if( x.n_args > 2 ) { + ASRUtils::require_impl(ASRUtils::is_integer(*ASRUtils::expr_type(x.m_args[2])), + "Third argument must be of integer type", x.base.base.loc, diagnostics); + } + if( x.n_args > 3 ) { + ASRUtils::require_impl(false, "Unexpected number of args, get_command takes 3 arguments, found " + + std::to_string(x.n_args), x.base.base.loc, diagnostics); + } + } + + static inline ASR::asr_t* create_GetCommand(Allocator& al, const Location& loc, Vec& args, diag::Diagnostics& /*diag*/) { + Vec m_args; m_args.reserve(al, 3); + if(args[0]) m_args.push_back(al, args[0]); + if(args[1]) m_args.push_back(al, args[1]); + if(args[2]) m_args.push_back(al, args[2]); + return ASR::make_IntrinsicImpureSubroutine_t(al, loc, static_cast(IntrinsicImpureSubroutines::GetCommand), m_args.p, m_args.n, 0); + } + + static inline ASR::stmt_t* instantiate_GetCommand(Allocator &al, const Location &loc, + SymbolTable *scope, Vec& arg_types, + Vec& new_args, int64_t /*overload_id*/) { + + std::string c_func_name_1 = "_lfortran_get_command_command"; + std::string c_func_name_2 = "_lfortran_get_command_length"; + std::string c_func_name_3 = "_lfortran_get_command_status"; + + std::string new_name = "_lcompilers_get_command_"; + declare_basic_variables(new_name); + Vec call_args; call_args.reserve(al, 0); + + if(arg_types.size() > 0){ + fill_func_arg_sub("command", arg_types[0], InOut); + ASR::symbol_t *s_1 = b.create_c_func_subroutines(c_func_name_1, fn_symtab, 0, arg_types[0]); + fn_symtab->add_symbol(c_func_name_1, s_1); + dep.push_back(al, s2c(al, c_func_name_1)); + body.push_back(al, b.Assignment(args[0], b.Call(s_1, call_args, arg_types[0]))); + } + if(arg_types.size() > 1){ + fill_func_arg_sub("length", arg_types[1], InOut); + ASR::symbol_t *s_2 = b.create_c_func_subroutines(c_func_name_2, fn_symtab, 0, arg_types[1]); + fn_symtab->add_symbol(c_func_name_2, s_2); + dep.push_back(al, s2c(al, c_func_name_2)); + body.push_back(al, b.Assignment(args[1], b.Call(s_2, call_args, arg_types[1]))); + } + if(arg_types.size() > 2){ + fill_func_arg_sub("status", arg_types[2], InOut); + ASR::symbol_t *s_3 = b.create_c_func_subroutines(c_func_name_3, fn_symtab, 0, arg_types[2]); + fn_symtab->add_symbol(c_func_name_3, s_3); + dep.push_back(al, s2c(al, c_func_name_3)); + body.push_back(al, b.Assignment(args[2], b.Call(s_3, call_args, arg_types[2]))); + } + + ASR::symbol_t *new_symbol = make_ASR_Function_t(fn_name, fn_symtab, dep, args, + body, nullptr, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); + scope->add_symbol(fn_name, new_symbol); + return b.SubroutineCall(new_symbol, new_args); + } + +} // namespace GetCommand + +namespace GetCommandArgument { + + static inline void verify_args(const ASR::IntrinsicImpureSubroutine_t& x, diag::Diagnostics& diagnostics) { + if (x.n_args > 0) { + ASRUtils::require_impl(ASRUtils::is_integer(*ASRUtils::expr_type(x.m_args[0])), "First argument must be of integer type", x.base.base.loc, diagnostics); + } + if(x.n_args > 1) { + ASRUtils::require_impl(ASRUtils::is_character(*ASRUtils::expr_type(x.m_args[1])), "Second argument must be of character type", x.base.base.loc, diagnostics); + } + if (x.n_args > 2) { + ASRUtils::require_impl(ASRUtils::is_integer(*ASRUtils::expr_type(x.m_args[2])), "Third argument must be of integer type", x.base.base.loc, diagnostics); + } + if (x.n_args == 4) { + ASRUtils::require_impl(ASRUtils::is_integer(*ASRUtils::expr_type(x.m_args[3])), "Fourth argument must be of integer type", x.base.base.loc, diagnostics); + } else { + ASRUtils::require_impl(false, "Unexpected number of args, get_command_argument takes atmost 4 arguments, found " + std::to_string(x.n_args), x.base.base.loc, diagnostics); + } + } + + static inline ASR::asr_t* create_GetCommandArgument(Allocator& al, const Location& loc, Vec& args, diag::Diagnostics& /*diag*/) { + Vec m_args; m_args.reserve(al, args.size()); + m_args.push_back(al, args[0]); + for (int i = 1; i < int(args.size()); i++) { + if(args[i]) m_args.push_back(al, args[i]); + } + return ASR::make_IntrinsicImpureSubroutine_t(al, loc, static_cast(IntrinsicImpureSubroutines::GetCommandArgument), m_args.p, m_args.n, 0); + } + + static inline ASR::stmt_t* instantiate_GetCommandArgument(Allocator &al, const Location &loc, + SymbolTable *scope, Vec& arg_types, + Vec& new_args, int64_t /*overload_id*/) { + + std::string c_func_name_1 = "_lfortran_get_command_argument_value"; + std::string c_func_name_2 = "_lfortran_get_command_argument_length"; + std::string c_func_name_3 = "_lfortran_get_command_argument_status"; + + std::string new_name = "_lcompilers_get_command_argument_"; + declare_basic_variables(new_name); + Vec call_args; call_args.reserve(al, 0); + fill_func_arg_sub("number", arg_types[0], In); + if (arg_types.size() > 1) { + fill_func_arg_sub("value", arg_types[1], InOut); + Vec args_1; args_1.reserve(al, 0); + SymbolTable *fn_symtab_1 = al.make_new(fn_symtab); + ASR::expr_t *arg = b.Variable(fn_symtab_1, "n", arg_types[0], + ASR::intentType::In, ASR::abiType::BindC, true); + args_1.push_back(al, arg); + SetChar dep_1; dep_1.reserve(al, 1); + Vec body_1; body_1.reserve(al, 1); + ASR::expr_t *return_var_1 = b.Variable(fn_symtab_1, c_func_name_1, + ASRUtils::type_get_past_array(ASRUtils::type_get_past_allocatable(arg_types[1])), + ASRUtils::intent_return_var, ASR::abiType::BindC, false); + ASR::symbol_t *s_1 = make_ASR_Function_t(c_func_name_1, fn_symtab_1, dep_1, args_1, + body_1, return_var_1, ASR::abiType::BindC, ASR::deftypeType::Interface, s2c(al, c_func_name_1)); + + fn_symtab->add_symbol(c_func_name_1, s_1); + dep.push_back(al, s2c(al, c_func_name_1)); + Vec call_args1; call_args1.reserve(al, 1); + call_args1.push_back(al, args[0]); + body.push_back(al, b.Assignment(args[1], b.Call(s_1, call_args1, arg_types[1]))); + } + if (arg_types.size() > 2) { + fill_func_arg_sub("length", arg_types[2], InOut); + + ASR::symbol_t *s_2 = b.create_c_func_subroutines(c_func_name_2, fn_symtab, 1, arg_types[2]); + fn_symtab->add_symbol(c_func_name_2, s_2); + dep.push_back(al, s2c(al, c_func_name_2)); + Vec call_args2; call_args2.reserve(al, 1); + call_args2.push_back(al, args[0]); + body.push_back(al, b.Assignment(args[2], b.Call(s_2, call_args2, arg_types[2]))); + } + if (arg_types.size() == 4) { + fill_func_arg_sub("status", arg_types[3], InOut); + ASR::symbol_t *s_3 = b.create_c_func_subroutines(c_func_name_3, fn_symtab, 0, arg_types[3]); + fn_symtab->add_symbol(c_func_name_3, s_3); + dep.push_back(al, s2c(al, c_func_name_3)); + body.push_back(al, b.Assignment(args[3], b.Call(s_3, call_args, arg_types[3]))); + } + + ASR::symbol_t *new_symbol = make_ASR_Function_t(fn_name, fn_symtab, dep, args, + body, nullptr, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); + scope->add_symbol(fn_name, new_symbol); + return b.SubroutineCall(new_symbol, new_args); + } + +} // namespace GetCommandArgument + +namespace SystemClock { + + static inline void verify_args(const ASR::IntrinsicImpureSubroutine_t& x, diag::Diagnostics& diagnostics) { + if (x.n_args > 0) { + ASRUtils::require_impl(ASRUtils::is_integer(*ASRUtils::expr_type(x.m_args[0])), "`count` argument must be of integer type", x.base.base.loc, diagnostics); + } + if (x.n_args > 1) { + ASRUtils::require_impl(ASRUtils::is_integer(*ASRUtils::expr_type(x.m_args[1])) || ASRUtils::is_real(*ASRUtils::expr_type(x.m_args[1])), "`count_rate` argument must be of integer or real type", x.base.base.loc, diagnostics); + } + if (x.n_args > 2) { + ASRUtils::require_impl(ASRUtils::is_integer(*ASRUtils::expr_type(x.m_args[2])), "`count_max` argument must be of integer type", x.base.base.loc, diagnostics); + } + if (x.n_args > 3) { + ASRUtils::require_impl(false, "Unexpected number of args, system_clock takes atmost 3 arguments, found " + std::to_string(x.n_args), x.base.base.loc, diagnostics); + } + } + + static inline ASR::asr_t* create_SystemClock(Allocator& al, const Location& loc, Vec& args, diag::Diagnostics& /*diag*/) { + int64_t count_id = 0, count_rate_id = 1, count_max_id = 2, count_count_rate_id = 3, count_count_max_id = 4, count_rate_count_max_id = 5, count_count_rate_count_max_id = 6; + int64_t overload_id = -1; + Vec m_args; m_args.reserve(al, args.size()); + ASRBuilder b(al, loc); + if(args[0]) overload_id = count_id; + if(args[1]) overload_id = count_rate_id; + if(args[2]) overload_id = count_max_id; + if(args[0] && args[1]) overload_id = count_count_rate_id; + if(args[0] && args[2]) overload_id = count_count_max_id; + if(args[1] && args[2]) overload_id = count_rate_count_max_id; + if(args[0] && args[1] && args[2]) overload_id = count_count_rate_count_max_id; + for (int i = 0; i < int(args.size()); i++) { + if(args[i]) m_args.push_back(al, args[i]); + else m_args.push_back(al, b.i32(1)); + } + return ASR::make_IntrinsicImpureSubroutine_t(al, loc, static_cast(IntrinsicImpureSubroutines::SystemClock), m_args.p, m_args.n, overload_id); + } + + static inline ASR::stmt_t* instantiate_SystemClock(Allocator &al, const Location &loc, + SymbolTable *scope, Vec& arg_types, + Vec& new_args, int64_t overload_id) { + + std::string c_func_name_1 = "_lfortran_i32sys_clock_count"; + std::string c_func_name_2 = "_lfortran_i32sys_clock_count_rate"; + std::string c_func_name_3 = "_lfortran_i32sys_clock_count_max"; + std::string new_name = "_lcompilers_system_clock_"; + declare_basic_variables(new_name); + Vec call_args; call_args.reserve(al, 0); + if (overload_id == 0 || overload_id == 3 || overload_id == 4 || overload_id == 6) { + if (ASRUtils::extract_kind_from_ttype_t(arg_types[0]) == 8) { + c_func_name_1 = "_lfortran_i64sys_clock_count"; + } + fill_func_arg_sub("count", arg_types[0], InOut); + ASR::symbol_t *s_1 = b.create_c_func_subroutines(c_func_name_1, fn_symtab, 0, arg_types[0]); + fn_symtab->add_symbol(c_func_name_1, s_1); + dep.push_back(al, s2c(al, c_func_name_1)); + body.push_back(al, b.Assignment(args[0], b.Call(s_1, call_args, arg_types[0]))); + } else { + fill_func_arg_sub("count", int32, InOut); + body.push_back(al, b.Assignment(args[0], b.i32(0))); + } + if (overload_id == 1 || overload_id == 3 || overload_id == 5 || overload_id == 6) { + if (ASRUtils::extract_kind_from_ttype_t(arg_types[1]) == 8) { + if (is_real(*arg_types[1])) { + c_func_name_2 = "_lfortran_i64r64sys_clock_count_rate"; + } else { + c_func_name_2 = "_lfortran_i64sys_clock_count_rate"; + } + } else if (is_real(*arg_types[1])) { + c_func_name_2 = "_lfortran_i32r32sys_clock_count_rate"; + } + fill_func_arg_sub("count_rate", arg_types[1], InOut); + ASR::symbol_t *s_2 = b.create_c_func_subroutines(c_func_name_2, fn_symtab, 0, arg_types[1]); + fn_symtab->add_symbol(c_func_name_2, s_2); + dep.push_back(al, s2c(al, c_func_name_2)); + body.push_back(al, b.Assignment(args[1], b.Call(s_2, call_args, arg_types[1]))); + } else { + fill_func_arg_sub("count_rate", int32, InOut); + body.push_back(al, b.Assignment(args[1], b.i32(0))); + } + if (overload_id == 2 || overload_id == 4 || overload_id == 5 || overload_id == 6) { + if (ASRUtils::extract_kind_from_ttype_t(arg_types[2]) == 8) { + c_func_name_3 = "_lfortran_i64sys_clock_count_max"; + } + fill_func_arg_sub("count_max", arg_types[2], InOut); + ASR::symbol_t *s_3 = b.create_c_func_subroutines(c_func_name_3, fn_symtab, 0, arg_types[2]); + fn_symtab->add_symbol(c_func_name_3, s_3); + dep.push_back(al, s2c(al, c_func_name_3)); + body.push_back(al, b.Assignment(args[2], b.Call(s_3, call_args, arg_types[2]))); + } else { + fill_func_arg_sub("count_max", int32, InOut); + body.push_back(al, b.Assignment(args[2], b.i32(0))); + } + + ASR::symbol_t *new_symbol = make_ASR_Function_t(fn_name, fn_symtab, dep, args, + body, nullptr, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); + scope->add_symbol(fn_name, new_symbol); + return b.SubroutineCall(new_symbol, new_args); + } + +} // namespace SystemClock + +namespace DateAndTime { + + static inline void verify_args(const ASR::IntrinsicImpureSubroutine_t& x, diag::Diagnostics& diagnostics) { + if (x.n_args > 0) { + ASRUtils::require_impl(ASRUtils::is_character(*ASRUtils::expr_type(x.m_args[0])), "`date` argument must be of character type", x.base.base.loc, diagnostics); + } + if (x.n_args > 1) { + ASRUtils::require_impl(ASRUtils::is_character(*ASRUtils::expr_type(x.m_args[1])), "`time` argument must be of character or real type", x.base.base.loc, diagnostics); + } + if (x.n_args > 2) { + ASRUtils::require_impl(ASRUtils::is_character(*ASRUtils::expr_type(x.m_args[2])), "`zone` argument must be of character type", x.base.base.loc, diagnostics); + } + if (x.n_args > 3) { + ASRUtils::require_impl(ASRUtils::is_integer(*ASRUtils::expr_type(x.m_args[3])), "`values` argument must be of integer array type", x.base.base.loc, diagnostics); + } + if (x.n_args > 4) { + ASRUtils::require_impl(false, "Unexpected number of args, date_and_time takes atmost 4 arguments, found " + std::to_string(x.n_args), x.base.base.loc, diagnostics); + } + } + + static inline ASR::asr_t* create_DateAndTime(Allocator& al, const Location& loc, Vec& args, diag::Diagnostics& /*diag*/) { + Vec m_args; m_args.reserve(al, args.size()); + ASRBuilder b(al, loc); + for (int i = 0; i < int(args.size()); i++) { + if(args[i]) { + m_args.push_back(al, args[i]); + } else { + m_args.push_back(al, b.f32(1)); + } + } + return ASR::make_IntrinsicImpureSubroutine_t(al, loc, static_cast(IntrinsicImpureSubroutines::DateAndTime), m_args.p, m_args.n, 0); + } + + static inline ASR::stmt_t* instantiate_DateAndTime(Allocator &al, const Location &loc, + SymbolTable *scope, Vec& arg_types, + Vec& new_args, int64_t /*overload_id*/) { + + std::string c_func_name_1 = "_lfortran_date"; + std::string c_func_name_2 = "_lfortran_time"; + std::string c_func_name_3 = "_lfortran_zone"; + std::string c_func_name_4 = "_lfortran_values"; + std::string new_name = "_lcompilers_date_and_time_"; + declare_basic_variables(new_name); + Vec call_args; call_args.reserve(al, 0); + + if (!is_real(*arg_types[0])) { + fill_func_arg_sub("date", arg_types[0], InOut); + ASR::symbol_t *s_1 = b.create_c_func_subroutines(c_func_name_1, fn_symtab, 0, arg_types[0]); + fn_symtab->add_symbol(c_func_name_1, s_1); + dep.push_back(al, s2c(al, c_func_name_1)); + body.push_back(al, b.Assignment(args[0], b.Call(s_1, call_args, arg_types[0]))); + } else { + fill_func_arg_sub("date", real32, InOut); + body.push_back(al, b.Assignment(args[0], b.f32(0))); + } + if (!is_real(*arg_types[1])) { + fill_func_arg_sub("time", arg_types[1], InOut); + ASR::symbol_t *s_2 = b.create_c_func_subroutines(c_func_name_2, fn_symtab, 0, arg_types[1]); + fn_symtab->add_symbol(c_func_name_2, s_2); + dep.push_back(al, s2c(al, c_func_name_2)); + body.push_back(al, b.Assignment(args[1], b.Call(s_2, call_args, arg_types[1]))); + } else { + fill_func_arg_sub("time", real32, InOut); + body.push_back(al, b.Assignment(args[1], b.f32(0))); + } + if (!is_real(*arg_types[2])) { + fill_func_arg_sub("zone", arg_types[2], InOut); + ASR::symbol_t *s_3 = b.create_c_func_subroutines(c_func_name_3, fn_symtab, 0, arg_types[2]); + fn_symtab->add_symbol(c_func_name_3, s_3); + dep.push_back(al, s2c(al, c_func_name_3)); + body.push_back(al, b.Assignment(args[2], b.Call(s_3, call_args, arg_types[2]))); + } else { + fill_func_arg_sub("zone", real32, InOut); + body.push_back(al, b.Assignment(args[2], b.f32(0))); + } + if (!is_real(*arg_types[3])) { + fill_func_arg_sub("values", arg_types[3], InOut); + std::vector vals; + ASR::symbol_t *s_4 = b.create_c_func_subroutines(c_func_name_4, fn_symtab, 1, int32); + fn_symtab->add_symbol(c_func_name_4, s_4); + dep.push_back(al, s2c(al, c_func_name_4)); + for (int i = 0; i < 8; i++) { + Vec call_args2; call_args2.reserve(al, 1); + call_args2.push_back(al, b.i32(i+1)); + auto xx = declare("i_" + std::to_string(i), int32, Local); + body.push_back(al, b.Assignment(xx, b.Call(s_4, call_args2, int32))); + vals.push_back(xx); + } + body.push_back(al, b.Assignment(args[3], b.ArrayConstant(vals, extract_type(arg_types[3]), false))); + } else { + fill_func_arg_sub("values", real32, InOut); + body.push_back(al, b.Assignment(args[3], b.f32(0))); + } + ASR::symbol_t *new_symbol = make_ASR_Function_t(fn_name, fn_symtab, dep, args, + body, nullptr, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); + scope->add_symbol(fn_name, new_symbol); + return b.SubroutineCall(new_symbol, new_args); + } + +} // namespace DateAndTime + +namespace GetEnvironmentVariable { + + static inline void verify_args(const ASR::IntrinsicImpureSubroutine_t& x, diag::Diagnostics& diagnostics) { + if (x.n_args == 1) { + ASRUtils::require_impl(ASRUtils::is_character(*ASRUtils::expr_type(x.m_args[0])), "First argument must be of character type", x.base.base.loc, diagnostics); + } else if (x.n_args == 2) { + ASRUtils::require_impl(ASRUtils::is_character(*ASRUtils::expr_type(x.m_args[0])) && ASRUtils::is_character(*ASRUtils::expr_type(x.m_args[1])), "First two arguments of `get_environment_variable` must be of character type", x.base.base.loc, diagnostics); + } + } + + static inline ASR::asr_t* create_GetEnvironmentVariable(Allocator& al, const Location& loc, Vec& args, diag::Diagnostics& /*diag*/) { + Vec m_args; m_args.reserve(al, args.size()); + m_args.push_back(al, args[0]); + for (int i = 1; i < int(args.size()); i++) { + if(args[i]) m_args.push_back(al, args[i]); + } + return ASR::make_IntrinsicImpureSubroutine_t(al, loc, static_cast(IntrinsicImpureSubroutines::GetEnvironmentVariable), m_args.p, m_args.n, 0); + } + + static inline ASR::stmt_t* instantiate_GetEnvironmentVariable(Allocator &al, const Location &loc, + SymbolTable *scope, Vec& arg_types, + Vec& new_args, int64_t /*overload_id*/) { + + std::string c_func_name = "_lfortran_get_environment_variable"; + std::string new_name = "_lcompilers_get_environment_variable_"; + declare_basic_variables(new_name); + fill_func_arg_sub("name", arg_types[0], InOut); + fill_func_arg_sub("value", arg_types[1], InOut); + if (arg_types.size() == 3) { + fill_func_arg_sub("length", arg_types[2], InOut); + } + if (arg_types.size() == 4) { + fill_func_arg_sub("status", arg_types[3], InOut); + } + if (arg_types.size() == 5) { + fill_func_arg_sub("trim_name", arg_types[4], InOut); + } + SymbolTable *fn_symtab_1 = al.make_new(fn_symtab); + + Vec args_1; args_1.reserve(al, 1); + ASR::expr_t *arg = b.Variable(fn_symtab_1, "n", arg_types[0], + ASR::intentType::InOut, ASR::abiType::BindC, true); + args_1.push_back(al, arg); + + ASR::expr_t *return_var_1 = b.Variable(fn_symtab_1, c_func_name, + ASRUtils::type_get_past_array(ASRUtils::type_get_past_allocatable(arg_types[1])), + ASRUtils::intent_return_var, ASR::abiType::BindC, false); + + SetChar dep_1; dep_1.reserve(al, 1); + Vec body_1; body_1.reserve(al, 1); + ASR::symbol_t *s = make_ASR_Function_t(c_func_name, fn_symtab_1, dep_1, args_1, + body_1, return_var_1, ASR::abiType::BindC, ASR::deftypeType::Interface, s2c(al, c_func_name)); + fn_symtab->add_symbol(c_func_name, s); + dep.push_back(al, s2c(al, c_func_name)); + + Vec call_args; call_args.reserve(al, 1); + call_args.push_back(al, args[0]); + body.push_back(al, b.Assignment(args[1], b.Call(s, call_args, arg_types[1]))); + ASR::symbol_t *new_symbol = make_ASR_Function_t(fn_name, fn_symtab, dep, args, + body, nullptr, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); + scope->add_symbol(fn_name, new_symbol); + return b.SubroutineCall(new_symbol, new_args); + } + +} // namespace GetEnvironmentVariable + +namespace ExecuteCommandLine { + + static inline void verify_args(const ASR::IntrinsicImpureSubroutine_t& x, diag::Diagnostics& diagnostics) { + if (x.n_args == 1) { + ASRUtils::require_impl(ASRUtils::is_character(*ASRUtils::expr_type(x.m_args[0])), "First argument must be of character type", x.base.base.loc, diagnostics); + } + } + + static inline ASR::asr_t* create_ExecuteCommandLine(Allocator& al, const Location& loc, Vec& args, diag::Diagnostics& /*diag*/) { + Vec m_args; m_args.reserve(al, args.size()); + m_args.push_back(al, args[0]); + for (int i = 1; i < int(args.size()); i++) { + if(args[i]) m_args.push_back(al, args[i]); + } + return ASR::make_IntrinsicImpureSubroutine_t(al, loc, static_cast(IntrinsicImpureSubroutines::ExecuteCommandLine), m_args.p, m_args.n, 0); + } + + static inline ASR::stmt_t* instantiate_ExecuteCommandLine(Allocator &al, const Location &loc, + SymbolTable *scope, Vec& arg_types, + Vec& new_args, int64_t /*overload_id*/) { + + std::string c_func_name = "_lfortran_exec_command"; + std::string new_name = "_lcompilers_execute_command_line_"; + ASR::symbol_t* s = scope->get_symbol(new_name); + if (s) { + ASRBuilder b(al, loc); + return b.SubroutineCall(s, new_args); + } else { + declare_basic_variables(new_name); + fill_func_arg_sub("command", arg_types[0], InOut); + if (arg_types.size() == 2) { + fill_func_arg_sub("wait", arg_types[1], InOut); + } else if (arg_types.size() == 3) { + fill_func_arg_sub("exitstat", arg_types[2], InOut); + } else if (arg_types.size() == 4) { + fill_func_arg_sub("cmdstat", arg_types[3], InOut); + } else if (arg_types.size() == 5) { + fill_func_arg_sub("cmdmsg", arg_types[4], InOut); + } + + SymbolTable *fn_symtab_1 = al.make_new(fn_symtab); + Vec args_1; args_1.reserve(al, 1); + ASR::expr_t *arg = b.Variable(fn_symtab_1, "n", arg_types[0], + ASR::intentType::InOut, ASR::abiType::BindC, true); + args_1.push_back(al, arg); + + ASR::expr_t *return_var_1 = b.Variable(fn_symtab_1, c_func_name, + ASRUtils::type_get_past_array(ASRUtils::type_get_past_allocatable(arg_types[0])), + ASRUtils::intent_return_var, ASR::abiType::BindC, false); + + SetChar dep_1; dep_1.reserve(al, 1); + Vec body_1; body_1.reserve(al, 1); + ASR::symbol_t *s = make_ASR_Function_t(c_func_name, fn_symtab_1, dep_1, args_1, + body_1, return_var_1, ASR::abiType::BindC, ASR::deftypeType::Interface, s2c(al, c_func_name)); + fn_symtab->add_symbol(c_func_name, s); + dep.push_back(al, s2c(al, c_func_name)); + + Vec call_args; call_args.reserve(al, 1); + call_args.push_back(al, args[0]); + body.push_back(al, b.Assignment(args[0], b.Call(s, call_args, arg_types[0]))); + ASR::symbol_t *new_symbol = make_ASR_Function_t(fn_name, fn_symtab, dep, args, + body, nullptr, ASR::abiType::Intrinsic, ASR::deftypeType::Implementation, nullptr); + scope->add_symbol(fn_name, new_symbol); + return b.SubroutineCall(new_symbol, new_args); + } + } + +} // namespace ExecuteCommandLine + +namespace CpuTime { + + static inline void verify_args(const ASR::IntrinsicImpureSubroutine_t& x, diag::Diagnostics& diagnostics) { + if (x.n_args == 1) { + ASRUtils::require_impl(ASRUtils::is_real(*ASRUtils::expr_type(x.m_args[0])), "First argument must be of real type", x.base.base.loc, diagnostics); + } + } + + static inline ASR::asr_t* create_CpuTime(Allocator& al, const Location& loc, Vec& args, diag::Diagnostics& /*diag*/) { + Vec m_args; m_args.reserve(al, 1); m_args.push_back(al, args[0]); + return ASR::make_IntrinsicImpureSubroutine_t(al, loc, static_cast(IntrinsicImpureSubroutines::CpuTime), m_args.p, m_args.n, 0); + } + + static inline ASR::stmt_t* instantiate_CpuTime(Allocator &al, const Location &loc, + SymbolTable *scope, Vec& arg_types, + Vec& new_args, int64_t /*overload_id*/) { + + std::string c_func_name; + if (ASRUtils::extract_kind_from_ttype_t(arg_types[0]) == 4) { + c_func_name = "_lfortran_s_cpu_time"; + } else { + c_func_name = "_lfortran_d_cpu_time"; + } + std::string new_name = "_lcompilers_cpu_time_" + type_to_str_python(arg_types[0]); + declare_basic_variables(new_name); + fill_func_arg_sub("time", arg_types[0], InOut); + + ASR::symbol_t *s = b.create_c_func_subroutines(c_func_name, fn_symtab, 0, arg_types[0]); + fn_symtab->add_symbol(c_func_name, s); + dep.push_back(al, s2c(al, c_func_name)); + + Vec call_args; call_args.reserve(al, 0); + body.push_back(al, b.Assignment(args[0], b.Call(s, call_args, arg_types[0]))); + ASR::symbol_t *new_symbol = make_ASR_Function_t(fn_name, fn_symtab, dep, args, + body, nullptr, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); + scope->add_symbol(fn_name, new_symbol); + return b.SubroutineCall(new_symbol, new_args); + } + +} // namespace CpuTime + } // namespace LCompilers::ASRUtils #endif // LIBASR_PASS_INTRINSIC_SUBROUTINES_H diff --git a/src/libasr/pass/loop_unroll.cpp b/src/libasr/pass/loop_unroll.cpp index 7a9135a706..b78f01f28f 100644 --- a/src/libasr/pass/loop_unroll.cpp +++ b/src/libasr/pass/loop_unroll.cpp @@ -6,9 +6,6 @@ #include #include -#include -#include -#include #include diff --git a/src/libasr/pass/loop_vectorise.cpp b/src/libasr/pass/loop_vectorise.cpp index ab7cd067a2..86ceb47488 100644 --- a/src/libasr/pass/loop_vectorise.cpp +++ b/src/libasr/pass/loop_vectorise.cpp @@ -6,8 +6,6 @@ #include #include -#include -#include #include diff --git a/src/libasr/pass/nested_vars.cpp b/src/libasr/pass/nested_vars.cpp index 62033c5ee8..65c40ea563 100644 --- a/src/libasr/pass/nested_vars.cpp +++ b/src/libasr/pass/nested_vars.cpp @@ -5,7 +5,7 @@ #include #include #include -#include +#include namespace LCompilers { @@ -114,7 +114,29 @@ class NestedVarVisitor : public ASR::BaseWalkVisitor nesting_depth++; bool is_func_visited = false; for (auto &item : x.m_symtab->get_scope()) { + if ( ASR::is_a(*item.second) ) { + ASR::Variable_t* v = ASR::down_cast(item.second); + if ( ASRUtils::is_array(v->m_type) ) { + ASR::dimension_t* m_dims; + size_t n_dims = ASRUtils::extract_dimensions_from_ttype(v->m_type, m_dims); + for( size_t i = 0; i < n_dims; i++ ) { + if (m_dims[i].m_start) { + if ( ASR::is_a(*m_dims[i].m_start)) { + visit_expr(*m_dims[i].m_start); + } + } + if (m_dims[i].m_length) { + if ( ASR::is_a(*m_dims[i].m_length)) { + visit_expr(*m_dims[i].m_length); + } else if ( ASR::is_a(*m_dims[i].m_length)) { + visit_expr(*m_dims[i].m_length); + } + } + } + } + } if (ASR::is_a(*item.second)) { + ASR::symbol_t* par_func_sym_copy = par_func_sym; par_func_sym = cur_func_sym; ASR::Function_t *s = ASR::down_cast( item.second); @@ -124,7 +146,9 @@ class NestedVarVisitor : public ASR::BaseWalkVisitor visit_stmt(*x.m_body[i]); } } + visit_Function(*s); + par_func_sym = par_func_sym_copy; } } if (!is_func_visited) { @@ -160,18 +184,33 @@ class NestedVarVisitor : public ASR::BaseWalkVisitor void visit_Var(const ASR::Var_t &x) { // Only attempt if we are actually in a nested function if (nesting_depth > 1) { - ASR::Variable_t *v = ASR::down_cast( - ASRUtils::symbol_get_past_external(x.m_v)); - // If the variable is not defined in the current scope, it is a - // "needed global" since we need to be able to access it from the - // nested procedure. - if ( current_scope && - v->m_parent_symtab->get_counter() != current_scope->get_counter()) { - nesting_map[par_func_sym].insert(x.m_v); + ASR::symbol_t* sym = ASRUtils::symbol_get_past_external(x.m_v); + if (!ASR::is_a(*sym)) { + visit_symbol(*sym); + } else { + ASR::Variable_t *v = ASR::down_cast(sym); + // If the variable is not defined in the current scope, it is a + // "needed global" since we need to be able to access it from the + // nested procedure. + if ( current_scope && par_func_sym && + v->m_parent_symtab->get_counter() != current_scope->get_counter()) { + nesting_map[par_func_sym].insert(x.m_v); + } } } } + void visit_SubroutineCall(const ASR::SubroutineCall_t &x) { + ASR::symbol_t* fn_sym = x.m_name; + if ( current_scope && par_func_sym && ASR::is_a(*x.m_name) && ASR::down_cast(x.m_name)->m_type_declaration && + ASRUtils::symbol_parent_symtab(fn_sym)->get_counter() != current_scope->get_counter() && + current_scope->parent && current_scope->parent->parent != nullptr && + (current_scope->parent)->get_counter() == ASRUtils::symbol_parent_symtab(fn_sym)->get_counter() ) { + nesting_map[par_func_sym].insert(fn_sym); + } + ASR::BaseWalkVisitor::visit_SubroutineCall(x); + } + void visit_ArrayBroadcast(const ASR::ArrayBroadcast_t& x) { visit_expr(*x.m_array); } @@ -286,6 +325,16 @@ class ReplaceNestedVisitor: public ASR::CallReplacerOnExpressionsVisitorm_type)); ASR::ttype_t* var_type_ = ASRUtils::type_get_past_array(var_type); + if ( var->m_type_declaration && + ASR::is_a(*ASRUtils::symbol_get_past_external(var->m_type_declaration)) ) { + ASRUtils::SymbolDuplicator sd(al); + ASR::Variable_t* dup_var = ASR::down_cast(sd.duplicate_Variable(var, current_scope)); + dup_var->m_name = s2c(al, new_ext_var); + ASR::symbol_t* dup_sym = (ASR::symbol_t*) dup_var; + current_scope->add_symbol(new_ext_var, dup_sym); + nested_var_to_ext_var[it2] = std::make_pair(module_name, dup_sym); + continue; + } if( ASR::is_a(*var_type_) ) { ASR::StructType_t* struct_t = ASR::down_cast(var_type_); if( current_scope->get_counter() != ASRUtils::symbol_parent_symtab( @@ -293,21 +342,35 @@ class ReplaceNestedVisitor: public ASR::CallReplacerOnExpressionsVisitorget_symbol( ASRUtils::symbol_name(struct_t->m_derived_type)); if( m_derived_type == nullptr ) { - char* fn_name = ASRUtils::symbol_name(struct_t->m_derived_type); - ASR::symbol_t* original_symbol = ASRUtils::symbol_get_past_external(struct_t->m_derived_type); - ASR::asr_t *fn = ASR::make_ExternalSymbol_t( - al, struct_t->m_derived_type->base.loc, - /* a_symtab */ current_scope, - /* a_name */ fn_name, - original_symbol, - ASRUtils::symbol_name(ASRUtils::get_asr_owner(original_symbol)), - nullptr, 0, fn_name, ASR::accessType::Public - ); - m_derived_type = ASR::down_cast(fn); - current_scope->add_symbol(fn_name, m_derived_type); + if (!ASR::is_a( + *ASRUtils::get_asr_owner(ASRUtils::symbol_get_past_external( + struct_t->m_derived_type)))) { + char* fn_name = ASRUtils::symbol_name(struct_t->m_derived_type); + ASR::symbol_t* original_symbol = ASRUtils::symbol_get_past_external(struct_t->m_derived_type); + ASR::asr_t *fn = ASR::make_ExternalSymbol_t( + al, struct_t->m_derived_type->base.loc, + /* a_symtab */ current_scope, + /* a_name */ fn_name, + original_symbol, + ASRUtils::symbol_name(ASRUtils::get_asr_owner(original_symbol)), + nullptr, 0, fn_name, ASR::accessType::Public + ); + m_derived_type = ASR::down_cast(fn); + current_scope->add_symbol(fn_name, m_derived_type); + } else { + ASRUtils::SymbolDuplicator sd(al); + sd.duplicate_symbol(struct_t->m_derived_type, current_scope); + ASR::down_cast( + ASRUtils::get_asr_owner(&var->base))->m_symtab->erase_symbol( + ASRUtils::symbol_name(struct_t->m_derived_type)); + m_derived_type = current_scope->get_symbol( + ASRUtils::symbol_name(struct_t->m_derived_type)); + } } - var_type_ = ASRUtils::TYPE(ASRUtils::make_StructType_t_util(al, struct_t->base.base.loc, - m_derived_type)); + var_type_ = ASRUtils::TYPE(ASR::make_StructType_t(al, struct_t->base.base.loc, + struct_t->m_data_member_types, struct_t->n_data_member_types, + struct_t->m_member_function_types, struct_t->n_member_function_types, + struct_t->m_is_cstruct, m_derived_type)); if( ASR::is_a(*var_type) ) { ASR::Array_t* array_t = ASR::down_cast(var_type); var_type = ASRUtils::make_Array_t_util(al, struct_t->base.base.loc, @@ -364,6 +427,49 @@ class ReplaceNestedVisitor: public ASR::CallReplacerOnExpressionsVisitor(x); + if ( ASRUtils::is_array(xx.m_type) ) { + ASR::Array_t* array = ASR::down_cast(ASRUtils::type_get_past_allocatable_pointer(xx.m_type)); + ASR::dimension_t* m_dims; + size_t n_dims = ASRUtils::extract_dimensions_from_ttype(xx.m_type, m_dims); + for( size_t i = 0; i < n_dims; i++ ) { + if (m_dims[i].m_start) { + if ( ASR::is_a(*m_dims[i].m_start)) { + ASR::expr_t** current_expr_copy_1 = current_expr; + current_expr = const_cast(&(m_dims[i].m_start)); + call_replacer(); + current_expr = current_expr_copy_1; + visit_expr(*m_dims[i].m_start); + } + } + if (m_dims[i].m_length) { + if ( ASR::is_a(*m_dims[i].m_length)) { + ASR::expr_t** current_expr_copy_2 = current_expr; + current_expr = const_cast(&(m_dims[i].m_length)); + call_replacer(); + current_expr = current_expr_copy_2; + visit_expr(*m_dims[i].m_length); + } else if ( ASR::is_a(*m_dims[i].m_length) ) { + ASR::expr_t** current_expr_copy_3 = current_expr; + ASR::expr_t* m_length = const_cast(m_dims[i].m_length); + current_expr = const_cast(&(m_dims[i].m_length)); + ASR::symbol_t* prev_sym = ASR::down_cast(m_length)->m_v; + call_replacer(); + ASR::symbol_t* new_sym = ASR::down_cast(m_length)->m_v; + if ( prev_sym != new_sym ) { + // need to convert this to a pointer + array->m_physical_type = ASR::array_physical_typeType::PointerToDataArray; + } + current_expr = current_expr_copy_3; + visit_expr(*m_dims[i].m_length); + } + } + } + } + ASR::CallReplacerOnExpressionsVisitor::visit_Variable(x); + } + void visit_Function(const ASR::Function_t &x) { nesting_depth++; ASR::Function_t& xx = const_cast(x); @@ -420,12 +526,33 @@ class ReplaceNestedVisitor: public ASR::CallReplacerOnExpressionsVisitor(x); ASRUtils::Call_t_body(al, xx.m_name, xx.m_args, xx.n_args, x.m_dt, - nullptr, false, false); + nullptr, false, ASRUtils::get_class_proc_nopass_val(x.m_name)); } void visit_SubroutineCall(const ASR::SubroutineCall_t &x) { + ASR::SubroutineCall_t& xx = const_cast(x); bool is_in_call_copy = is_in_call; is_in_call = true; + if (nested_var_to_ext_var.find(x.m_name) != nested_var_to_ext_var.end()) { + std::string m_name = nested_var_to_ext_var[x.m_name].first; + ASR::symbol_t *t = nested_var_to_ext_var[x.m_name].second; + char *fn_name = ASRUtils::symbol_name(t); + std::string sym_name = fn_name; + if (current_scope->get_symbol(sym_name) != nullptr) { + return; + } + ASR::asr_t *fn = ASR::make_ExternalSymbol_t( + al, t->base.loc, + /* a_symtab */ current_scope, + /* a_name */ fn_name, + t, + s2c(al, m_name), nullptr, 0, fn_name, + ASR::accessType::Public + ); + ASR::symbol_t *ext_sym = ASR::down_cast(fn); + current_scope->add_symbol(sym_name, ext_sym); + xx.m_name = ext_sym; + } for (size_t i=0; i(x); + ASRUtils::Call_t_body(al, xx.m_name, xx.m_args, xx.n_args, x.m_dt, nullptr, false, ASRUtils::get_class_proc_nopass_val(x.m_name)); } @@ -500,6 +627,34 @@ class AssignNestedVars: public PassUtils::PassVisitor { ); ext_sym = ASR::down_cast(fn); current_scope->add_symbol(sym_name_ext, ext_sym); + } else if (ASR::is_a( + *ASRUtils::symbol_get_past_external(ext_sym)) + && ASR::is_a(*ASRUtils::type_get_past_array( + ASRUtils::type_get_past_allocatable_pointer( + ASR::down_cast( + ASRUtils::symbol_get_past_external(ext_sym))->m_type))) + && ASR::is_a(*ASRUtils::get_asr_owner((ext_sym)))) { + ASR::StructType_t* st = ASR::down_cast(ASRUtils::type_get_past_array( + ASRUtils::type_get_past_allocatable_pointer( + ASR::down_cast( + ASRUtils::symbol_get_past_external(ext_sym))->m_type))); + // Import the Struct as an `ExternalSymbol` into `Program` + ASR::symbol_t* st_sym = ASR::down_cast( + ASR::make_ExternalSymbol_t( + al, + st->m_derived_type->base.loc, + current_scope, + ASRUtils::symbol_name(st->m_derived_type), + st->m_derived_type, + ASR::down_cast( + ext_sym)->m_module_name, + nullptr, + 0, + ASRUtils::symbol_name(st->m_derived_type), + ASR::accessType::Public)); + if (!current_scope->get_symbol(ASRUtils::symbol_name(st->m_derived_type))) { + current_scope->add_symbol(ASRUtils::symbol_name(st->m_derived_type), st_sym); + } } ASR::symbol_t* sym_ = sym; if( current_scope->get_counter() != ASRUtils::symbol_parent_symtab(sym_)->get_counter() ) { @@ -526,6 +681,10 @@ class AssignNestedVars: public PassUtils::PassVisitor { ASRUtils::is_allocatable(ASRUtils::symbol_type(sym))); bool is_ext_sym_allocatable_or_pointer = (ASRUtils::is_pointer(ASRUtils::symbol_type(ext_sym)) || ASRUtils::is_allocatable(ASRUtils::symbol_type(ext_sym))); + bool is_procedure_variable = ASR::is_a(*sym_) && + ASR::down_cast(sym_)->m_type_declaration && + ASR::is_a(*ASRUtils::symbol_get_past_external + (ASR::down_cast(sym_)->m_type_declaration)); if( ASRUtils::is_array(ASRUtils::symbol_type(sym)) || is_sym_allocatable_or_pointer ) { ASR::stmt_t *associate = ASRUtils::STMT(ASRUtils::make_Associate_t_util(al, t->base.loc, target, val, current_scope)); @@ -536,6 +695,8 @@ class AssignNestedVars: public PassUtils::PassVisitor { val, target, current_scope)); assigns_at_end.push_back(associate); } + } else if (is_procedure_variable) { + body.push_back(al, ASRUtils::STMT(ASR::make_Associate_t(al, t->base.loc, target, val))); } else { ASR::stmt_t *assignment = ASRUtils::STMT(ASR::make_Assignment_t(al, t->base.loc, target, val, nullptr)); @@ -606,6 +767,22 @@ class AssignNestedVars: public PassUtils::PassVisitor { ASR::Block_t *s = ASR::down_cast(item.second); visit_Block(*s); } + if (ASR::is_a(*item.second)) { + ASR::Variable_t* v = ASR::down_cast(item.second); + if (ASR::is_a(*ASRUtils::type_get_past_array( + ASRUtils::type_get_past_allocatable_pointer(v->m_type)))) { + // Fix the ttype of variables to point to the imported Struct (as ExternalSymbol) + ASR::StructType_t* st = ASR::down_cast( + ASRUtils::type_get_past_array( + ASRUtils::type_get_past_allocatable_pointer( + v->m_type))); + ASR::down_cast( + ASRUtils::type_get_past_array( + ASRUtils::type_get_past_allocatable_pointer( + v->m_type)))->m_derived_type = current_scope->get_symbol( + ASRUtils::symbol_name(st->m_derived_type)); + } + } } current_scope = current_scope_copy; cur_func_sym = sym_copy; diff --git a/src/libasr/pass/openmp.cpp b/src/libasr/pass/openmp.cpp new file mode 100644 index 0000000000..a275d0fa7d --- /dev/null +++ b/src/libasr/pass/openmp.cpp @@ -0,0 +1,1765 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace LCompilers { + + +class ReplaceArrayPhysicalCast: public ASR::BaseExprReplacer { + private: + Allocator& al; + public: + std::vector array_variables; + + ReplaceArrayPhysicalCast(Allocator& al_) : + al(al_) {} + + void replace_ArrayPhysicalCast(ASR::ArrayPhysicalCast_t* x) { + ASRUtils::ASRBuilder b(al, x->base.base.loc); + ASR::symbol_t* sym = ASR::down_cast(x->m_arg)->m_v; + std::string sym_name = ASRUtils::symbol_name(sym); + if (std::find(array_variables.begin(), array_variables.end(), sym_name) != array_variables.end()) { + *current_expr = b.Var(sym); + } + } +}; + +class ArrayPhysicalCastVisitor : public ASR::CallReplacerOnExpressionsVisitor { + private: + std::string function_name; + ReplaceArrayPhysicalCast replacer; + std::vector &array_variables; + public: + ArrayPhysicalCastVisitor(Allocator &al_, std::vector &array_variables_, std::string function_name_) : + function_name(function_name_), replacer(al_), array_variables(array_variables_) {} + + void call_replacer() { + replacer.array_variables = array_variables; + replacer.current_expr = current_expr; + replacer.replace_expr(*current_expr); + } + + void visit_SubroutineCall(const ASR::SubroutineCall_t &x) { + if (ASRUtils::symbol_name(x.m_name) == function_name) { + CallReplacerOnExpressionsVisitor::visit_SubroutineCall(x); + } + } + + void visit_FunctionCall(const ASR::FunctionCall_t &x) { + if (ASRUtils::symbol_name(x.m_name) == function_name) { + CallReplacerOnExpressionsVisitor::visit_FunctionCall(x); + } + } +}; + +class ReplaceArrayVariable: public ASR::BaseExprReplacer { + private: + Allocator& al; + public: + SymbolTable* current_scope; + std::vector array_variables; + + ReplaceArrayVariable(Allocator& al_) : + al(al_) {} + + void replace_Var(ASR::Var_t* x) { + ASRUtils::ASRBuilder b(al, x->base.base.loc); + if (std::find(array_variables.begin(), array_variables.end(), ASRUtils::symbol_name(x->m_v)) != array_variables.end() && + ASRUtils::symbol_parent_symtab(x->m_v)->counter == current_scope->counter) { + // TODO: Ideally we shall not need any check for the symbol parent symtab + // This is a bug where somehow it changes symbol present in lcompilers_function or say not of the current_scope + ASR::symbol_t* sym = current_scope->get_symbol(std::string(ASRUtils::symbol_name(x->m_v))); + LCOMPILERS_ASSERT(sym != nullptr); + *current_expr = b.Var(sym); + } + } + + void replace_ArrayPhysicalCast(ASR::ArrayPhysicalCast_t* x) { + ASRUtils::ASRBuilder b(al, x->base.base.loc); + if (ASR::is_a(*x->m_arg)) { + ASR::Var_t* var = ASR::down_cast(x->m_arg); + if (std::find(array_variables.begin(), array_variables.end(), ASRUtils::symbol_name(var->m_v)) != array_variables.end() && + ASRUtils::symbol_parent_symtab(var->m_v)->counter == current_scope->counter) { + ASR::symbol_t* sym = current_scope->get_symbol(std::string(ASRUtils::symbol_name(var->m_v))); + LCOMPILERS_ASSERT(sym != nullptr); + *current_expr = b.Var(sym); + } + } + } +}; + +class ArrayVisitor: public ASR::CallReplacerOnExpressionsVisitor { + private: + SymbolTable* current_scope; + ReplaceArrayVariable replacer; + std::vector array_variables; + + public: + ArrayVisitor(Allocator &al_, SymbolTable* current_scope_, std::vector array_variables_) : + current_scope(current_scope_), replacer(al_) , array_variables(array_variables_) {} + + void call_replacer() { + replacer.current_expr = current_expr; + replacer.current_scope = current_scope; + replacer.array_variables = array_variables; + replacer.replace_expr(*current_expr); + } +}; + +class CheckIfAlreadyAllocatedVisitor: public ASR::BaseWalkVisitor { + private: + bool &already_allocated; + int array_variable_index; + std::string function_name; + SymbolTable* current_scope; + std::string array_variable_name; + + public: + CheckIfAlreadyAllocatedVisitor(int array_variable_index_, std::string function_name_, std::string array_variable_name_, bool &already_allocated_) : + already_allocated(already_allocated_), array_variable_index(array_variable_index_), + function_name(function_name_), array_variable_name(array_variable_name_) {} + + void visit_Program(const ASR::Program_t &x) { + ASR::Program_t& xx = const_cast(x); + SymbolTable* current_scope_copy = current_scope; + current_scope = xx.m_symtab; + + BaseWalkVisitor::visit_Program(x); + + current_scope = current_scope_copy; + } + + void visit_Function(const ASR::Function_t &x) { + ASR::Function_t& xx = const_cast(x); + SymbolTable* current_scope_copy = current_scope; + current_scope = xx.m_symtab; + + BaseWalkVisitor::visit_Function(x); + + current_scope = current_scope_copy; + } + + void visit_FunctionCall(const ASR::FunctionCall_t &x) { + if (ASRUtils::symbol_name(x.m_name) == function_name) { + ASR::expr_t* arg = x.m_args[array_variable_index].m_value; + if (ASR::is_a(*arg)) { + arg = ASR::down_cast(arg)->m_arg; + } + if (ASR::is_a(*arg)) { + ASR::ttype_t* sym_type = ASRUtils::symbol_type(current_scope->get_symbol(ASRUtils::symbol_name(ASR::down_cast(arg)->m_v))); + already_allocated &= (ASRUtils::is_pointer(sym_type) || ASRUtils::is_allocatable(sym_type)); + } + } + BaseWalkVisitor::visit_FunctionCall(x); + } + + void visit_SubroutineCall(const ASR::SubroutineCall_t &x) { + if (ASRUtils::symbol_name(x.m_name) == function_name) { + ASR::expr_t* arg = x.m_args[array_variable_index].m_value; + if (ASR::is_a(*arg)) { + arg = ASR::down_cast(arg)->m_arg; + } + if (ASR::is_a(*arg)) { + ASR::ttype_t* sym_type = ASRUtils::symbol_type(current_scope->get_symbol(ASRUtils::symbol_name(ASR::down_cast(arg)->m_v))); + already_allocated &= (ASRUtils::is_pointer(sym_type) || ASRUtils::is_allocatable(sym_type)); + } + } + BaseWalkVisitor::visit_SubroutineCall(x); + } +}; + +class FunctionSubroutineCallVisitor: public ASR::BaseWalkVisitor { + private: + std::string function_name; + SymbolTable* current_scope; + std::vector &scopes; + std::vector &array_variable_indices; + std::vector &array_variables; + std::map>> &scoped_array_variable_map; + + public: + FunctionSubroutineCallVisitor(std::string function_name_, std::vector &scopes_, + std::vector &array_variable_indices_, + std::vector &array_variables_, + std::map>> &scoped_array_variable_map_) : + function_name(function_name_), scopes(scopes_), array_variable_indices(array_variable_indices_), + array_variables(array_variables_), + scoped_array_variable_map(scoped_array_variable_map_) {} + + void visit_Program(const ASR::Program_t &x) { + ASR::Program_t& xx = const_cast(x); + SymbolTable* current_scope_copy = current_scope; + current_scope = xx.m_symtab; + + BaseWalkVisitor::visit_Program(x); + + current_scope = current_scope_copy; + } + + void visit_Function(const ASR::Function_t &x) { + ASR::Function_t& xx = const_cast(x); + SymbolTable* current_scope_copy = current_scope; + current_scope = xx.m_symtab; + + // handle interface + if (x.m_name == function_name) { + ASR::FunctionType_t* func_type = ASR::down_cast(x.m_function_signature); + if (func_type->m_deftype == ASR::deftypeType::Interface) { + scopes.push_back(current_scope); + + for (size_t i = 0; i < array_variable_indices.size(); i++) { + ASR::symbol_t* sym = current_scope->get_symbol(array_variables[i]); + LCOMPILERS_ASSERT(sym != nullptr); + scoped_array_variable_map[current_scope->counter][array_variables[i]].push_back(sym); + } + } + } + + BaseWalkVisitor::visit_Function(x); + + current_scope = current_scope_copy; + } + + void visit_FunctionCall(const ASR::FunctionCall_t& x) { + if (ASRUtils::symbol_name(x.m_name) == function_name) { + scopes.push_back(current_scope); + for (size_t i = 0; i < array_variable_indices.size(); i++) { + ASR::expr_t* arg = x.m_args[array_variable_indices[i]].m_value; + if (ASR::is_a(*arg)) { + arg = ASR::down_cast(arg)->m_arg; + } + if (ASR::is_a(*arg)) { + ASR::Var_t* var = ASR::down_cast(arg); + ASR::symbol_t* sym = current_scope->get_symbol(ASRUtils::symbol_name(var->m_v)); + LCOMPILERS_ASSERT(sym != nullptr); + scoped_array_variable_map[current_scope->counter][array_variables[i]].push_back(sym); + } + } + } + + BaseWalkVisitor::visit_FunctionCall(x); + } + + void visit_SubroutineCall(const ASR::SubroutineCall_t& x) { + if (ASRUtils::symbol_name(x.m_name) == function_name) { + scopes.push_back(current_scope); + for (size_t i = 0; i < array_variable_indices.size(); i++) { + ASR::expr_t* arg = x.m_args[array_variable_indices[i]].m_value; + if (ASR::is_a(*arg)) { + arg = ASR::down_cast(arg)->m_arg; + } + if (ASR::is_a(*arg)) { + ASR::Var_t* var = ASR::down_cast(arg); + ASR::symbol_t* sym = current_scope->get_symbol(ASRUtils::symbol_name(var->m_v)); + LCOMPILERS_ASSERT(sym != nullptr); + scoped_array_variable_map[current_scope->counter][array_variables[i]].push_back(sym); + } + } + } + + BaseWalkVisitor::visit_SubroutineCall(x); + } +}; + +class ReplaceReductionVariable: public ASR::BaseExprReplacer { + private: + Allocator& al; + public: + ASR::expr_t* data_expr; + SymbolTable* current_scope; + std::string thread_data_name; + std::vector reduction_variables; + + ReplaceReductionVariable(Allocator& al_) : + al(al_) {} + + void replace_Var(ASR::Var_t* x) { + if (std::find(reduction_variables.begin(), reduction_variables.end(), ASRUtils::symbol_name(x->m_v)) != reduction_variables.end()) { + ASR::symbol_t* sym = current_scope->get_symbol(thread_data_name + "_" + std::string(ASRUtils::symbol_name(x->m_v))); + LCOMPILERS_ASSERT(sym != nullptr); + *current_expr = ASRUtils::EXPR(ASR::make_StructInstanceMember_t(al, x->base.base.loc, data_expr, sym, ASRUtils::symbol_type(sym), nullptr)); + } + } +}; + +class ReductionVariableVisitor: public ASR::CallReplacerOnExpressionsVisitor { + private: + ASR::expr_t* data_expr; + SymbolTable* current_scope; + std::string thread_data_name; + ReplaceReductionVariable replacer; + std::vector reduction_variables; + + public: + ReductionVariableVisitor(Allocator &al_, SymbolTable* current_scope_, std::string thread_data_name_, ASR::expr_t* data_expr_, + std::vector reduction_variables_) : + data_expr(data_expr_), current_scope(current_scope_), thread_data_name(thread_data_name_), replacer(al_) { + reduction_variables = reduction_variables_; + } + + void call_replacer() { + replacer.data_expr = data_expr; + replacer.current_expr = current_expr; + replacer.current_scope = current_scope; + replacer.thread_data_name = thread_data_name; + replacer.reduction_variables = reduction_variables; + replacer.replace_expr(*current_expr); + } +}; + +class ReplaceExpression: public ASR::BaseExprReplacer { + private: + Allocator& al; + public: + SymbolTable* current_scope; + + ReplaceExpression(Allocator& al_) : + al(al_) {} + + void replace_Var(ASR::Var_t* x) { + ASR::symbol_t* sym = current_scope->get_symbol(ASRUtils::symbol_name(x->m_v)); + LCOMPILERS_ASSERT(sym != nullptr); + *current_expr = ASRUtils::EXPR(ASR::make_Var_t(al, x->base.base.loc, sym)); + } + +}; + +class DoConcurrentStatementVisitor : public ASR::CallReplacerOnExpressionsVisitor { + private: + Allocator& al; + SymbolTable* current_scope; + ReplaceExpression replacer; + + public: + DoConcurrentStatementVisitor(Allocator &al_, SymbolTable* current_scope_) : + al(al_), current_scope(current_scope_), replacer(al_) {} + + void call_replacer() { + replacer.current_expr = current_expr; + replacer.current_scope = current_scope; + replacer.replace_expr(*current_expr); + } + + template + void visit_Call(const T &x) { + T* x_copy = const_cast(&x); + ASR::Function_t* fn = ASR::down_cast( + ASRUtils::symbol_get_past_external(x_copy->m_name)); + ASR::asr_t* asr_owner = ASRUtils::symbol_parent_symtab(x.m_name)->asr_owner; + ASR::symbol_t* fun_sym_for_module = nullptr; + char* module_name = nullptr; + // Steps: + // Create a module add it to current_scope->parent symtab + // Add func to that module symtab + // Overwrite External symbol to x's asr_owner's symtab + if (ASR::is_a(*ASR::down_cast(asr_owner))) { + ASRUtils::SymbolDuplicator duplicator(al); + SymbolTable* module_scope = al.make_new(current_scope->parent); + + module_name = s2c(al, current_scope->parent->get_unique_name("lcompilers_user_defined_functions")); + ASR::asr_t* mo = ASR::make_Module_t( + al, x.base.base.loc, module_scope, + s2c(al, module_name), nullptr, + 0, false, false); + if (current_scope->parent->get_symbol(module_name) == nullptr) { + current_scope->parent->add_symbol(module_name, ASR::down_cast(mo)); + } + + ASR::Module_t* module = ASR::down_cast(ASR::down_cast(mo)); + fun_sym_for_module = duplicator.duplicate_Function(fn, module_scope); + module->m_symtab->add_symbol(fn->m_name, fun_sym_for_module); + + ASR::asr_t* ext_fn = ASR::make_ExternalSymbol_t( + al, + x.base.base.loc, + ASRUtils::symbol_parent_symtab(x.m_name), + fn->m_name, + fun_sym_for_module, + s2c(al, module_name), + nullptr, + 0, + x_copy->m_original_name + ? ASRUtils::symbol_name(x_copy->m_original_name) + : ASRUtils::symbol_name(x_copy->m_name), + ASR::accessType::Public); + ASR::Program_t* program = ASR::down_cast( + ASR::down_cast(asr_owner)); + program->m_symtab->add_or_overwrite_symbol(fn->m_name, + ASR::down_cast(ext_fn)); + } + + ASR::symbol_t* func_sym = current_scope->get_symbol(ASRUtils::symbol_name(x.m_name)); + if (func_sym == nullptr) { + if (ASR::is_a(*ASR::down_cast(asr_owner))) { + ASR::asr_t* ext_fn = ASR::make_ExternalSymbol_t( + al, + x.base.base.loc, + current_scope, + fn->m_name, + fun_sym_for_module, + s2c(al, module_name), + nullptr, + 0, + x_copy->m_original_name + ? ASRUtils::symbol_name(x_copy->m_original_name) + : ASRUtils::symbol_name(x_copy->m_name), + ASR::accessType::Public); + current_scope->add_or_overwrite_symbol(fn->m_name, + ASR::down_cast(ext_fn)); + func_sym = current_scope->get_symbol(fn->m_name); + } else if (ASR::is_a(*ASR::down_cast(asr_owner))) { + func_sym = current_scope->resolve_symbol(fn->m_name); + } + } + LCOMPILERS_ASSERT(func_sym != nullptr); + x_copy->m_name = func_sym; + x_copy->m_original_name = func_sym; + } + + void visit_FunctionCall(const ASR::FunctionCall_t &x) { + visit_Call(x); + CallReplacerOnExpressionsVisitor::visit_FunctionCall(x); + } + + void visit_SubroutineCall(const ASR::SubroutineCall_t &x) { + visit_Call(x); + CallReplacerOnExpressionsVisitor::visit_SubroutineCall(x); + } +}; + +class InvolvedSymbolsCollector: + public ASR::BaseWalkVisitor +{ + private: + std::map &symbols; + public: + InvolvedSymbolsCollector(std::map &symbols) : + symbols(symbols) {} + + void visit_Var(const ASR::Var_t &x) { + symbols[to_lower(ASRUtils::symbol_name(x.m_v))] = ASRUtils::symbol_type(x.m_v); + return; + } +}; + +// Replaces all the symbols used inside the DoConcurrentLoop region with the +// same symbols passed as argument to the function +class ReplaceSymbols: public ASR::BaseExprReplacer { +private: + SymbolTable &fn_scope; + +public: + ReplaceSymbols(SymbolTable &fn_scope) : fn_scope(fn_scope) {} + + void replace_Var(ASR::Var_t *x) { + x->m_v = fn_scope.get_symbol(ASRUtils::symbol_name(x->m_v)); + } + + void replace_FunctionCall(ASR::FunctionCall_t* x) { + x->m_name = fn_scope.get_symbol(ASRUtils::symbol_name(x->m_name)); + if (x->m_original_name) x->m_original_name = fn_scope.get_symbol(ASRUtils::symbol_name(x->m_original_name)); + } +}; + +// Expression visitor to call the replacer +class ReplaceSymbolsVisitor: + public ASR::CallReplacerOnExpressionsVisitor { + +private: + ReplaceSymbols replacer; + +public: + ReplaceSymbolsVisitor(SymbolTable &fn_scope): replacer(fn_scope) { } + + void call_replacer() { + replacer.current_expr = current_expr; + replacer.replace_expr(*current_expr); + } + + void visit_FunctionCall(const ASR::FunctionCall_t &x) { + replacer.replace_expr(&const_cast(&x)->base); + } +}; + +class ReplaceStatements: public ASR::BaseStmtReplacer { +private: + SymbolTable &scope; + +public: + ReplaceStatements(SymbolTable &scope) : scope(scope) {} + + void replace_SubroutineCall(ASR::SubroutineCall_t* x) { + x->m_name = scope.get_symbol(ASRUtils::symbol_name(x->m_name)); + if (x->m_original_name) x->m_original_name = scope.get_symbol(ASRUtils::symbol_name(x->m_original_name)); + } + +}; + +class ReplaceStatementsVisitor: public ASR::CallReplacerOnExpressionsVisitor { +private: + ReplaceStatements replacer; + +public: + ReplaceStatementsVisitor(SymbolTable &scope) : replacer(scope) {} + + void visit_SubroutineCall(const ASR::SubroutineCall_t &x) { + replacer.replace_stmt(&const_cast(&x)->base); + } + +}; + +class DoConcurrentVisitor : + public ASR::BaseWalkVisitor +{ + private: + Allocator& al; + bool remove_original_statement; + Vec pass_result; + Vec pass_result_allocatable; + SymbolTable* current_scope; + PassOptions pass_options; + int current_stmt_index = -1; + ASR::stmt_t** current_m_body; size_t current_n_body; + std::vector reduction_variables; + public: + DoConcurrentVisitor(Allocator& al_, PassOptions pass_options_) : + al(al_), remove_original_statement(false), pass_options(pass_options_) { + pass_result.n = 0; + pass_result_allocatable.n = 0; + } + + void transform_stmts(ASR::stmt_t **&m_body, size_t &n_body) { + bool remove_original_statement_copy = remove_original_statement; + Vec body; + body.reserve(al, n_body); + current_m_body = m_body; + current_n_body = n_body; + for (size_t i=0; i body; + body.reserve(al, n_body); + current_m_body = m_body; + current_n_body = n_body; + for (size_t i=0; im_symtab->get_scope()) { + if( current_scope->get_symbol(item.first) != nullptr ) { + continue; + } + // TODO: only import "public" symbols from the module + if (ASR::is_a(*item.second)) { + ASR::Function_t *mfn = ASR::down_cast(item.second); + ASR::asr_t *fn = ASR::make_ExternalSymbol_t( + al, mfn->base.base.loc, + /* a_symtab */ current_scope, + /* a_name */ mfn->m_name, + (ASR::symbol_t*)mfn, + m->m_name, nullptr, 0, mfn->m_name, + ASR::accessType::Public + ); + std::string sym = to_lower(mfn->m_name); + current_scope->add_symbol(sym, ASR::down_cast(fn)); + } else if (ASR::is_a(*item.second)) { + ASR::GenericProcedure_t *gp = ASR::down_cast< + ASR::GenericProcedure_t>(item.second); + ASR::asr_t *ep = ASR::make_ExternalSymbol_t( + al, gp->base.base.loc, + current_scope, + /* a_name */ gp->m_name, + (ASR::symbol_t*)gp, + m->m_name, nullptr, 0, gp->m_name, + ASR::accessType::Public + ); + std::string sym = to_lower(gp->m_name); + current_scope->add_symbol(sym, ASR::down_cast(ep)); + } else if (ASR::is_a(*item.second)) { + ASR::CustomOperator_t *gp = ASR::down_cast< + ASR::CustomOperator_t>(item.second); + ASR::asr_t *ep = ASR::make_ExternalSymbol_t( + al, gp->base.base.loc, + current_scope, + /* a_name */ gp->m_name, + (ASR::symbol_t*)gp, + m->m_name, nullptr, 0, gp->m_name, + ASR::accessType::Public + ); + std::string sym = to_lower(gp->m_name); + current_scope->add_symbol(sym, ASR::down_cast(ep)); + } else if (ASR::is_a(*item.second)) { + ASR::Variable_t *mvar = ASR::down_cast(item.second); + // check if m_access of mvar is public + if ( mvar->m_access == ASR::accessType::Public || to_submodule ) { + ASR::asr_t *var = ASR::make_ExternalSymbol_t( + al, mvar->base.base.loc, + /* a_symtab */ current_scope, + /* a_name */ mvar->m_name, + (ASR::symbol_t*)mvar, + m->m_name, nullptr, 0, mvar->m_name, + ASR::accessType::Public + ); + std::string sym = to_lower(mvar->m_name); + current_scope->add_symbol(sym, ASR::down_cast(var)); + } + } else if (ASR::is_a(*item.second)) { + // We have to "repack" the ExternalSymbol so that it lives in the + // local symbol table + ASR::ExternalSymbol_t *es0 = ASR::down_cast(item.second); + std::string sym; + sym = to_lower(es0->m_original_name); + ASR::asr_t *es = ASR::make_ExternalSymbol_t( + al, es0->base.base.loc, + /* a_symtab */ current_scope, + /* a_name */ s2c(al, sym), + es0->m_external, + es0->m_module_name, nullptr, 0, + es0->m_original_name, + ASR::accessType::Public + ); + current_scope->add_or_overwrite_symbol(sym, ASR::down_cast(es)); + } else if( ASR::is_a(*item.second) ) { + ASR::Struct_t *mv = ASR::down_cast(item.second); + // `mv` is the Variable in a module. Now we construct + // an ExternalSymbol that points to it. + Str name; + name.from_str(al, item.first); + char *cname = name.c_str(al); + ASR::asr_t *v = ASR::make_ExternalSymbol_t( + al, mv->base.base.loc, + /* a_symtab */ current_scope, + /* a_name */ cname, + (ASR::symbol_t*)mv, + m->m_name, nullptr, 0, mv->m_name, + ASR::accessType::Public + ); + current_scope->add_symbol(item.first, ASR::down_cast(v)); + } else if (ASR::is_a(*item.second)) { + ASR::Requirement_t *req = ASR::down_cast(item.second); + Str name; + name.from_str(al, item.first); + char *cname = name.c_str(al); + ASR::asr_t *v = ASR::make_ExternalSymbol_t( + al, req->base.base.loc, + current_scope, + cname, + (ASR::symbol_t*)req, + m->m_name, nullptr, 0, req->m_name, + ASR::accessType::Public + ); + current_scope->add_symbol(item.first, ASR::down_cast(v)); + } else if (ASR::is_a(*item.second)) { + ASR::Template_t *temp = ASR::down_cast(item.second); + Str name; + name.from_str(al, item.first); + char *cname = name.c_str(al); + ASR::asr_t *v = ASR::make_ExternalSymbol_t( + al, temp->base.base.loc, + current_scope, + cname, + (ASR::symbol_t*)temp, + m->m_name, nullptr, 0, temp->m_name, + ASR::accessType::Public + ); + current_scope->add_symbol(item.first, ASR::down_cast(v)); + } else { + return item.first; + } + } + return ""; + } + + ASR::symbol_t* create_module(const Location& loc, std::string module_name) { + SymbolTable* current_scope_copy = current_scope; + while (current_scope->parent != nullptr) { + current_scope = current_scope->parent; + } + SetChar module_dependencies; module_dependencies.reserve(al, 1); + module_dependencies.push_back(al, s2c(al, module_name)); + LCompilers::LocationManager lm; + lm.file_ends.push_back(0); + LCompilers::LocationManager::FileLocations file; + file.out_start.push_back(0); file.in_start.push_back(0); file.in_newlines.push_back(0); + file.in_filename = "test"; file.current_line = 1; file.preprocessor = false; file.out_start0.push_back(0); + file.in_start0.push_back(0); file.in_size0.push_back(0); file.interval_type0.push_back(0); + file.in_newlines0.push_back(0); + lm.files.push_back(file); + ASR::symbol_t* module_sym = (ASR::symbol_t*)(ASRUtils::load_module(al, current_scope, + module_name, loc, false, pass_options, true, + [&](const std::string &/*msg*/, const Location &/*loc*/) { }, lm + )); + LCOMPILERS_ASSERT(module_sym != nullptr && ASR::is_a(*module_sym)); + current_scope = current_scope_copy; + return module_sym; + } + + std::pair create_thread_data_module(std::map &involved_symbols, const Location& loc) { + SymbolTable* current_scope_copy = current_scope; + while (current_scope->parent != nullptr) { + current_scope = current_scope->parent; + } + SetChar module_dependencies; module_dependencies.reserve(al, 1); + module_dependencies.push_back(al, s2c(al, "iso_c_binding")); + LCompilers::LocationManager lm; + lm.file_ends.push_back(0); + LCompilers::LocationManager::FileLocations file; + file.out_start.push_back(0); file.in_start.push_back(0); file.in_newlines.push_back(0); + file.in_filename = "test"; file.current_line = 1; file.preprocessor = false; file.out_start0.push_back(0); + file.in_start0.push_back(0); file.in_size0.push_back(0); file.interval_type0.push_back(0); + file.in_newlines0.push_back(0); + lm.files.push_back(file); + ASR::symbol_t* iso_c_binding = (ASR::symbol_t*)(ASRUtils::load_module(al, current_scope, + "iso_c_binding", loc, false, pass_options, true, + [&](const std::string &/*msg*/, const Location &/*loc*/) { }, lm + )); + LCOMPILERS_ASSERT(iso_c_binding != nullptr && ASR::is_a(*iso_c_binding)); + current_scope = al.make_new(current_scope); + std::string unsupported_sym_name = import_all(ASR::down_cast(iso_c_binding)); + LCOMPILERS_ASSERT(unsupported_sym_name == ""); + + // create Struct + ASRUtils::ASRBuilder b(al, loc); + SymbolTable* parent_scope = current_scope; + current_scope = al.make_new(parent_scope); + SetChar involved_symbols_set; involved_symbols_set.reserve(al, involved_symbols.size()); + for (auto it: involved_symbols) { + ASR::ttype_t* sym_type = nullptr; + bool is_array = ASRUtils::is_array(it.second); + sym_type = is_array ? b.CPtr() : it.second; + b.VariableDeclaration(current_scope, it.first, sym_type, ASR::intentType::Local); + if (is_array) { + // add lbound and ubound variables for array + ASR::Array_t* arr_type = ASR::down_cast(ASRUtils::type_get_past_allocatable(ASRUtils::type_get_past_pointer(it.second))); + for (size_t i = 0; i < arr_type->n_dims; i++) { + std::string lbound_name = "lbound_" + it.first + "_" + std::to_string(i); + std::string ubound_name = "ubound_" + it.first + "_" + std::to_string(i); + b.VariableDeclaration(current_scope, lbound_name, ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)), ASR::intentType::Local); + b.VariableDeclaration(current_scope, ubound_name, ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)), ASR::intentType::Local); + involved_symbols_set.push_back(al, s2c(al, lbound_name)); + involved_symbols_set.push_back(al, s2c(al, ubound_name)); + } + } + involved_symbols_set.push_back(al, s2c(al, it.first)); + } + std::string thread_data_module_name = parent_scope->parent->get_unique_name("thread_data_module"); + std::string suffix = thread_data_module_name.substr(18); + std::string thread_data_name = "thread_data" + suffix; + ASR::symbol_t* thread_data_struct = ASR::down_cast(ASR::make_Struct_t(al, loc, + current_scope, s2c(al, thread_data_name), nullptr, 0, involved_symbols_set.p, involved_symbols_set.n, nullptr, 0, ASR::abiType::Source, + ASR::accessType::Public, false, false, nullptr, 0, nullptr, nullptr)); + current_scope->parent->add_symbol(thread_data_name, thread_data_struct); + current_scope = parent_scope; + ASR::symbol_t* thread_data_module = ASR::down_cast(ASR::make_Module_t(al, loc, + current_scope, s2c(al, thread_data_module_name), + module_dependencies.p, module_dependencies.n, false, false)); + current_scope->parent->add_symbol(thread_data_module_name, thread_data_module); + current_scope = current_scope_copy; + return {thread_data_module_name, thread_data_struct}; + } + + std::vector create_modules_for_lcompilers_function(const Location &loc) { + std::vector module_symbols; + ASR::symbol_t* mod_sym = create_module(loc, "iso_c_binding"); + LCOMPILERS_ASSERT(mod_sym != nullptr && ASR::is_a(*mod_sym)); + module_symbols.push_back(mod_sym); + mod_sym = create_module(loc, "omp_lib"); + LCOMPILERS_ASSERT(mod_sym != nullptr && ASR::is_a(*mod_sym)); + module_symbols.push_back(mod_sym); + return module_symbols; + } + + ASR::symbol_t* create_lcompilers_function(const Location &loc, const ASR::DoConcurrentLoop_t &do_loop, + std::map &involved_symbols, std::string thread_data_module_name, + std::vector module_symbols) { + SymbolTable* current_scope_copy = current_scope; + while (current_scope->parent != nullptr) { + current_scope = current_scope->parent; + } + current_scope = al.make_new(current_scope); + // load modules + std::string unsupported_sym_name = import_all(ASR::down_cast(module_symbols[0])); + LCOMPILERS_ASSERT(unsupported_sym_name == ""); + unsupported_sym_name = import_all(ASR::down_cast(module_symbols[1])); + LCOMPILERS_ASSERT(unsupported_sym_name == ""); + ASR::symbol_t* mod_sym = create_module(loc, thread_data_module_name); + LCOMPILERS_ASSERT(mod_sym != nullptr && ASR::is_a(*mod_sym)); + unsupported_sym_name = import_all(ASR::down_cast(mod_sym)); + LCOMPILERS_ASSERT(unsupported_sym_name == ""); + + + ASRUtils::ASRBuilder b(al, loc); + ASR::symbol_t* thread_data_sym = current_scope->get_symbol("thread_data" + thread_data_module_name.substr(18)); + ASR::symbol_t* thread_data_ext_sym = ASRUtils::symbol_get_past_external(thread_data_sym); + + // create data variable: `type(c_ptr), value :: data` + ASR::expr_t* data_expr = b.Variable(current_scope, "data", ASRUtils::TYPE(ASR::make_CPtr_t(al, loc)), ASR::intentType::Unspecified, + ASR::abiType::BindC, true); + LCOMPILERS_ASSERT(data_expr != nullptr); + + // create tdata variable: `type(thread_data), pointer :: tdata` + ASR::expr_t* tdata_expr = b.Variable(current_scope, "tdata", ASRUtils::TYPE(ASR::make_Pointer_t(al, loc, ASRUtils::TYPE(ASRUtils::make_StructType_t_util(al, loc, thread_data_sym)))), + ASR::intentType::Local, ASR::abiType::BindC); + LCOMPILERS_ASSERT(tdata_expr != nullptr); + + Vec body; body.reserve(al, involved_symbols.size() + 1); + body.push_back(al, b.CPtrToPointer(data_expr, tdata_expr)); + + Vec args; args.reserve(al, 1); + args.push_back(al, data_expr); + + // declare involved variables + for (auto it: involved_symbols) { + LCOMPILERS_ASSERT(b.Variable(current_scope, it.first, it.second, ASR::intentType::Local, ASR::abiType::BindC)); + } + + // add external symbols to struct members, we need those for `data%n = n` + // first process all non-arrays + SymbolTable* thread_data_symtab = ASRUtils::symbol_symtab(thread_data_ext_sym); + for (auto it: involved_symbols) { + std::string sym_name = std::string(ASRUtils::symbol_name(thread_data_sym)) + "_" + it.first; + ASR::symbol_t* sym = ASR::down_cast(ASR::make_ExternalSymbol_t(al, loc, + current_scope, s2c(al, sym_name), thread_data_symtab->resolve_symbol(it.first), ASRUtils::symbol_name(thread_data_sym), nullptr, 0, + s2c(al, it.first), ASR::accessType::Public)); + current_scope->add_symbol(sym_name, sym); + + ASR::ttype_t* sym_type = it.second; + if (!ASRUtils::is_array(sym_type)) { + body.push_back(al, b.Assignment( + b.Var(current_scope->get_symbol(it.first)), + ASRUtils::EXPR(ASR::make_StructInstanceMember_t(al, loc, tdata_expr, + sym, ASRUtils::symbol_type(sym), nullptr)) + )); + } + } + + // then process arrays + for (auto it: involved_symbols) { + std::string sym_name = std::string(ASRUtils::symbol_name(thread_data_sym)) + "_" + it.first; + ASR::symbol_t* sym = current_scope->get_symbol(sym_name); + + // handle arrays + ASR::ttype_t* sym_type = it.second; + if (ASRUtils::is_array(sym_type)) { + ASR::Array_t* array_type = ASR::down_cast(ASRUtils::type_get_past_pointer(sym_type)); + Vec size_args; size_args.reserve(al, array_type->n_dims); + for (size_t i = 0; i < array_type->n_dims; i++) { + std::string ubound_name = std::string(ASRUtils::symbol_name(thread_data_sym)) + "_ubound_" + it.first + "_" + std::to_string(i); + ASR::symbol_t* ubound_sym = ASR::down_cast(ASR::make_ExternalSymbol_t(al, loc, + current_scope, s2c(al, ubound_name), thread_data_symtab->resolve_symbol("ubound_" + it.first + "_" + std::to_string(i)), ASRUtils::symbol_name(thread_data_sym), nullptr, 0, + s2c(al, "ubound_" + it.first + "_" + std::to_string(i)), ASR::accessType::Public)); + current_scope->add_symbol(ubound_name, ubound_sym); + ASR::expr_t* ubound = ASRUtils::EXPR(ASR::make_StructInstanceMember_t(al, loc, tdata_expr, + ubound_sym, ASRUtils::symbol_type(ubound_sym), nullptr)); + std::string lbound_name = std::string(ASRUtils::symbol_name(thread_data_sym)) + "_lbound_" + it.first + "_" + std::to_string(i); + ASR::symbol_t* lbound_sym = ASR::down_cast(ASR::make_ExternalSymbol_t(al, loc, + current_scope, s2c(al, lbound_name), thread_data_symtab->resolve_symbol("lbound_" + it.first + "_" + std::to_string(i)), ASRUtils::symbol_name(thread_data_sym), nullptr, 0, + s2c(al, "lbound_" + it.first + "_" + std::to_string(i)), ASR::accessType::Public)); + current_scope->add_symbol(lbound_name, lbound_sym); + ASR::expr_t* lbound = ASRUtils::EXPR(ASR::make_StructInstanceMember_t(al, loc, tdata_expr, + lbound_sym, ASRUtils::symbol_type(lbound_sym), nullptr)); + size_args.push_back(al, b.Add(b.Sub(ubound, lbound), b.i32(1))); + } + ASR::expr_t* shape = ASRUtils::EXPR(ASRUtils::make_ArrayConstructor_t_util(al, loc, + size_args.p, size_args.n, ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)), ASR::arraystorageType::ColMajor)); + // call c_f_pointer(tdata%, , [ubound-lbound+1]) + body.push_back(al, b.CPtrToPointer( + ASRUtils::EXPR(ASR::make_StructInstanceMember_t(al, loc, tdata_expr, + sym, ASRUtils::symbol_type(sym), nullptr)), + b.Var(current_scope->get_symbol(it.first)), + shape + )); + } + } + + // Partitioning logic + // declare start, end, num_threads, chunk, leftovers, thread_num + // TODO: find a better way to declare these + ASR::ttype_t* int_type = ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)); + ASR::expr_t* start = b.Variable(current_scope, current_scope->get_unique_name("start"), int_type, ASR::intentType::Local, ASR::abiType::BindC); + ASR::expr_t* end = b.Variable(current_scope, current_scope->get_unique_name("end"), int_type, ASR::intentType::Local, ASR::abiType::BindC); + ASR::expr_t* num_threads = b.Variable(current_scope, current_scope->get_unique_name("num_threads"), int_type, ASR::intentType::Local, ASR::abiType::BindC); + ASR::expr_t* chunk = b.Variable(current_scope, current_scope->get_unique_name("chunk"), int_type, ASR::intentType::Local, ASR::abiType::BindC); + ASR::expr_t* leftovers = b.Variable(current_scope, current_scope->get_unique_name("leftovers"), int_type, ASR::intentType::Local, ASR::abiType::BindC); + ASR::expr_t* thread_num = b.Variable(current_scope, current_scope->get_unique_name("thread_num"), int_type, ASR::intentType::Local, ASR::abiType::BindC); + + // update all expr present in DoConcurrent to use the new symbols + DoConcurrentStatementVisitor v(al, current_scope); + v.current_expr = nullptr; + v.visit_DoConcurrentLoop(do_loop); + ASR::do_loop_head_t loop_head = do_loop.m_head[0]; + + /* + do concurrent ( ix =ax:nx, iy = ay:ny, iz=az:nz , ik=ak:nk ) + print *, "iy->", iy, "ix->", ix, "iz->", iz + ! ........some computation .... + end do + + ------To-----> + + total_iterations = (nx - ax + 1) * (ny - ay + 1) * (nz - az + 1) * (nk - ak + 1) - 1 + integer :: I = 0; + do I = 0, total_iterations + ix = (I / ((ny - ay + 1) * (nz - az + 1) * (nk - ak + 1))) + ax + iy = ((I / ((nz - az + 1) * (nk - ak + 1))) % (ny - ay + 1)) + ay + iz = ((I / (nk - ak + 1)) % (nz - az + 1)) + az + ik = (I % (nk - ak + 1)) + ak + ! ... some computation ... + end do + */ + + // total_iterations = (nx - ax + 1) * (ny - ay + 1) * (nz - az + 1) * (nk - ak + 1) - 1 + ASR::expr_t* total_iterations = b.i32(1); + std::vector dimension_lengths; + for (size_t i = 0; i < do_loop.n_head; ++i) { + ASR::do_loop_head_t head = do_loop.m_head[i]; + ASR::expr_t* length = b.Add(b.Sub(head.m_end, head.m_start), b.i32(1)); + dimension_lengths.push_back(length); + total_iterations = b.Mul(total_iterations, length); + } + + // always this shall be IntegerBinOp_t + ASR::expr_t* loop_length = total_iterations; + // ASR::expr_t* loop_length = b.Add(b.Sub(loop_head.m_end, loop_head.m_start), b.i32(1)); + // calculate chunk size + body.push_back(al, b.Assignment(num_threads, + ASRUtils::EXPR(ASR::make_FunctionCall_t(al, loc, current_scope->get_symbol("omp_get_max_threads"), + current_scope->get_symbol("omp_get_max_threads"), nullptr, 0, ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)), nullptr, nullptr)))); + body.push_back(al, b.Assignment(chunk, + b.Div(loop_length, num_threads))); + Vec mod_args; mod_args.reserve(al, 2); + mod_args.push_back(al, loop_length); + mod_args.push_back(al, num_threads); + body.push_back(al, b.Assignment(leftovers, + ASRUtils::EXPR(ASRUtils::make_IntrinsicElementalFunction_t_util(al, loc, + 2, + mod_args.p, 2, 0, ASRUtils::expr_type(loop_length), nullptr)))); + body.push_back(al, b.Assignment(thread_num, + ASRUtils::EXPR(ASR::make_FunctionCall_t(al, loc, current_scope->get_symbol("omp_get_thread_num"), + current_scope->get_symbol("omp_get_thread_num"), nullptr, 0, ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)), nullptr, nullptr)))); + body.push_back(al, b.Assignment(start, b.Mul(chunk, thread_num))); + body.push_back(al, b.If(b.Lt(thread_num, leftovers), { + b.Assignment(start, b.Add(start, thread_num)) + }, { + b.Assignment(start, b.Add(start, leftovers)) + })); + body.push_back(al, b.Assignment(end, b.Add(start, chunk))); + body.push_back(al, b.If(b.Lt(thread_num, leftovers), { + b.Assignment(end, b.Add(end, b.i32(1))) + }, { + // do nothing + })); + + // Partioning logic ends + + // initialize reduction variables + for ( size_t i = 0; i < do_loop.n_reduction; i++ ) { + ASR::reduction_expr_t red = do_loop.m_reduction[i]; + reduction_variables.push_back(ASRUtils::symbol_name(ASR::down_cast(red.m_arg)->m_v)); + switch (red.m_op) { + case ASR::reduction_opType::ReduceAdd : { + body.push_back(al, b.Assignment(red.m_arg, b.constant_t(0.0, ASRUtils::expr_type(red.m_arg)))); + break; + } + case ASR::reduction_opType::ReduceMul : { + body.push_back(al, b.Assignment(red.m_arg, b.constant_t(1.0, ASRUtils::expr_type(red.m_arg)))); + break; + } + case ASR::reduction_opType::ReduceSub : { + body.push_back(al, b.Assignment(red.m_arg, b.constant_t(0.0, ASRUtils::expr_type(red.m_arg)))); + break; + } + case ASR::reduction_opType::ReduceMAX : { + if (ASRUtils::is_integer(*ASRUtils::expr_type(red.m_arg))) { + body.push_back(al, b.Assignment(red.m_arg, b.i_t(INT_MIN, ASRUtils::expr_type(red.m_arg)))); + } else if (ASRUtils::is_real(*ASRUtils::expr_type(red.m_arg))) { + body.push_back(al, b.Assignment(red.m_arg, b.f_t(std::numeric_limits::min(), ASRUtils::expr_type(red.m_arg)))); + } else { + // handle other types + LCOMPILERS_ASSERT(false); + } + break; + } + case ASR::reduction_opType::ReduceMIN : { + if (ASRUtils::is_integer(*ASRUtils::expr_type(red.m_arg))) { + body.push_back(al, b.Assignment(red.m_arg, b.i_t(INT_MAX, ASRUtils::expr_type(red.m_arg)))); + } else if (ASRUtils::is_real(*ASRUtils::expr_type(red.m_arg))) { + body.push_back(al, b.Assignment(red.m_arg, b.f_t(std::numeric_limits::max(), ASRUtils::expr_type(red.m_arg)))); + } else { + // handle other types + LCOMPILERS_ASSERT(false); + } + break; + } + default: { + LCOMPILERS_ASSERT(false); + } + } + } + + // integer :: I = 0; + std::vector flattened_body; + ASR::expr_t* I = b.Variable(current_scope, "I", ASRUtils::TYPE(ASR::make_Integer_t(al, loc, + 4)),ASR::intentType::Local, ASR::abiType::BindC); + + ASR::expr_t* temp_I = I; + for (size_t i = 0; i < do_loop.n_head; ++i) { + ASR::do_loop_head_t head = do_loop.m_head[i]; + ASR::expr_t* computed_var; + + if (i == do_loop.n_head - 1) { + // Last loop variable -> ik = (I % (nk - ak 1)) + ak + Vec mod_args; mod_args.reserve(al, 2); + mod_args.push_back(al, temp_I); + mod_args.push_back(al, dimension_lengths[i]); + computed_var = b.Add(ASRUtils::EXPR(ASRUtils::make_IntrinsicElementalFunction_t_util(al, + loc,2,mod_args.p, 2, 0, ASRUtils::expr_type(dimension_lengths[i]), nullptr)),head.m_start); + } else { + // Intermediate loop variable -> iy = ((I / ((nz - az 1) * (nk - ak 1))) % (ny - ay +1)) ay + ASR::expr_t* product_of_next_dimensions = b.i32(1); + for (size_t j = i + 1 ; j mod_args; mod_args.reserve(al, 2); + mod_args.push_back(al, b.Div(temp_I, product_of_next_dimensions)); + mod_args.push_back(al, dimension_lengths[i]); + computed_var = b.Add(ASRUtils::EXPR(ASRUtils::make_IntrinsicElementalFunction_t_util(al, + loc,2,mod_args.p, 2, 0, ASRUtils::expr_type(dimension_lengths[i]), nullptr)),head.m_start); + } else { + computed_var = b.Add(b.Div(b.Add(temp_I,b.i32(-1)), product_of_next_dimensions),head.m_start); + } + } + + // Add the assignment to the body + flattened_body.push_back(b.Assignment(b.Var(current_scope->resolve_symbol(ASRUtils::symbol_name(ASR::down_cast(head.m_v)->m_v))), + computed_var)); + } + + for (size_t i = 0; i < do_loop.n_body; ++i) { + flattened_body.push_back(do_loop.m_body[i]); + } + // Collapse Ends Here + + body.push_back(al, b.DoLoop(I, b.Add(start, b.i32(1)), end, flattened_body, loop_head.m_increment)); + body.push_back(al, ASRUtils::STMT(ASR::make_SubroutineCall_t(al, loc, current_scope->get_symbol("gomp_barrier"), nullptr, nullptr, 0, nullptr))); + + /* + handle reduction variables if any then: + call gomp_atomic_start() + => perform atomic operation + call gomp_atomic_end() + */ + if (do_loop.n_reduction > 0) { + body.push_back(al, ASRUtils::STMT(ASR::make_SubroutineCall_t(al, loc, + current_scope->get_symbol("gomp_atomic_start"), nullptr, nullptr, 0, nullptr))); + } + for ( size_t i = 0; i < do_loop.n_reduction; i++ ) { + ASR::reduction_expr_t red = do_loop.m_reduction[i]; + ASR::symbol_t* red_sym = current_scope->get_symbol(std::string(ASRUtils::symbol_name(thread_data_sym)) + "_" + std::string(ASRUtils::symbol_name(ASR::down_cast(red.m_arg)->m_v))); + ASR::expr_t* lhs = ASRUtils::EXPR(ASR::make_StructInstanceMember_t(al, loc, tdata_expr, red_sym, ASRUtils::symbol_type(red_sym), nullptr)); + + switch (red.m_op) { + case ASR::reduction_opType::ReduceAdd : { + body.push_back(al, b.Assignment(lhs, b.Add(lhs, red.m_arg))); + break; + } + case ASR::reduction_opType::ReduceSub : { + body.push_back(al, b.Assignment(lhs, b.Sub(lhs, red.m_arg))); + break; + } + case ASR::reduction_opType::ReduceMul : { + body.push_back(al, b.Assignment(lhs, b.Mul(lhs, red.m_arg))); + break; + } + case ASR::reduction_opType::ReduceMAX : { + body.push_back(al, b.If(b.Lt(lhs, red.m_arg), { + b.Assignment(lhs, red.m_arg) + }, { + // do nothing + })); + break; + } + case ASR::reduction_opType::ReduceMIN : { + body.push_back(al, b.If(b.Gt(lhs, red.m_arg), { + b.Assignment(lhs, red.m_arg) + }, { + // do nothing + })); + break; + } + default : { + LCOMPILERS_ASSERT(false); + } + } + } + if (do_loop.n_reduction > 0) { + body.push_back(al, ASRUtils::STMT(ASR::make_SubroutineCall_t(al, loc, + current_scope->get_symbol("gomp_atomic_end"), nullptr, nullptr, 0, nullptr))); + } + + ASR::symbol_t* function = ASR::down_cast(ASRUtils::make_Function_t_util(al, loc, current_scope, s2c(al, current_scope->parent->get_unique_name("lcompilers_function")), + nullptr, 0, + args.p, args.n, + body.p, body.n, + nullptr, ASR::abiType::BindC, ASR::accessType::Public, + ASR::deftypeType::Implementation, nullptr, false, false, false, false, false, + nullptr, 0, + false, false, false, nullptr)); + + current_scope->parent->add_symbol(ASRUtils::symbol_name(function), function); + current_scope = current_scope_copy; + return function; + } + + ASR::ttype_t* f_type_to_c_type(ASR::ttype_t* /*f_type*/) { + // populate it when required + // right now in ASR `integer(c_int) :: n` is represented same as `integer :: n` + return nullptr; + } + + ASR::symbol_t* create_interface_lcompilers_function(ASR::Function_t* func) { + ASRUtils::ASRBuilder b(al, func->base.base.loc); + SymbolTable* current_scope_copy = current_scope; + current_scope = al.make_new(current_scope); + ASR::expr_t* data_expr = b.Variable(current_scope, "data", ASRUtils::TYPE(ASR::make_CPtr_t(al, func->base.base.loc)), ASR::intentType::Unspecified, ASR::abiType::BindC, true); + Vec args; args.reserve(al, 1); + args.push_back(al, data_expr); + ASR::symbol_t* interface_function = ASR::down_cast(ASRUtils::make_Function_t_util(al, func->base.base.loc, + current_scope, func->m_name, func->m_dependencies, func->n_dependencies, + args.p, args.n, nullptr, 0, nullptr, ASR::abiType::BindC, ASR::accessType::Public, + ASR::deftypeType::Interface, nullptr, false, false, false, false, false, nullptr, 0, + false, false, false, nullptr)); + current_scope->parent->add_symbol(ASRUtils::symbol_name(interface_function), interface_function); + current_scope = current_scope_copy; + return interface_function; + } + + /* + This function is invoked only if array variables are used in OMP DoConcurrent + It does the following: + 1. As we changed declaration of array variables to pointers, we need to allocate memory for them + and update the function body accordingly + 2. Update the function signature for array variables + 3. Search for function / subroutine calls to existing function in entire ASR + 4. Recursively call this function for all the function calls found in step 3 + */ + void recursive_function_call_resolver(SymbolTable* current_scope, std::vector array_variables, + std::map>> scoped_array_variable_map, bool first_call=false, std::string func_name = "") { + ASR::asr_t* asr_owner = current_scope->asr_owner; + if (ASR::is_a(*asr_owner)) { + ASR::symbol_t* sym = ASR::down_cast(asr_owner); + if (ASR::is_a(*sym)) { + ASRUtils::ASRBuilder b(al, sym->base.loc); + ASR::Function_t* func = ASR::down_cast(sym); + bool is_interface = ASR::down_cast(func->m_function_signature)->m_deftype == ASR::deftypeType::Interface; + if (!first_call) { + Vec new_body; new_body.reserve(al, func->n_body); + for (size_t i = 0; i < array_variables.size(); i++) { + ASR::symbol_t* sym = current_scope->resolve_symbol(array_variables[i]); + ASR::ttype_t* sym_type = ASRUtils::symbol_type(sym); + // look at comment in Program_t case + if (ASR::is_a(*sym_type)) { + ASR::Array_t* array_type = ASR::down_cast(sym_type); + bool dimension_empty = ASRUtils::is_dimension_empty(*array_type->m_dims); + Vec dims; dims.reserve(al, array_type->n_dims); + ASR::dimension_t empty_dim; empty_dim.loc = array_type->base.base.loc; + empty_dim.m_start = nullptr; empty_dim.m_length = nullptr; + for (size_t i = 0; i < array_type->n_dims; i++) { + dims.push_back(al, empty_dim); + } + ASR::expr_t* array_expr = b.VariableOverwrite(current_scope, ASRUtils::symbol_name(sym), + ASRUtils::TYPE(ASR::make_Pointer_t(al, array_type->base.base.loc, + ASRUtils::TYPE(ASR::make_Array_t(al, array_type->base.base.loc, + array_type->m_type, dims.p, dims.n, ASR::array_physical_typeType::DescriptorArray)))), + check_is_argument(current_scope, ASRUtils::symbol_name(sym)) ? ASR::intentType::InOut : ASR::intentType::Local); + LCOMPILERS_ASSERT(array_expr != nullptr); + /* + We allocate memory for array variables only if we have information about their sizes. + */ + if (!is_interface && !dimension_empty) new_body.push_back(al, b.Allocate(array_expr, array_type->m_dims, array_type->n_dims)); + } + } + for (size_t i = 0; i < func->n_body; i++) { + new_body.push_back(al, func->m_body[i]); + } + func->m_body = new_body.p; + func->n_body = new_body.n; + } + // update function body + ArrayVisitor v(al, func->m_symtab, array_variables); + for (size_t i=0; in_body; i++) { + v.visit_stmt(*func->m_body[i]); + } + + // update function signature for arrays + std::map array_arg_mapping; + for (size_t i = 0; i < func->n_args; i++) { + std::string arg_name = ASRUtils::symbol_name(ASR::down_cast(func->m_args[i])->m_v); + if (std::find(array_variables.begin(), array_variables.end(), arg_name) != array_variables.end()) { + array_arg_mapping[arg_name] = i; + func->m_args[i] = b.Var(func->m_symtab->resolve_symbol(arg_name)); + } + } + ASR::FunctionType_t* func_type = ASR::down_cast(func->m_function_signature); + for (auto it: array_arg_mapping) { + func_type->m_arg_types[it.second] = ASRUtils::symbol_type(func->m_symtab->resolve_symbol(it.first)); + } + + std::vector array_variables_indices; + for (auto it: array_variables) { + array_variables_indices.push_back(array_arg_mapping[it]); + } + + // search for function / subroutine calls to existing function + std::vector scopes; + scoped_array_variable_map.clear(); + FunctionSubroutineCallVisitor fsv(func->m_name, scopes, array_variables_indices, array_variables, scoped_array_variable_map); + + // get global scope + SymbolTable* global_scope = current_scope; + while (global_scope->parent != nullptr) { + global_scope = global_scope->parent; + } + if (!is_interface) fsv.visit_TranslationUnit(*ASR::down_cast2(global_scope->asr_owner)); + + std::vector unique_scopes; + for(auto it: scopes) { + if (std::find(unique_scopes.begin(), unique_scopes.end(), it) == unique_scopes.end()) { + unique_scopes.push_back(it); + } + } + for (auto it: unique_scopes ) { + if (it->counter != current_scope->counter) { + std::vector new_array_variables; + for (auto it2: scoped_array_variable_map[it->counter]) { + for (auto it3: it2.second) { + new_array_variables.push_back(ASRUtils::symbol_name(it3)); + } + } + recursive_function_call_resolver(it, new_array_variables, scoped_array_variable_map, false, func->m_name); + } + } + scopes.clear(); + } else if (ASR::is_a(*sym)) { + ASRUtils::ASRBuilder b(al, sym->base.loc); + ASR::Program_t* prog = ASR::down_cast(sym); + if (!first_call) { + Vec new_body; new_body.reserve(al, prog->n_body); + for (size_t i = 0; i < array_variables.size(); i++) { + ASR::symbol_t* sym = current_scope->get_symbol(array_variables[i]); + ASR::ttype_t* sym_type = ASRUtils::symbol_type(sym); + /* + For pointer and allocatable arrays, we already have the symbol with the correct type + and we don't need to allocate memory for them as they are already allocated. + + So special handling is required only for non-pointer and non-allocatable arrays. + */ + if (ASR::is_a(*sym_type)) { + ASR::Array_t* array_type = ASR::down_cast(sym_type); + /* + More precisely dimension cannot be empty for arrays in program, so + it is just a check to see if we have information about the size of the array. + */ + if (!ASRUtils::is_dimension_empty(*array_type->m_dims)) { + Vec dims; dims.reserve(al, array_type->n_dims); + ASR::dimension_t empty_dim; empty_dim.loc = array_type->base.base.loc; + empty_dim.m_start = nullptr; empty_dim.m_length = nullptr; + for (size_t i = 0; i < array_type->n_dims; i++) { + dims.push_back(al, empty_dim); + } + ASR::expr_t* array_expr = b.VariableOverwrite(prog->m_symtab, ASRUtils::symbol_name(sym), + ASRUtils::TYPE(ASR::make_Pointer_t(al, array_type->base.base.loc, + ASRUtils::TYPE(ASR::make_Array_t(al, array_type->base.base.loc, + array_type->m_type, dims.p, dims.n, ASR::array_physical_typeType::DescriptorArray)))), + ASR::intentType::Local); + LCOMPILERS_ASSERT(array_expr != nullptr); + new_body.push_back(al, b.Allocate(array_expr, array_type->m_dims, array_type->n_dims)); + } else { + // we have no information about what size to allocate + } + } + } + for (size_t i = 0; i < prog->n_body; i++) { + new_body.push_back(al, prog->m_body[i]); + } + prog->m_body = new_body.p; + prog->n_body = new_body.n; + } + // update function body + ArrayVisitor v(al, prog->m_symtab, array_variables); + for (size_t i=0; in_body; i++) { + // we can create a replacer but then there will be too many replacers to handle. + ArrayPhysicalCastVisitor apcv(al, array_variables, func_name); + apcv.current_expr = nullptr; + apcv.visit_stmt(*prog->m_body[i]); + v.visit_stmt(*prog->m_body[i]); + } + } + } else { + LCOMPILERS_ASSERT(false); + } + } + + bool check_is_argument(SymbolTable *current_scope, std::string arg_name) { + if (ASR::is_a(*current_scope->asr_owner) && + ASR::is_a(*ASR::down_cast(current_scope->asr_owner)) ) { + ASR::Function_t* func = ASR::down_cast(ASR::down_cast(current_scope->asr_owner)); + for (size_t i = 0; i < func->n_args; i++) { + if (ASRUtils::symbol_name(ASR::down_cast(func->m_args[i])->m_v) == arg_name) { + return true; + } + } + } + return false; + } + + void visit_DoConcurrentLoop(const ASR::DoConcurrentLoop_t &x) { + std::map involved_symbols; + + InvolvedSymbolsCollector c(involved_symbols); + c.visit_DoConcurrentLoop(x); + if (pass_options.enable_gpu_offloading) { + // + // Implementation details: + // + // 1. Creates a module: `_lcompilers_mlir_gpu_offloading` and + // adds a new function: `_lcompilers_doconcurrent_replacer_func` + // for each `do concurrent` node in the body. + // 2. Move the `do concurrent` into the function body, pass + // all the used variables as an argument to the function. + // 3. Place the subroutine call pointing to the new function. + // 4. The replacer class modifies the variables used in the do + // concurrent body with the same arguments passed to the + // function + // + // The following + // + // do concurrent (i = 1: 10) + // x(i) = i + // end do + // + // becomes: + // + // call _lcompilers_doconcurrent_replacer_func(i, x) + // + // [...] + // + // module _lcompilers_mlir_gpu_offloading + // subroutine _lcompilers_doconcurrent_replacer_func (i, x) + // [...] + // end subroutine + // end module + // + Location loc{x.base.base.loc}; + SymbolTable *scope_copy{current_scope}; + SymbolTable *mod_scope{nullptr}; + std::string mod_name{"_lcompilers_mlir_gpu_offloading"}; + if (ASR::symbol_t *mod = current_scope->resolve_symbol(mod_name)) { + mod_scope = ASR::down_cast(mod)->m_symtab; + } else { + while(current_scope->parent) { + current_scope = current_scope->parent; + } + mod_scope = al.make_new(current_scope); + mod = ASR::down_cast( + ASR::make_Module_t(al, loc, mod_scope, s2c(al, mod_name), + nullptr, 0, false, false)); + current_scope->add_symbol(mod_name, mod); + } + SymbolTable *fn_scope{al.make_new(mod_scope)}; + Vec fn_args; + fn_args.reserve(al, involved_symbols.size()); + Vec call_args; + call_args.reserve(al, involved_symbols.size()); + for (auto &[sym_name, sym_type]: involved_symbols) { + ASR::symbol_t *sym{scope_copy->resolve_symbol(sym_name)}; + ASR::call_arg_t arg; arg.loc = loc; + arg.m_value = ASRUtils::EXPR(ASR::make_Var_t(al, loc, sym)); + call_args.push_back(al, arg); + + sym = ASR::down_cast(ASRUtils::make_Variable_t_util(al, + loc, fn_scope, s2c(al, sym_name), nullptr, 0, + ASR::intentType::InOut, nullptr, nullptr, + ASR::storage_typeType::Default, + ASRUtils::duplicate_type(al, sym_type), + nullptr, ASR::abiType::Source, ASR::accessType::Private, + ASR::presenceType::Required, false)); + fn_scope->add_symbol(sym_name, sym); + fn_args.push_back(al, ASRUtils::EXPR(ASR::make_Var_t(al, loc, sym))); + } + + ReplaceSymbolsVisitor v(*fn_scope); + v.visit_DoConcurrentLoop(x); + + Vec fn_body; fn_body.reserve(al, 1); + fn_body.push_back(al, (ASR::stmt_t *)&x); + + std::string fn_name{mod_scope->get_unique_name( + "_lcompilers_doconcurrent_replacer_func")}; + ASR::symbol_t* function = ASR::down_cast( + ASRUtils::make_Function_t_util(al, loc, fn_scope, + s2c(al, fn_name), nullptr, 0, fn_args.p, fn_args.n, + fn_body.p, fn_body.n, nullptr, ASR::abiType::BindC, + ASR::accessType::Public, ASR::deftypeType::Implementation, + nullptr, false, false, false, false, false, nullptr, 0, + false, false, false, nullptr)); + mod_scope->add_symbol(fn_name, function); + + current_scope = scope_copy; + + SymbolTable *fnI_scope{al.make_new(current_scope)}; + Vec fnI_args; + fnI_args.reserve(al, involved_symbols.size()); + for (auto &[sym_name, sym_type]: involved_symbols) { + ASR::symbol_t *sym{ASR::down_cast( + ASRUtils::make_Variable_t_util(al, loc, fnI_scope, + s2c(al, sym_name), nullptr, 0, ASR::intentType::InOut, + nullptr, nullptr, ASR::storage_typeType::Default, + ASRUtils::duplicate_type(al, sym_type), + nullptr, ASR::abiType::Source, ASR::accessType::Private, + ASR::presenceType::Required, false))}; + fnI_scope->add_symbol(sym_name, sym); + fnI_args.push_back(al, ASRUtils::EXPR( + ASR::make_Var_t(al, loc, sym))); + } + + ASR::symbol_t* fnInterface = ASR::down_cast( + ASRUtils::make_Function_t_util(al, loc, fnI_scope, + s2c(al, fn_name), nullptr, 0, fnI_args.p, fnI_args.n, + nullptr, 0, nullptr, ASR::abiType::BindC, + ASR::accessType::Public, ASR::deftypeType::Interface, + nullptr, false, false, false, false, false, nullptr, 0, + false, false, false, nullptr)); + current_scope->add_symbol(fn_name, fnInterface); + pass_result.push_back(al, ASRUtils::STMT( + ASR::make_SubroutineCall_t(al, loc, fnInterface, fnInterface, + call_args.p, call_args.n, nullptr))); + remove_original_statement = true; + return; + } + + // create thread data module + std::pair thread_data_module = create_thread_data_module(involved_symbols, x.base.base.loc); + std::vector module_symbols = create_modules_for_lcompilers_function(x.base.base.loc); + + // create external symbol for the thread data module + ASR::symbol_t* thread_data_ext_sym = ASR::down_cast(ASR::make_ExternalSymbol_t(al, x.base.base.loc, + current_scope, ASRUtils::symbol_name(thread_data_module.second), thread_data_module.second, s2c(al, thread_data_module.first), + nullptr, 0, ASRUtils::symbol_name(thread_data_module.second), ASR::accessType::Public)); + current_scope->add_symbol(ASRUtils::symbol_name(thread_data_module.second), thread_data_ext_sym); + + std::vector array_variables; + // create data variable for the thread data module + ASRUtils::ASRBuilder b(al, x.base.base.loc); + ASR::expr_t* data_expr = b.Variable(current_scope, current_scope->get_unique_name("data"), ASRUtils::TYPE(ASRUtils::make_StructType_t_util(al, x.base.base.loc, thread_data_ext_sym)), ASR::intentType::Local); + LCOMPILERS_ASSERT(data_expr != nullptr); + + // now create a tdata (cptr) + ASR::expr_t* tdata_expr = b.Variable(current_scope, current_scope->get_unique_name("tdata"), ASRUtils::TYPE(ASR::make_CPtr_t(al, x.base.base.loc)), ASR::intentType::Local); + LCOMPILERS_ASSERT(tdata_expr != nullptr); + + // TODO: update symbols with correct type + for (auto it: involved_symbols) { + ASR::ttype_t* sym_type = it.second; + if (ASR::is_a(*sym_type)) { + // everything is already handled + array_variables.push_back(it.first); + continue; + } else if (ASR::is_a(*ASRUtils::type_get_past_allocatable(sym_type))) { + bool is_argument = check_is_argument(current_scope, it.first); + bool is_allocatable = ASR::is_a(*sym_type); + ASR::Array_t* array_type = ASR::down_cast(ASRUtils::type_get_past_allocatable(sym_type)); + Vec dims; dims.reserve(al, array_type->n_dims); + ASR::dimension_t empty_dim; empty_dim.loc = array_type->base.base.loc; + empty_dim.m_start = nullptr; empty_dim.m_length = nullptr; + for (size_t i = 0; i < array_type->n_dims; i++) { + dims.push_back(al, empty_dim); + } + ASR::expr_t* array_expr = b.VariableOverwrite(current_scope, it.first, + ASRUtils::TYPE(ASR::make_Pointer_t(al, array_type->base.base.loc, + ASRUtils::TYPE(ASR::make_Array_t(al, array_type->base.base.loc, + array_type->m_type, dims.p, dims.n, ASR::array_physical_typeType::DescriptorArray)))), + is_argument ? ASR::intentType::InOut : ASR::intentType::Local); + LCOMPILERS_ASSERT(array_expr != nullptr); + bool already_allocated = true; + if (ASR::is_a(*current_scope->asr_owner) && ASR::is_a(*ASR::down_cast(current_scope->asr_owner))) { + ASR::Function_t* func = ASR::down_cast(ASR::down_cast(current_scope->asr_owner)); + int arg_index = -1; + for (size_t i = 0; i < func->n_args; i++) { + if (ASRUtils::symbol_name(ASR::down_cast(func->m_args[i])->m_v) == it.first) { + arg_index = i; + break; + } + } + if (arg_index != -1) { + /* + Same reasoning as in the comment below, I'll keep this line as well + */ + CheckIfAlreadyAllocatedVisitor v(arg_index, func->m_name, it.first, already_allocated); + SymbolTable* global_scope = current_scope; + while (global_scope->parent != nullptr) { + global_scope = global_scope->parent; + } + v.visit_TranslationUnit(*ASR::down_cast2(global_scope->asr_owner)); + } + } + /* + I will not remove the line below, it is used to allocate memory for arrays present in thread_data module + but we are not sure if that is correct way to do it. + + Based on example ./integration_tests/openmp_15.f90, we will assume that passed on variable is already + allocated and we will not allocate memory for it again. + + This way we can handle arrays with dimension not known at compile time. + + Reason to comment this line can be found in function `recursive_function_call_resolver` + */ + // if (!already_allocated) pass_result.push_back(al, b.Allocate(array_expr, array_type->m_dims, array_type->n_dims)); + /* + If it is not an argument, we need to allocate memory for it. + But if it is also an allocatable, we assume that user will allocate memory for it or code is incorrect. + */ + if (!is_argument && !is_allocatable) pass_result_allocatable.push_back(al, b.Allocate(array_expr, array_type->m_dims, array_type->n_dims)); + involved_symbols[it.first] = ASRUtils::expr_type(array_expr); + array_variables.push_back(it.first); + } + } + + // add external symbols to struct members, we need those for `data%n = n` + ASR::symbol_t* thread_data_sym = thread_data_module.second; + SymbolTable* thread_data_symtab = ASRUtils::symbol_symtab(thread_data_sym); + for (auto it: involved_symbols) { + std::string sym_name = std::string(ASRUtils::symbol_name(thread_data_sym)) + "_" + it.first; + ASR::symbol_t* sym = ASR::down_cast(ASR::make_ExternalSymbol_t(al, x.base.base.loc, + current_scope, s2c(al, sym_name), thread_data_symtab->resolve_symbol(it.first), ASRUtils::symbol_name(thread_data_sym), nullptr, 0, + s2c(al, it.first), ASR::accessType::Public)); + current_scope->add_symbol(sym_name, sym); + + // handle arrays + ASR::ttype_t* sym_type = it.second; + if (ASRUtils::is_array(sym_type)) { + pass_result.push_back(al, b.Assignment( + ASRUtils::EXPR(ASR::make_StructInstanceMember_t(al, x.base.base.loc, data_expr, + sym, ASRUtils::symbol_type(sym), nullptr)), + b.PointerToCPtr(b.Var(current_scope->get_symbol(it.first)), ASRUtils::symbol_type(sym)) + )); + // add sym, assignment for Ubound and Lbound + ASR::Array_t *array_type = ASR::down_cast(ASRUtils::type_get_past_pointer(sym_type)); + for (size_t i = 0; i < array_type->n_dims; i++) { + std::string lbound_name = std::string(ASRUtils::symbol_name(thread_data_sym)) + "_" + "lbound_" + it.first + "_" + std::to_string(i); + ASR::symbol_t* lbound_sym = ASR::down_cast(ASR::make_ExternalSymbol_t(al, x.base.base.loc, + current_scope, s2c(al, lbound_name), thread_data_symtab->resolve_symbol("lbound_" + it.first + "_" + std::to_string(i)), ASRUtils::symbol_name(thread_data_sym), nullptr, 0, + s2c(al, "lbound_" + it.first + "_" + std::to_string(i)), ASR::accessType::Public)); + current_scope->add_symbol(lbound_name, lbound_sym); + pass_result.push_back(al, b.Assignment( + ASRUtils::EXPR(ASR::make_StructInstanceMember_t(al, x.base.base.loc, data_expr, + lbound_sym, ASRUtils::symbol_type(lbound_sym), nullptr)), + b.ArrayLBound(b.Var(current_scope->get_symbol(it.first)), i+1) + )); + std::string ubound_name = std::string(ASRUtils::symbol_name(thread_data_sym)) + "_" + "ubound_" + it.first + "_" + std::to_string(i); + ASR::symbol_t* ubound_sym = ASR::down_cast(ASR::make_ExternalSymbol_t(al, x.base.base.loc, + current_scope, s2c(al, ubound_name), thread_data_symtab->resolve_symbol("ubound_" + it.first + "_" + std::to_string(i)), ASRUtils::symbol_name(thread_data_sym), nullptr, 0, + s2c(al, "ubound_" + it.first + "_" + std::to_string(i)), ASR::accessType::Public)); + current_scope->add_symbol(ubound_name, ubound_sym); + pass_result.push_back(al, b.Assignment( + ASRUtils::EXPR(ASR::make_StructInstanceMember_t(al, x.base.base.loc, data_expr, + ubound_sym, ASRUtils::symbol_type(ubound_sym), nullptr)), + b.ArrayUBound(b.Var(current_scope->get_symbol(it.first)), i+1) + )); + } + } else { + pass_result.push_back(al, b.Assignment( + ASRUtils::EXPR(ASR::make_StructInstanceMember_t(al, x.base.base.loc, data_expr, + sym, ASRUtils::symbol_type(sym), nullptr)), + b.Var(current_scope->get_symbol(it.first)) + )); + } + } + + // tdata = c_loc(data) + pass_result.push_back(al, b.Assignment( + tdata_expr, + ASRUtils::EXPR(ASR::make_PointerToCPtr_t(al, x.base.base.loc, + ASRUtils::EXPR(ASR::make_GetPointer_t(al, x.base.base.loc, data_expr, ASRUtils::TYPE(ASR::make_Pointer_t(al, x.base.base.loc, ASRUtils::expr_type(data_expr))), nullptr)), + ASRUtils::expr_type(tdata_expr), nullptr)) + )); + + ASR::symbol_t* lcompilers_function = create_lcompilers_function(x.base.base.loc, x, involved_symbols, thread_data_module.first, module_symbols); + LCOMPILERS_ASSERT(lcompilers_function != nullptr); + ASR::Function_t* lcompilers_func = ASR::down_cast(lcompilers_function); + ASR::symbol_t* lcompilers_interface_function = create_interface_lcompilers_function(lcompilers_func); + ASR::Function_t* lcompilers_interface_func = ASR::down_cast(lcompilers_interface_function); + + // create interface for the lcompilers function + + // create: c_funloc(lcompilers_function) + ASR::expr_t* c_funloc = ASRUtils::EXPR(ASR::make_PointerToCPtr_t(al, x.base.base.loc, + ASRUtils::EXPR(ASR::make_GetPointer_t(al, x.base.base.loc, + b.Var(lcompilers_interface_function), ASRUtils::TYPE(ASR::make_Pointer_t(al, x.base.base.loc, lcompilers_interface_func->m_function_signature)), nullptr)), + ASRUtils::TYPE(ASR::make_CPtr_t(al, x.base.base.loc)), nullptr)); + + Vec call_args; call_args.reserve(al, 4); + ASR::call_arg_t arg1; arg1.loc = x.base.base.loc; arg1.m_value = c_funloc; + ASR::call_arg_t arg2; arg2.loc = x.base.base.loc; arg2.m_value = tdata_expr; + ASR::call_arg_t arg3; arg3.loc = x.base.base.loc; arg3.m_value = b.i32(0); + ASR::call_arg_t arg4; arg4.loc = x.base.base.loc; arg4.m_value = b.i32(0); + + call_args.push_back(al, arg1); call_args.push_back(al, arg2); + call_args.push_back(al, arg3); call_args.push_back(al, arg4); + + ASR::symbol_t* mod_sym = create_module(x.base.base.loc, "omp_lib"); + LCOMPILERS_ASSERT(mod_sym != nullptr && ASR::is_a(*mod_sym)); + std::string unsupported_sym_name = import_all(ASR::down_cast(mod_sym)); + LCOMPILERS_ASSERT(unsupported_sym_name == ""); + + pass_result.push_back(al, ASRUtils::STMT(ASR::make_SubroutineCall_t(al, x.base.base.loc, current_scope->get_symbol("gomp_parallel"), nullptr, + call_args.p, call_args.n, nullptr))); + + for (auto it: reduction_variables) { + ASR::symbol_t* actual_sym = current_scope->resolve_symbol(it); + ASR::symbol_t* sym = current_scope->get_symbol(std::string(ASRUtils::symbol_name(thread_data_sym)) + "_" + it); + LCOMPILERS_ASSERT(sym != nullptr); + pass_result.push_back(al, b.Assignment( + b.Var(actual_sym), + ASRUtils::EXPR(ASR::make_StructInstanceMember_t(al, x.base.base.loc, data_expr, sym, ASRUtils::symbol_type(sym), nullptr) + ))); + } + reduction_variables.clear(); + + if (array_variables.size() > 0) { + // std::vector function_names; function_names.push_back(ASRUtils::symbol_name(ASR::down_cast(current_scope->asr_owner))); + std::map>> scoped_array_variable_map; + std::string func_name = ""; + if (ASR::is_a(*current_scope->asr_owner)) { + func_name = ASRUtils::symbol_name(ASR::down_cast(current_scope->asr_owner)); + } + recursive_function_call_resolver(current_scope, array_variables, scoped_array_variable_map, true, func_name); + } + + remove_original_statement = true; + return; + } + + void visit_Function(const ASR::Function_t &x) { + // FIXME: this is a hack, we need to pass in a non-const `x`, + // which requires to generate a TransformVisitor. + ASR::Function_t& xx = const_cast(x); + SymbolTable* current_scope_copy = current_scope; + current_scope = xx.m_symtab; + + for (auto &item : x.m_symtab->get_scope()) { + this->visit_symbol(*item.second); + } + + transform_stmts(xx.m_body, xx.n_body); + current_scope = current_scope_copy; + } + + void visit_Program(const ASR::Program_t &x) { + ASR::Program_t& xx = const_cast(x); + SymbolTable* current_scope_copy = current_scope; + current_scope = xx.m_symtab; + + for (auto &a : xx.m_symtab->get_scope()) { + this->visit_symbol(*a.second); + } + + transform_stmts(xx.m_body, xx.n_body); + current_scope = current_scope_copy; + } + + void visit_FunctionCall(const ASR::FunctionCall_t &x) { + SymbolTable* current_scope_copy = current_scope; + current_scope = ASRUtils::symbol_parent_symtab(x.m_name); + + ReplaceSymbolsVisitor sym_replacer(*current_scope); + sym_replacer.visit_FunctionCall(x); + + current_scope = current_scope_copy; + } + + void visit_SubroutineCall(const ASR::SubroutineCall_t &x) { + SymbolTable* current_scope_copy = current_scope; + current_scope = ASRUtils::symbol_parent_symtab(x.m_name); + + ReplaceStatementsVisitor stmt_replacer(*current_scope); + stmt_replacer.visit_SubroutineCall(x); + + current_scope = current_scope_copy; + } + + void visit_DoLoop(const ASR::DoLoop_t &x) { + ASR::DoLoop_t& xx = const_cast(x); + + visit_do_loop_head(xx.m_head); + + transform_stmts_do_loop(xx.m_body, xx.n_body); + transform_stmts_do_loop(xx.m_orelse, xx.n_orelse); + } + +}; + +void pass_replace_openmp(Allocator &al, ASR::TranslationUnit_t &unit, + const PassOptions &pass_options) { + if (pass_options.openmp) { + DoConcurrentVisitor v(al, pass_options); + v.visit_TranslationUnit(unit); + } + return; +} + +} // namespace LCompilers diff --git a/src/libasr/pass/pass_array_by_data.cpp b/src/libasr/pass/pass_array_by_data.cpp index 453acdc30b..f05edc0c71 100644 --- a/src/libasr/pass/pass_array_by_data.cpp +++ b/src/libasr/pass/pass_array_by_data.cpp @@ -9,6 +9,7 @@ #include #include #include +#include /* This ASR to ASR pass can be called whenever you want to avoid @@ -128,9 +129,9 @@ class PassArrayByDataProcedureVisitor : public PassUtils::PassVisitorm_function_signature); + suffix += "_" + ASRUtils::type_to_str_fortran(arg_func->m_function_signature); } else { - suffix += "_" + ASRUtils::type_to_str(arg->m_type); + suffix += "_" + ASRUtils::type_to_str_fortran(arg->m_type); } suffix += "_" + std::to_string(i); } @@ -312,11 +313,72 @@ class EditProcedureReplacer: public ASR::BaseExprReplacer EditProcedureReplacer(PassArrayByDataProcedureVisitor& v_): v(v_), current_scope(nullptr) {} + /* + We need this for the cases where pass array by data is possible for parent function and also + for the child function. Let's take the following example: + ```fortran + subroutine cobyla(x) + implicit none + + real, intent(inout) :: x(:) + call evaluate(calcfc_internal) + contains + + subroutine calcfc_internal(x_internal) + implicit none + real, intent(in) :: x_internal(:) + end subroutine calcfc_internal + + subroutine evaluate(calcfc) + use, non_intrinsic :: pintrf_mod, only : OBJCON + implicit none + procedure(OBJCON) :: calcfc + end subroutine evaluate + + end subroutine + ``` + + Here, cobyla is parent and calcfc_internal is child. What happens is by `bfs` we first + create `cobyla_real____0` and add it as a symbol in global scope. Then we visit `cobyla`, + create `calcfc_internal_real____0` as replacement of `calcfc_internal` and add it as a symbol + in scope of `cobyla`. Now, we visit `cobyla_real____0` and replace `calcfc_internal` with + `calcfc_internal_real____0` + + This means both symbols `cobyla` and `cobyla_real____0` have `calcfc_internal_real____0` as a symbol + but eventually `cobyla` is removed from scope. + + In `proc2newproc` we map `cobyla(1) -> cobyla_real____0(2)` and `calcfc_internal(1.1) -> calcfc_internal_real____0(1.2)` + and also have `calcfc_internal(2.1) -> calcfc_internal_real____0(2.2)`. Where `(x)` represents symtab counter. + + When it comes to replace `call evaluate(calcfc_internal(1.1))`, it gets replaced with `call evaluate(calcfc_internal_real____0(1.2))` + which eventually gets deleted. We need to actually replace it with `call evaluate(calcfc_internal_real____0(2.2))`, so what we do is + we resolve the symbol to the latest symbol in the scope. + + From `calcfc_internal(1.1)`, we get `calcfc_internal_real____0(1.2)` and then we get the parent of `calcfc_internal_real____0(1.2)`, + i.e. `cobyla(1)`, resolve it to `cobyla_real____0(2)` and then get the symbol `calcfc_internal_real____0(2.2)` from it. + */ + ASR::symbol_t* resolve_new_proc(ASR::symbol_t* old_sym) { + ASR::symbol_t* ext_sym = ASRUtils::symbol_get_past_external(old_sym); + if( v.proc2newproc.find(ext_sym) != v.proc2newproc.end() ) { + ASR::symbol_t* new_sym = v.proc2newproc[ext_sym].first; + ASR::asr_t* new_sym_parent = ASRUtils::symbol_parent_symtab(new_sym)->asr_owner; + if ( ASR::is_a(*new_sym_parent) ) { + ASR::symbol_t* resolved_parent_sym = resolve_new_proc(ASR::down_cast(new_sym_parent)); + if ( resolved_parent_sym != nullptr ) { + ASR::symbol_t* sym_to_return = ASRUtils::symbol_symtab(resolved_parent_sym)->get_symbol(ASRUtils::symbol_name(new_sym)); + return sym_to_return ? sym_to_return : new_sym; + } + } + return new_sym; + } + return nullptr; + } + void replace_Var(ASR::Var_t* x) { ASR::symbol_t* x_sym_ = x->m_v; bool is_external = ASR::is_a(*x_sym_); if ( v.proc2newproc.find(ASRUtils::symbol_get_past_external(x_sym_)) != v.proc2newproc.end() ) { - x->m_v = v.proc2newproc[ASRUtils::symbol_get_past_external(x_sym_)].first; + x->m_v = resolve_new_proc(x_sym_); if( is_external ) { ASR::ExternalSymbol_t* x_sym_ext = ASR::down_cast(x_sym_); std::string new_func_sym_name = current_scope->get_unique_name(ASRUtils::symbol_name( @@ -326,12 +388,13 @@ class EditProcedureReplacer: public ASR::BaseExprReplacer s2c(v.al, new_func_sym_name), x->m_v, x_sym_ext->m_module_name, x_sym_ext->m_scope_names, x_sym_ext->n_scope_names, ASRUtils::symbol_name(x->m_v), x_sym_ext->m_access)); + v.proc2newproc[x_sym_] = {new_func_sym_, {}}; current_scope->add_symbol(new_func_sym_name, new_func_sym_); x->m_v = new_func_sym_; } return ; } - + edit_symbol_pointer(v) } @@ -339,15 +402,21 @@ class EditProcedureReplacer: public ASR::BaseExprReplacer ASR::BaseExprReplacer::replace_ArrayPhysicalCast(x); // TODO: Allow for DescriptorArray to DescriptorArray physical cast for allocatables // later on + x->m_old = ASRUtils::extract_physical_type(ASRUtils::expr_type(x->m_arg)); if( (x->m_old == x->m_new && x->m_old != ASR::array_physical_typeType::DescriptorArray) || (x->m_old == x->m_new && x->m_old == ASR::array_physical_typeType::DescriptorArray && (ASR::is_a(*ASRUtils::expr_type(x->m_arg)) || - ASR::is_a(*ASRUtils::expr_type(x->m_arg)))) || - x->m_old != ASRUtils::extract_physical_type(ASRUtils::expr_type(x->m_arg)) ) { + ASR::is_a(*ASRUtils::expr_type(x->m_arg))))) { *current_expr = x->m_arg; } else { - x->m_old = ASRUtils::extract_physical_type(ASRUtils::expr_type(x->m_arg)); + ASR::Array_t* arr = ASR::down_cast(ASRUtils::type_get_past_pointer( + ASRUtils::type_get_past_allocatable(x->m_type))); + if (ASRUtils::is_dimension_empty(arr->m_dims, arr->n_dims)) { + arr->m_dims = ASR::down_cast( + ASRUtils::type_get_past_allocatable(ASRUtils::type_get_past_pointer( + ASRUtils::expr_type(x->m_arg))))->m_dims; + } } } @@ -392,6 +461,27 @@ class EditProcedureVisitor: public ASR::CallReplacerOnExpressionsVisitor::visit_SubroutineCall(x); } + void visit_Module(const ASR::Module_t& x) { + for (auto it: x.m_symtab->get_scope()) { + if ( ASR::is_a(*it.second) && + ASR::down_cast(it.second)->m_type_declaration ) { + ASR::Variable_t* var = ASR::down_cast(it.second); + ASR::symbol_t* resolved_type_dec = nullptr; + if ( v.proc2newproc.find(var->m_type_declaration) != v.proc2newproc.end() ) { + resolved_type_dec = v.proc2newproc[var->m_type_declaration].first; + } else if ( v.proc2newproc.find(ASRUtils::symbol_get_past_external(var->m_type_declaration)) != v.proc2newproc.end() ) { + resolved_type_dec = v.proc2newproc[ASRUtils::symbol_get_past_external(var->m_type_declaration)].first; + } + if ( resolved_type_dec ) { + ASR::Function_t* fn = ASR::down_cast(resolved_type_dec); + var->m_type_declaration = resolved_type_dec; + var->m_type = fn->m_function_signature; + } + } + } + ASR::CallReplacerOnExpressionsVisitor::visit_Module(x); + } + }; /* @@ -424,6 +514,24 @@ class EditProcedureCallsVisitor : public ASR::ASRPassBaseWalkVisitor& not_to_be_erased_): al(al_), v(v_), not_to_be_erased(not_to_be_erased_) {} + // this is exactly the same as the one in EditProcedureReplacer + ASR::symbol_t* resolve_new_proc(ASR::symbol_t* old_sym) { + ASR::symbol_t* ext_sym = ASRUtils::symbol_get_past_external(old_sym); + if( v.proc2newproc.find(ext_sym) != v.proc2newproc.end() ) { + ASR::symbol_t* new_sym = v.proc2newproc[ext_sym].first; + ASR::asr_t* new_sym_parent = ASRUtils::symbol_parent_symtab(new_sym)->asr_owner; + if ( ASR::is_a(*new_sym_parent) ) { + ASR::symbol_t* resolved_parent_sym = resolve_new_proc(ASR::down_cast(new_sym_parent)); + if ( resolved_parent_sym != nullptr ) { + ASR::symbol_t* sym_to_return = ASRUtils::symbol_symtab(resolved_parent_sym)->get_symbol(ASRUtils::symbol_name(new_sym)); + return sym_to_return ? sym_to_return : new_sym; + } + } + return new_sym; + } + return nullptr; + } + template void update_args_for_pass_arr_by_data_funcs_passed_as_callback(const T& x) { bool args_updated = false; @@ -437,7 +545,7 @@ class EditProcedureCallsVisitor : public ASR::ASRPassBaseWalkVisitor(expr); ASR::symbol_t* sym = var->m_v; if ( v.proc2newproc.find(sym) != v.proc2newproc.end() ) { - ASR::symbol_t* new_var_sym = v.proc2newproc[sym].first; + ASR::symbol_t* new_var_sym = resolve_new_proc(sym); ASR::expr_t* new_var = ASRUtils::EXPR(ASR::make_Var_t(al, var->base.base.loc, new_var_sym)); { // update exisiting arg @@ -469,7 +577,11 @@ class EditProcedureCallsVisitor : public ASR::ASRPassBaseWalkVisitor new_args; new_args.reserve(al, n_args); for( size_t i = 0; i < n_args; i++ ) { - if (orig_args[i].m_value == nullptr || - std::find(indices.begin(), indices.end(), i) == indices.end()) { + if (orig_args[i].m_value == nullptr) { + new_args.push_back(al, orig_args[i]); + continue; + } else if (std::find(indices.begin(), indices.end(), i) == indices.end()) { + ASR::expr_t* expr = orig_args[i].m_value; + if (ASR::is_a(*expr)) { + ASR::Var_t* var = ASR::down_cast(expr); + ASR::symbol_t* sym = var->m_v; + if ( v.proc2newproc.find(sym) != v.proc2newproc.end() ) { + ASR::symbol_t* new_var_sym = v.proc2newproc[sym].first; + ASR::expr_t* new_var = ASRUtils::EXPR(ASR::make_Var_t(al, var->base.base.loc, new_var_sym)); + orig_args[i].m_value = new_var; + } + } new_args.push_back(al, orig_args[i]); continue; } @@ -490,7 +614,7 @@ class EditProcedureCallsVisitor : public ASR::ASRPassBaseWalkVisitor( - ASRUtils::type_get_past_allocatable(orig_arg_type)); + ASRUtils::type_get_past_allocatable(ASRUtils::type_get_past_pointer(orig_arg_type))); if( array_t->m_physical_type != ASR::array_physical_typeType::PointerToDataArray ) { ASR::expr_t* physical_cast = ASRUtils::EXPR(ASRUtils::make_ArrayPhysicalCast_t_util( al, orig_arg_i->base.loc, orig_arg_i, array_t->m_physical_type, @@ -534,10 +658,53 @@ class EditProcedureCallsVisitor : public ASR::ASRPassBaseWalkVisitor void visit_Call(const T& x) { + T& xx = const_cast(x); ASR::symbol_t* subrout_sym = x.m_name; bool is_external = ASR::is_a(*subrout_sym); subrout_sym = ASRUtils::symbol_get_past_external(subrout_sym); + if(ASR::is_a(*ASRUtils::symbol_get_past_external(x.m_name))){ + // Case: procedure(cb) :: call_back (Here call_back is variable of type cb which is a function) + ASR::Variable_t* variable = ASR::down_cast(ASRUtils::symbol_get_past_external(x.m_name)); + ASR::symbol_t* type_dec = variable->m_type_declaration; + subrout_sym = ASRUtils::symbol_get_past_external(type_dec); + + // check if subrout_sym is present as value in proc2newproc + bool is_present = false; + std::vector present_indices; + for ( auto it: v.proc2newproc ) { + if (it.second.first == subrout_sym) { + is_present = true; + present_indices = it.second.second; + break; + } + } + + if ( v.proc2newproc.find(subrout_sym) != v.proc2newproc.end()) { + ASR::symbol_t* new_x_name = nullptr; + if (is_external && (v.proc2newproc.find(x.m_name) != v.proc2newproc.end())) { + new_x_name = v.proc2newproc[x.m_name].first; + } else { + new_x_name = resolve_new_proc(x.m_name); + } + if ( new_x_name != nullptr ) { + ASR::Function_t* new_func = ASR::down_cast(resolve_new_proc(subrout_sym)); + ASR::down_cast(ASRUtils::symbol_get_past_external(x.m_name))->m_type = new_func->m_function_signature; + xx.m_name = new_x_name; + xx.m_original_name = new_x_name; + std::vector& indices = v.proc2newproc[subrout_sym].second; + Vec new_args = construct_new_args(x.n_args, x.m_args, indices); + xx.m_args = new_args.p; + xx.n_args = new_args.size(); + return; + } + } else if ( is_present ) { + Vec new_args = construct_new_args(x.n_args, x.m_args, present_indices); + xx.m_args = new_args.p; + xx.n_args = new_args.size(); + return; + } + } if( !can_edit_call(x.m_args, x.n_args) ) { not_to_be_erased.insert(subrout_sym); return ; @@ -548,7 +715,7 @@ class EditProcedureCallsVisitor : public ASR::ASRPassBaseWalkVisitor& indices = v.proc2newproc[subrout_sym].second; Vec new_args = construct_new_args(x.n_args, x.m_args, indices); @@ -582,31 +749,216 @@ class EditProcedureCallsVisitor : public ASR::ASRPassBaseWalkVisitorresolve_symbol(new_func_sym_name) == nullptr ) { - new_func_sym_ = ASR::down_cast( - ASR::make_ExternalSymbol_t(al, x.m_name->base.loc, func_ext_sym->m_parent_symtab, - new_func_sym_name, new_func_sym, func_ext_sym->m_module_name, - func_ext_sym->m_scope_names, func_ext_sym->n_scope_names, new_func_sym_name, - func_ext_sym->m_access)); + if ( ASR::is_a(*ASRUtils::symbol_get_past_external(func_ext_sym->m_external)) && + ASR::down_cast(ASRUtils::symbol_get_past_external(func_ext_sym->m_external))->m_type_declaration ) { + ASR::Variable_t* var = ASR::down_cast(ASRUtils::symbol_get_past_external(func_ext_sym->m_external)); + ASR::symbol_t* type_dec_sym = current_scope->resolve_symbol(ASRUtils::symbol_name(var->m_type_declaration)); + std::string module_name = func_ext_sym->m_module_name; + + if ( type_dec_sym && ASR::is_a(*type_dec_sym) ) { + module_name = ASR::down_cast(type_dec_sym)->m_module_name; + } + new_func_sym_ = ASR::down_cast( + ASR::make_ExternalSymbol_t(al, x.m_name->base.loc, func_ext_sym->m_parent_symtab, + new_func_sym_name, new_func_sym, s2c(al, module_name), + func_ext_sym->m_scope_names, func_ext_sym->n_scope_names, new_func_sym_name, + func_ext_sym->m_access)); + } else { + new_func_sym_ = ASR::down_cast( + ASR::make_ExternalSymbol_t(al, x.m_name->base.loc, func_ext_sym->m_parent_symtab, + new_func_sym_name, new_func_sym, func_ext_sym->m_module_name, + func_ext_sym->m_scope_names, func_ext_sym->n_scope_names, new_func_sym_name, + func_ext_sym->m_access)); + } + func_ext_sym->m_parent_symtab->add_symbol(new_func_sym_name, new_func_sym_); } else { new_func_sym_ = current_scope->resolve_symbol(new_func_sym_name); } } - T& xx = const_cast(x); - xx.m_name = new_func_sym_; - xx.m_original_name = new_func_sym_; + if(!ASR::is_a(*x.m_name)){ + xx.m_name = new_func_sym_; + xx.m_original_name = new_func_sym_; + } else if(v.proc2newproc.find(x.m_name) != v.proc2newproc.end()){ + xx.m_name = resolve_new_proc(x.m_name); + xx.m_original_name = resolve_new_proc(x.m_name); + } xx.m_args = new_args.p; xx.n_args = new_args.size(); } + void visit_TranslationUnit(const ASR::TranslationUnit_t &x) { + SymbolTable* current_scope_copy = current_scope; + current_scope = x.m_symtab; + for (auto &a : x.m_symtab->get_scope()) { + if (ASR::is_a(*a.second)) { + this->visit_symbol(*a.second); + } + } + for (auto &a : x.m_symtab->get_scope()) { + if (!ASR::is_a(*a.second)) { + this->visit_symbol(*a.second); + } + } + current_scope = current_scope_copy; + } + + void visit_Program(const ASR::Program_t &x) { + ASR::Program_t& xx = const_cast(x); + SymbolTable* current_scope_copy = current_scope; + current_scope = x.m_symtab; + for (auto &a : x.m_symtab->get_scope()) { + if(!ASR::is_a(*a.second)){ + this->visit_symbol(*a.second); + } + } + for (auto &a : x.m_symtab->get_scope()) { + if(ASR::is_a(*a.second)){ + this->visit_symbol(*a.second); + } + } + this->transform_stmts(xx.m_body, xx.n_body); + current_scope = current_scope_copy; + } + + void visit_Module(const ASR::Module_t &x) { + SymbolTable* current_scope_copy = current_scope; + current_scope = x.m_symtab; + for (auto &a : x.m_symtab->get_scope()) { + if(!ASR::is_a(*a.second)){ + this->visit_symbol(*a.second); + } + } + for (auto &a : x.m_symtab->get_scope()) { + if(ASR::is_a(*a.second)){ + this->visit_symbol(*a.second); + } + } + current_scope = current_scope_copy; + } + void visit_SubroutineCall(const ASR::SubroutineCall_t& x) { - visit_Call(x); ASR::ASRPassBaseWalkVisitor::visit_SubroutineCall(x); + visit_Call(x); } void visit_FunctionCall(const ASR::FunctionCall_t& x) { - visit_Call(x); ASR::ASRPassBaseWalkVisitor::visit_FunctionCall(x); + visit_Call(x); + } + + void visit_Variable(const ASR::Variable_t &x) { + if (v.proc2newproc.find((ASR::symbol_t*) &x) != v.proc2newproc.end()){ + return; + } + // Case: procedure(cb) :: call_back (Here call_back is variable of type cb which is a function) + ASR::symbol_t* type_dec = x.m_type_declaration; + if (v.proc2newproc.find(ASRUtils::symbol_get_past_external(type_dec)) != v.proc2newproc.end() && + v.proc2newproc.find(type_dec) == v.proc2newproc.end()){ + ASR::symbol_t* new_func = resolve_new_proc(ASRUtils::symbol_get_past_external(type_dec)); + ASR::ExternalSymbol_t* x_sym_ext = ASR::down_cast(type_dec); + std::string new_func_sym_name = x_sym_ext->m_parent_symtab->get_unique_name(ASRUtils::symbol_name( + ASRUtils::symbol_get_past_external(type_dec))); + ASR::symbol_t* new_func_sym_ = ASR::down_cast( + ASR::make_ExternalSymbol_t(v.al, type_dec->base.loc, x_sym_ext->m_parent_symtab, + s2c(v.al, new_func_sym_name), new_func, x_sym_ext->m_module_name, + x_sym_ext->m_scope_names, x_sym_ext->n_scope_names, ASRUtils::symbol_name(new_func), + x_sym_ext->m_access)); + v.proc2newproc[type_dec] = {new_func_sym_, {}}; + x_sym_ext->m_parent_symtab->add_symbol(new_func_sym_name, new_func_sym_); + } + if(type_dec && v.proc2newproc.find(type_dec) != v.proc2newproc.end() && + ASR::is_a(*ASRUtils::symbol_get_past_external(type_dec))){ + ASR::symbol_t* new_sym = resolve_new_proc(type_dec); + if ( new_sym == nullptr ) { + return; + } + ASR::expr_t* sym_val = x.m_symbolic_value; + ASR::expr_t* m_val = x.m_value; + ASR::Function_t * subrout = ASR::down_cast(ASRUtils::symbol_get_past_external(new_sym)); + if (x.m_symbolic_value && ASR::is_a(*x.m_symbolic_value)) { + ASR::PointerNullConstant_t* pnc = ASR::down_cast(x.m_symbolic_value); + pnc->m_type = subrout->m_function_signature; + sym_val = (ASR::expr_t*) pnc; + } + if (x.m_value && ASR::is_a(*x.m_value)) { + ASR::PointerNullConstant_t* pnc = ASR::down_cast(x.m_value); + pnc->m_type = subrout->m_function_signature; + m_val = (ASR::expr_t*) pnc; + } + std::string new_sym_name = x.m_parent_symtab->get_unique_name(x.m_name); + ASR::symbol_t* new_func_sym_ = ASR::down_cast( + ASRUtils::make_Variable_t_util(v.al, x.base.base.loc, x.m_parent_symtab, s2c(v.al, new_sym_name), + x.m_dependencies, x.n_dependencies, x.m_intent, + sym_val, m_val, x.m_storage, subrout->m_function_signature, + new_sym, x.m_abi, x.m_access, x.m_presence, x.m_value_attr)); + v.proc2newproc[(ASR::symbol_t *) &x] = {new_func_sym_, {}}; + x.m_parent_symtab->add_symbol(new_sym_name, new_func_sym_); + not_to_be_erased.insert(new_func_sym_); + } + ASR::ASRPassBaseWalkVisitor::visit_Variable(x); + } + + void visit_StructInstanceMember(const ASR::StructInstanceMember_t &x) { + //Case: prob % calfun => temp_calfun (where calfun is procedure variable) + ASR::ASRPassBaseWalkVisitor::visit_StructInstanceMember(x); + if (v.proc2newproc.find(ASRUtils::symbol_get_past_external(x.m_m)) != v.proc2newproc.end()) { + ASR::symbol_t* new_func_sym_ = x.m_m; + if (ASR::is_a(*x.m_m)) { + ASR::symbol_t* new_func = v.proc2newproc[ASRUtils::symbol_get_past_external(x.m_m)].first; + ASR::ExternalSymbol_t* x_sym_ext = ASR::down_cast(x.m_m); + std::string new_func_sym_name = x_sym_ext->m_parent_symtab->get_unique_name(ASRUtils::symbol_name(x.m_m)); + new_func_sym_ = ASR::down_cast( + ASR::make_ExternalSymbol_t(v.al, x.m_m->base.loc, x_sym_ext->m_parent_symtab, + s2c(v.al, new_func_sym_name), new_func, x_sym_ext->m_module_name, + x_sym_ext->m_scope_names, x_sym_ext->n_scope_names, ASRUtils::symbol_name(new_func), + x_sym_ext->m_access)); + v.proc2newproc[x.m_m] = {new_func_sym_, {}}; + x_sym_ext->m_parent_symtab->add_symbol(new_func_sym_name, new_func_sym_); + } else if (ASR::is_a(*x.m_m)) { + new_func_sym_ = v.proc2newproc[x.m_m].first; + } + ASR::StructInstanceMember_t& sim = const_cast(x); + sim.m_m = new_func_sym_; + sim.m_type = ASRUtils::symbol_type(new_func_sym_); + } + } + + void visit_Struct(const ASR::Struct_t &x) { + //just to update names of changed symbols of Struct + ASR::ASRPassBaseWalkVisitor::visit_Struct(x); + ASR::Struct_t& ss = const_cast(x); + for (size_t i = 0; i < x.n_members; i++) { + ASR::symbol_t* old_sym = x.m_symtab->get_symbol(x.m_members[i]); + if (v.proc2newproc.find(old_sym) != v.proc2newproc.end()) { + ss.m_members[i] = ASRUtils::symbol_name(v.proc2newproc[old_sym].first); + } + } + } + + void visit_Var(const ASR::Var_t &x) { + if (v.proc2newproc.find(x.m_v) != v.proc2newproc.end()){ + ASR::symbol_t* new_sym = v.proc2newproc[x.m_v].first; + ASR::Var_t& vv = const_cast(x); + vv.m_v = new_sym; + return; + } + if (ASR::is_a(*x.m_v) && + v.proc2newproc.find(ASRUtils::symbol_get_past_external(x.m_v)) != v.proc2newproc.end()) { + ASR::symbol_t* new_func_sym_ = x.m_v; + ASR::symbol_t* new_func = v.proc2newproc[ASRUtils::symbol_get_past_external(x.m_v)].first; + ASR::ExternalSymbol_t* x_sym_ext = ASR::down_cast(x.m_v); + std::string new_func_sym_name = x_sym_ext->m_parent_symtab->get_unique_name(ASRUtils::symbol_name(x.m_v)); + new_func_sym_ = ASR::down_cast( + ASR::make_ExternalSymbol_t(v.al, x.m_v->base.loc, x_sym_ext->m_parent_symtab, + s2c(v.al, new_func_sym_name), new_func, x_sym_ext->m_module_name, + x_sym_ext->m_scope_names, x_sym_ext->n_scope_names, ASRUtils::symbol_name(new_func), + x_sym_ext->m_access)); + v.proc2newproc[x.m_v] = {new_func_sym_, {}}; + x_sym_ext->m_parent_symtab->add_symbol(new_func_sym_name, new_func_sym_); + ASR::Var_t& vv = const_cast(x); + vv.m_v = new_func_sym_; + } } }; @@ -644,11 +996,33 @@ class RemoveArrayByDescriptorProceduresVisitor : public PassUtils::PassVisitor to_be_erased; for( auto& item: current_scope->get_scope() ) { - if( v.proc2newproc.find(item.second) != v.proc2newproc.end() && - not_to_be_erased.find(item.second) == not_to_be_erased.end() ) { + if (ASR::is_a(*item.second)) { + ASR::FunctionType_t* func_type = ASRUtils::get_FunctionType(item.second); + SymbolTable* current_scope_copy = current_scope; + visit_symbol(*item.second); + current_scope = current_scope_copy; + if (func_type->n_arg_types >= 1 && ASR::is_a(*func_type->m_arg_types[0])) { + continue; + } + } + ASR::symbol_t* sym = item.second; + if (ASR::is_a(*item.second)) { + sym = ASR::down_cast(item.second)->m_external; + } + if( v.proc2newproc.find(sym) != v.proc2newproc.end() && + not_to_be_erased.find(sym) == not_to_be_erased.end() ) { LCOMPILERS_ASSERT(item.first == ASRUtils::symbol_name(item.second)) to_be_erased.push_back(item.first); } + if ( ASR::is_a(*item.second) || + ASR::is_a(*item.second) || + ASR::is_a(*item.second) || + ASR::is_a(*item.second) || + ASR::is_a(*item.second)) { + SymbolTable* current_scope_copy = current_scope; + visit_symbol(*item.second); + current_scope = current_scope_copy; + } } for (auto &item: to_be_erased) { @@ -668,6 +1042,22 @@ class RemoveArrayByDescriptorProceduresVisitor : public PassUtils::PassVisitor #include -#include -#include namespace LCompilers { @@ -61,7 +59,7 @@ class CompareExprReplacer : public ASR::BaseExprReplacer #define create_args(x, type, symtab, vec_exprs) { \ ASR::symbol_t* arg = ASR::down_cast( \ - ASR::make_Variable_t(al, loc, symtab, \ + ASRUtils::make_Variable_t_util(al, loc, symtab, \ s2c(al, x), nullptr, 0, ASR::intentType::In, nullptr, nullptr, \ ASR::storage_typeType::Default, type, nullptr, \ ASR::abiType::Source, ASR::accessType::Public, \ @@ -102,7 +100,7 @@ class CompareExprReplacer : public ASR::BaseExprReplacer return ASRUtils::EXPR(ASR::make_RealCompare_t(al, loc, left, ASR::cmpopType::Eq, rig, bool_type, nullptr)); } - case ASR::ttypeType::Character: { + case ASR::ttypeType::String: { return ASRUtils::EXPR(ASR::make_StringCompare_t(al, loc, left, ASR::cmpopType::Eq, rig, bool_type, nullptr)); } @@ -128,7 +126,8 @@ class CompareExprReplacer : public ASR::BaseExprReplacer return ASRUtils::EXPR(ASRUtils::make_FunctionCall_t_util(al, loc, fn, nullptr, args.p, args.n, - bool_type, nullptr, nullptr)); + bool_type, nullptr, nullptr, + false)); } case ASR::ttypeType::List: { ASR::symbol_t *fn = get_list_compare_func(loc, global_scope, type); @@ -144,7 +143,8 @@ class CompareExprReplacer : public ASR::BaseExprReplacer return ASRUtils::EXPR(ASRUtils::make_FunctionCall_t_util(al, loc, fn, nullptr, args.p, args.n, - bool_type, nullptr, nullptr)); + bool_type, nullptr, nullptr, + false)); } default: { LCOMPILERS_ASSERT(false); @@ -182,7 +182,7 @@ class CompareExprReplacer : public ASR::BaseExprReplacer // Declare `result` ASR::symbol_t* arg = ASR::down_cast( - ASR::make_Variable_t(al, loc, tup_compare_symtab, + ASRUtils::make_Variable_t_util(al, loc, tup_compare_symtab, s2c(al, "result"), nullptr, 0, ASR::intentType::ReturnVar, nullptr, nullptr, ASR::storage_typeType::Default, bool_type, nullptr, ASR::abiType::Source, ASR::accessType::Public, @@ -262,7 +262,7 @@ class CompareExprReplacer : public ASR::BaseExprReplacer ASR::symbol_t *fn_sym = get_tuple_compare_func(unit.base.base.loc, unit.m_symtab, ASRUtils::expr_type(x->m_left)); *current_expr = ASRUtils::EXPR(ASRUtils::make_FunctionCall_t_util(al, loc, - fn_sym, nullptr, args.p, args.n, bool_type, nullptr, nullptr)); + fn_sym, nullptr, args.p, args.n, bool_type, nullptr, nullptr, false)); if (x->m_op == ASR::cmpopType::NotEq) { *current_expr = ASRUtils::EXPR(ASR::make_LogicalNot_t(al, loc, *current_expr, bool_type, nullptr)); @@ -354,7 +354,7 @@ class CompareExprReplacer : public ASR::BaseExprReplacer // Declare `result` ASR::symbol_t* res_arg = ASR::down_cast( - ASR::make_Variable_t(al, loc, list_compare_symtab, + ASRUtils::make_Variable_t_util(al, loc, list_compare_symtab, s2c(al, "result"), nullptr, 0, ASR::intentType::ReturnVar, nullptr, nullptr, ASR::storage_typeType::Default, bool_type, nullptr, ASR::abiType::Source, ASR::accessType::Public, @@ -447,7 +447,8 @@ class CompareExprReplacer : public ASR::BaseExprReplacer ASR::symbol_t *fn_sym = get_list_compare_func(unit.base.base.loc, unit.m_symtab, ASRUtils::expr_type(x->m_left)); *current_expr = ASRUtils::EXPR(ASRUtils::make_FunctionCall_t_util(al, loc, - fn_sym, nullptr, args.p, args.n, bool_type, nullptr, nullptr)); + fn_sym, nullptr, args.p, args.n, bool_type, nullptr, nullptr, + false)); if (x->m_op == ASR::cmpopType::NotEq) { *current_expr = ASRUtils::EXPR(ASR::make_LogicalNot_t(al, loc, *current_expr, bool_type, nullptr)); diff --git a/src/libasr/pass/pass_list_expr.cpp b/src/libasr/pass/pass_list_expr.cpp index 6fff1d1df7..39ffca8731 100644 --- a/src/libasr/pass/pass_list_expr.cpp +++ b/src/libasr/pass/pass_list_expr.cpp @@ -6,9 +6,6 @@ #include #include -#include -#include - namespace LCompilers { @@ -98,7 +95,7 @@ class ListExprReplacer : public ASR::BaseExprReplacer #define create_args(x, type, symtab) { \ ASR::symbol_t* arg = ASR::down_cast( \ - ASR::make_Variable_t(al, loc, symtab, \ + ASRUtils::make_Variable_t_util(al, loc, symtab, \ s2c(al, x), nullptr, 0, ASR::intentType::In, nullptr, nullptr, \ ASR::storage_typeType::Default, type, nullptr, \ ASR::abiType::Source, ASR::accessType::Public, \ @@ -172,7 +169,7 @@ class ListExprReplacer : public ASR::BaseExprReplacer // Declare `result_list` ASR::symbol_t* arg = ASR::down_cast( - ASR::make_Variable_t(al, loc, list_section_symtab, + ASRUtils::make_Variable_t_util(al, loc, list_section_symtab, s2c(al, "result_list"), nullptr, 0, ASR::intentType::Local, nullptr, nullptr, ASR::storage_typeType::Default, list_type, nullptr, ASR::abiType::Source, ASR::accessType::Public, @@ -409,7 +406,7 @@ class ListExprReplacer : public ASR::BaseExprReplacer } ASR::symbol_t *fn_sym = list_section_func_map[list_type_name]; *current_expr = ASRUtils::EXPR(ASRUtils::make_FunctionCall_t_util(al, loc, - fn_sym, nullptr, args.p, args.n, x->m_type, nullptr, nullptr)); + fn_sym, nullptr, args.p, args.n, x->m_type, nullptr, nullptr, false)); } void create_concat_function(Location& loc, @@ -445,7 +442,7 @@ class ListExprReplacer : public ASR::BaseExprReplacer // Declare `result_list` ASR::symbol_t* arg = ASR::down_cast( - ASR::make_Variable_t(al, loc, list_concat_symtab, + ASRUtils::make_Variable_t_util(al, loc, list_concat_symtab, s2c(al, "result_list"), nullptr, 0, ASR::intentType::Local, nullptr, nullptr, ASR::storage_typeType::Default, list_type, nullptr, ASR::abiType::Source, ASR::accessType::Public, @@ -533,7 +530,7 @@ class ListExprReplacer : public ASR::BaseExprReplacer } ASR::symbol_t *fn_sym = list_concat_func_map[list_type_name]; *current_expr = ASRUtils::EXPR(ASRUtils::make_FunctionCall_t_util(al, loc, - fn_sym, nullptr, args.p, 2, x->m_type, nullptr, nullptr)); + fn_sym, nullptr, args.p, 2, x->m_type, nullptr, nullptr, false)); } }; diff --git a/src/libasr/pass/pass_manager.h b/src/libasr/pass/pass_manager.h index 6c3a11cd84..3508715614 100644 --- a/src/libasr/pass/pass_manager.h +++ b/src/libasr/pass/pass_manager.h @@ -1,6 +1,8 @@ #ifndef LCOMPILERS_PASS_MANAGER_H #define LCOMPILERS_PASS_MANAGER_H +#include + #include #include #include @@ -51,10 +53,13 @@ #include #include #include +#include #include #include #include -#include +#include +#include +#include #include #include #include @@ -73,14 +78,14 @@ namespace LCompilers { private: std::vector _passes; - std::vector _with_optimization_passes; + std::vector _optimization_passes; std::vector _user_defined_passes; std::vector _skip_passes, _c_skip_passes; std::map _passes_db = { + {"replace_with_compile_time_values", &pass_replace_with_compile_time_values}, {"do_loops", &pass_replace_do_loops}, {"while_else", &pass_while_else}, {"global_stmts", &pass_wrap_global_stmts}, - {"python_bind", &pass_python_bind}, {"implied_do_loops", &pass_replace_implied_do_loops}, {"array_op", &pass_replace_array_op}, {"symbolic", &pass_replace_symbolic}, @@ -110,10 +115,13 @@ namespace LCompilers { {"nested_vars", &pass_nested_vars}, {"where", &pass_replace_where}, {"function_call_in_declaration", &pass_replace_function_call_in_declaration}, + {"array_passed_in_function_call", &pass_replace_array_passed_in_function_call}, + {"openmp", &pass_replace_openmp}, {"print_struct_type", &pass_replace_print_struct_type}, {"unique_symbols", &pass_unique_symbols}, {"insert_deallocate", &pass_insert_deallocate}, - {"promote_allocatable_to_nonallocatable", &pass_promote_allocatable_to_nonallocatable} + {"promote_allocatable_to_nonallocatable", &pass_promote_allocatable_to_nonallocatable}, + {"array_struct_temporary", &pass_array_struct_temporary} }; bool apply_default_passes; @@ -121,11 +129,21 @@ namespace LCompilers { public: bool rtlib=false; - void apply_passes(Allocator& al, ASR::TranslationUnit_t* asr, std::vector& passes, PassOptions &pass_options, [[maybe_unused]] diag::Diagnostics &diagnostics) { if (pass_options.pass_cumulative) { + std::vector _with_optimization_passes; + _with_optimization_passes.insert( + _with_optimization_passes.end(), + _passes.begin(), + _passes.end() + ); + _with_optimization_passes.insert( + _with_optimization_passes.end(), + _optimization_passes.begin(), + _optimization_passes.end() + ); int _pass_max_idx = -1, _opt_max_idx = -1; for (std::string ¤t_pass: passes) { auto it1 = std::find(_passes.begin(), _passes.end(), current_pass); @@ -208,82 +226,54 @@ namespace LCompilers { PassManager(): apply_default_passes{false}, c_skip_pass{false} { _passes = { - "python_bind", - "nested_vars", "global_stmts", - "transform_optional_argument_functions", "init_expr", + "function_call_in_declaration", + "openmp", "implied_do_loops", + "array_struct_temporary", + "nested_vars", + "transform_optional_argument_functions", + "forall", "class_constructor", "pass_list_expr", "where", - "function_call_in_declaration", "subroutine_from_function", "array_op", "symbolic", "intrinsic_function", "intrinsic_subroutine", - "subroutine_from_function", "array_op", "pass_array_by_data", + "array_passed_in_function_call", "print_struct_type", "print_arr", "print_list_tuple", "print_struct_type", "array_dim_intrinsics_update", "do_loops", - "forall", "while_else", "select_case", - "inline_function_calls", "unused_functions", "unique_symbols", "insert_deallocate", }; - - _with_optimization_passes = { - "nested_vars", - "global_stmts", - "transform_optional_argument_functions", - "init_expr", - "implied_do_loops", - "class_constructor", - "pass_list_expr", - "where", - "function_call_in_declaration", - "subroutine_from_function", - "array_op", - "symbolic", - "flip_sign", - "intrinsic_function", - "intrinsic_subroutine", - "subroutine_from_function", - "array_op", - "pass_array_by_data", - "print_struct_type", - "print_arr", - "print_list_tuple", - "print_struct_type", + _optimization_passes = { + "replace_with_compile_time_values", "loop_vectorise", - "array_dim_intrinsics_update", - "do_loops", - "forall", - "while_else", "dead_code_removal", - "select_case", "unused_functions", "sign_from_value", "div_to_mul", "fma", - "inline_function_calls", - "unique_symbols", - "insert_deallocate", - "promote_allocatable_to_nonallocatable" + // "inline_function_calls", + // "promote_allocatable_to_nonallocatable" }; // These are re-write passes which are already handled // appropriately in C backend. _c_skip_passes = { + "replace_with_compile_time_values", "pass_list_expr", "print_list_tuple", "do_loops", @@ -307,11 +297,9 @@ namespace LCompilers { apply_passes(al, asr, _user_defined_passes, pass_options, diagnostics); } else if( apply_default_passes ) { - if( pass_options.fast ) { - apply_passes(al, asr, _with_optimization_passes, pass_options, - diagnostics); - } else { - apply_passes(al, asr, _passes, pass_options, diagnostics); + apply_passes(al, asr, _passes, pass_options, diagnostics); + if (pass_options.fast ){ + apply_passes(al, asr, _optimization_passes, pass_options, diagnostics); } } } @@ -321,7 +309,12 @@ namespace LCompilers { [[maybe_unused]] diag::Diagnostics &diagnostics, LocationManager &lm) { std::vector passes; if (pass_options.fast) { - passes = _with_optimization_passes; + passes = _passes; + passes.insert( + passes.end(), + _optimization_passes.begin(), + _optimization_passes.end() + ); } else { passes = _passes; } diff --git a/src/libasr/pass/pass_utils.cpp b/src/libasr/pass/pass_utils.cpp index e15eb84477..35a6aef97a 100644 --- a/src/libasr/pass/pass_utils.cpp +++ b/src/libasr/pass/pass_utils.cpp @@ -81,6 +81,10 @@ namespace LCompilers { } else if (ASR::is_a(*x)) { ASR::ComplexRe_t* cc = ASR::down_cast(x); return get_rank(cc->m_arg); + } else if ( ASR::is_a(*x) ) { + ASR::IntrinsicArrayFunction_t* iaf = ASR::down_cast(x); + ASR::dimension_t* m_dims; + get_dim_rank(iaf->m_type, m_dims, n_dims); } return n_dims; } @@ -149,17 +153,57 @@ namespace LCompilers { ai.m_step = nullptr; args.push_back(al, ai); } - + ASR::expr_t* array_ref = nullptr; + ASR::expr_t* arr_expr_copy = arr_expr; + ASR::expr_t** original_arr_expr =&arr_expr_copy; + ASR::expr_t** array_ref_container_node = nullptr; // If we have a structInstanceMember hierarch, It'd be used to emplace the resulting array_ref in the correct node. + ASR::StructInstanceMember_t* tmp = nullptr; + + // if first depth of hierarchy contains array, don't set array_ref_container_node and return array_ref directly. + if (ASR::is_a(*arr_expr) && + ASR::is_a(*ASRUtils::type_get_past_allocatable( + ASRUtils::symbol_type(ASR::down_cast(arr_expr)->m_m)))){ + original_arr_expr = &array_ref; + } + // This while loop is used to fetch the only single array from a structInstanceMember hierarchy. + // We assume there's a single array in the hierarachy, as multiple arrays should throw semantic error while building ASR. + bool check_m_m = true; + while(ASR::is_a(*arr_expr) && !array_ref_container_node ){ + tmp = ASR::down_cast(arr_expr); + if(ASR::is_a(*ASRUtils::type_get_past_allocatable(ASRUtils::expr_type(tmp->m_v)))){ + arr_expr = tmp->m_v; + array_ref_container_node = &(tmp->m_v); + } else if (ASR::is_a(*ASRUtils::type_get_past_allocatable(ASRUtils::symbol_type(tmp->m_m))) && check_m_m){ + array_ref_container_node = &arr_expr; + } else if(ASR::is_a(*tmp->m_v)){ + arr_expr = tmp->m_v; + check_m_m =true; + } else if (ASR::is_a(*tmp->m_v)){ + arr_expr = ASR::down_cast(tmp->m_v)->m_v; + check_m_m = false; + } else { + break; + } + } ASR::ttype_t* array_ref_type = ASRUtils::duplicate_type_without_dims( al, ASRUtils::expr_type(arr_expr), arr_expr->base.loc); fix_struct_type_scope() - ASR::expr_t* array_ref = ASRUtils::EXPR(ASRUtils::make_ArrayItem_t_util(al, + array_ref = ASRUtils::EXPR(ASRUtils::make_ArrayItem_t_util(al, arr_expr->base.loc, arr_expr, args.p, args.size(), ASRUtils::type_get_past_array( ASRUtils::type_get_past_pointer( ASRUtils::type_get_past_allocatable(array_ref_type))), ASR::arraystorageType::RowMajor, nullptr)); + // Emplace the resulting array_ref in the correct node. + if(array_ref_container_node){ + *array_ref_container_node = array_ref; + array_ref = *original_arr_expr; + if(ASR::is_a(*array_ref)){ + ASR::StructInstanceMember_t* tmp = ASR::down_cast(array_ref); + tmp->m_type = ASR::down_cast(ASRUtils::type_get_past_allocatable(tmp->m_type))->m_type; // Using type of the returing array to avoid creating array ref again by array_op pass. + } + } if( perform_cast ) { LCOMPILERS_ASSERT(casted_type != nullptr); array_ref = ASRUtils::EXPR(ASR::make_Cast_t(al, array_ref->base.loc, @@ -239,7 +283,7 @@ namespace LCompilers { PassUtils::get_dim_rank(sibling_type, m_dims, ndims); if( !ASRUtils::is_fixed_size_array(m_dims, ndims) && !ASRUtils::is_dimension_dependent_only_on_arguments(m_dims, ndims) ) { - return ASRUtils::TYPE(ASR::make_Allocatable_t(al, sibling_type->base.loc, + return ASRUtils::TYPE(ASRUtils::make_Allocatable_t_util(al, sibling_type->base.loc, ASRUtils::type_get_past_allocatable( ASRUtils::duplicate_type_with_empty_dims(al, sibling_type)))); } @@ -260,54 +304,69 @@ namespace LCompilers { new_m_dims.push_back(al, new_m_dim); } return PassUtils::set_dim_rank(sibling_type, new_m_dims.p, ndims, true, &al); - } - - ASR::expr_t* create_var(int counter, std::string suffix, const Location& loc, - ASR::ttype_t* var_type, Allocator& al, SymbolTable*& current_scope) { - ASR::dimension_t* m_dims = nullptr; - int ndims = 0; - PassUtils::get_dim_rank(var_type, m_dims, ndims); - if( !ASRUtils::is_fixed_size_array(m_dims, ndims) && - !ASRUtils::is_dimension_dependent_only_on_arguments(m_dims, ndims) && - !(ASR::is_a(*var_type) || ASR::is_a(*var_type)) ) { - var_type = ASRUtils::TYPE(ASR::make_Allocatable_t(al, var_type->base.loc, - ASRUtils::type_get_past_allocatable( - ASRUtils::duplicate_type_with_empty_dims(al, var_type)))); } - ASR::expr_t* idx_var = nullptr; - std::string str_name = "__libasr__created__var__" + std::to_string(counter) + "_" + suffix; - char* idx_var_name = s2c(al, str_name); - if( current_scope->get_symbol(std::string(idx_var_name)) == nullptr ) { - ASR::asr_t* idx_sym = ASR::make_Variable_t(al, loc, current_scope, idx_var_name, nullptr, 0, - ASR::intentType::Local, nullptr, nullptr, ASR::storage_typeType::Default, - var_type, nullptr, ASR::abiType::Source, ASR::accessType::Public, - ASR::presenceType::Required, false); - current_scope->add_symbol(std::string(idx_var_name), ASR::down_cast(idx_sym)); - idx_var = ASRUtils::EXPR(ASR::make_Var_t(al, loc, ASR::down_cast(idx_sym))); - } else { - ASR::symbol_t* idx_sym = current_scope->get_symbol(std::string(idx_var_name)); - idx_var = ASRUtils::EXPR(ASR::make_Var_t(al, loc, idx_sym)); + bool is_args_contains_allocatable(ASR::expr_t* x) { + if( ASR::is_a(*x) ) { + ASR::ArrayConstructor_t* arr_constructor = ASR::down_cast(x); + for(size_t i = 0; i < arr_constructor->n_args; i++) { + if( ASRUtils::is_allocatable(ASRUtils::expr_type(arr_constructor->m_args[i])) ) { + return true; + } + } + } + return false; } + ASR::expr_t* create_var(int counter, std::string suffix, const Location& loc, + ASR::ttype_t* var_type, Allocator& al, SymbolTable*& current_scope) { + ASR::dimension_t* m_dims = nullptr; + int ndims = 0; + PassUtils::get_dim_rank(var_type, m_dims, ndims); + if( !ASRUtils::is_fixed_size_array(m_dims, ndims) && + !ASRUtils::is_dimension_dependent_only_on_arguments(m_dims, ndims) && + !(ASR::is_a(*var_type) || ASR::is_a(*var_type)) ) { + var_type = ASRUtils::TYPE(ASRUtils::make_Allocatable_t_util(al, var_type->base.loc, + ASRUtils::type_get_past_allocatable( + ASRUtils::duplicate_type_with_empty_dims(al, var_type)))); + } + ASR::expr_t* idx_var = nullptr; + std::string str_name = "__libasr__created__var__" + std::to_string(counter) + "_" + suffix; + + if( current_scope->get_symbol(str_name) == nullptr || + !ASRUtils::check_equal_type( + ASRUtils::symbol_type(current_scope->get_symbol(str_name)), + var_type, true + ) ) { + str_name = current_scope->get_unique_name(str_name); + ASR::asr_t* idx_sym = ASRUtils::make_Variable_t_util(al, loc, current_scope, s2c(al, str_name), nullptr, 0, + ASR::intentType::Local, nullptr, nullptr, ASR::storage_typeType::Default, + var_type, nullptr, ASR::abiType::Source, ASR::accessType::Public, + ASR::presenceType::Required, false); + current_scope->add_symbol(str_name, ASR::down_cast(idx_sym)); + idx_var = ASRUtils::EXPR(ASR::make_Var_t(al, loc, ASR::down_cast(idx_sym))); + } else { + ASR::symbol_t* idx_sym = current_scope->get_symbol(str_name); + idx_var = ASRUtils::EXPR(ASR::make_Var_t(al, loc, idx_sym)); + } - return idx_var; - } + return idx_var; + } - ASR::expr_t* create_var(int counter, std::string suffix, const Location& loc, - ASR::expr_t* sibling, Allocator& al, SymbolTable*& current_scope) { - ASR::ttype_t* var_type = nullptr; - var_type = get_matching_type(sibling, al); - return create_var(counter, suffix, loc, var_type, al, current_scope); - } + ASR::expr_t* create_var(int counter, std::string suffix, const Location& loc, + ASR::expr_t* sibling, Allocator& al, SymbolTable*& current_scope) { + ASR::ttype_t* var_type = nullptr; + var_type = get_matching_type(sibling, al); + return create_var(counter, suffix, loc, var_type, al, current_scope); + } - void fix_dimension(ASR::Cast_t* x, ASR::expr_t* arg_expr) { - ASR::ttype_t* x_type = const_cast(x->m_type); - ASR::ttype_t* arg_type = ASRUtils::expr_type(arg_expr); - ASR::dimension_t* m_dims; - int ndims; - PassUtils::get_dim_rank(arg_type, m_dims, ndims); - PassUtils::set_dim_rank(x_type, m_dims, ndims); - } + void fix_dimension(ASR::Cast_t* x, ASR::expr_t* arg_expr) { + ASR::ttype_t* x_type = const_cast(x->m_type); + ASR::ttype_t* arg_type = ASRUtils::expr_type(arg_expr); + ASR::dimension_t* m_dims; + int ndims; + PassUtils::get_dim_rank(arg_type, m_dims, ndims); + PassUtils::set_dim_rank(x_type, m_dims, ndims); + } void create_vars(Vec& vars, int n_vars, const Location& loc, Allocator& al, SymbolTable*& current_scope, std::string suffix, @@ -315,6 +374,7 @@ namespace LCompilers { vars.reserve(al, n_vars); for (int i = 1; i <= n_vars; i++) { std::string idx_var_name = "__" + std::to_string(i) + suffix; + idx_var_name = current_scope->get_unique_name(idx_var_name, false); ASR::ttype_t* int32_type = ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)); if( current_scope->get_symbol(idx_var_name) != nullptr ) { ASR::symbol_t* idx_sym = current_scope->get_symbol(idx_var_name); @@ -331,7 +391,7 @@ namespace LCompilers { char* var_name = s2c(al, idx_var_name);; ASR::expr_t* var = nullptr; if( current_scope->get_symbol(idx_var_name) == nullptr ) { - ASR::asr_t* idx_sym = ASR::make_Variable_t(al, loc, current_scope, var_name, nullptr, 0, + ASR::asr_t* idx_sym = ASRUtils::make_Variable_t_util(al, loc, current_scope, var_name, nullptr, 0, intent, nullptr, nullptr, ASR::storage_typeType::Default, int32_type, nullptr, ASR::abiType::Source, ASR::accessType::Public, presence, false); @@ -376,7 +436,7 @@ namespace LCompilers { char* var_name = s2c(al, idx_var_name);; ASR::expr_t* var = nullptr; if( current_scope->get_symbol(idx_var_name) == nullptr ) { - ASR::asr_t* idx_sym = ASR::make_Variable_t(al, loc, current_scope, var_name, nullptr, 0, + ASR::asr_t* idx_sym = ASRUtils::make_Variable_t_util(al, loc, current_scope, var_name, nullptr, 0, ASR::intentType::Local, nullptr, nullptr, ASR::storage_typeType::Default, int32_type, nullptr, ASR::abiType::Source, ASR::accessType::Public, ASR::presenceType::Required, false); @@ -420,7 +480,7 @@ namespace LCompilers { char* var_name = s2c(al, idx_var_name);; ASR::expr_t* var = nullptr; if( current_scope->get_symbol(idx_var_name) == nullptr ) { - ASR::asr_t* idx_sym = ASR::make_Variable_t(al, loc, current_scope, var_name, nullptr, 0, + ASR::asr_t* idx_sym = ASRUtils::make_Variable_t_util(al, loc, current_scope, var_name, nullptr, 0, ASR::intentType::Local, nullptr, nullptr, ASR::storage_typeType::Default, int32_type, nullptr, ASR::abiType::Source, ASR::accessType::Public, ASR::presenceType::Required, false); @@ -447,10 +507,12 @@ namespace LCompilers { // We tell `load_module` not to run verify, since the ASR might // not be in valid state. We run verify at the end of this pass // anyway, so verify will be run no matter what. + LCompilers::LocationManager loc_manager; ASR::Module_t *m = ASRUtils::load_module(al, current_scope, module_name, loc, true, pass_options, false, - [&](const std::string &msg, const Location &) { throw LCompilersException(msg); } + [&](const std::string &msg, const Location &) { throw LCompilersException(msg); }, + loc_manager ); ASR::symbol_t *t = m->m_symtab->resolve_symbol(remote_sym); @@ -485,10 +547,12 @@ namespace LCompilers { // We tell `load_module` not to run verify, since the ASR might // not be in valid state. We run verify at the end of this pass // anyway, so verify will be run no matter what. + LCompilers::LocationManager loc_manager; ASR::Module_t *m = ASRUtils::load_module(al, current_scope, module_name, loc, true, pass_options, false, - [&](const std::string &msg, const Location &) { throw LCompilersException(msg); }); + [&](const std::string &msg, const Location &) { throw LCompilersException(msg); }, + loc_manager); ASR::symbol_t *t = m->m_symtab->resolve_symbol(remote_sym); ASR::Function_t *mfn = ASR::down_cast(t); @@ -516,7 +580,7 @@ namespace LCompilers { } return b.DoLoop(do_loop_variables[curr_idx - 1], LBound(mask, curr_idx), UBound(mask, curr_idx), { b.If(b.ArrayItem_01(mask, vars), { - b.Assignment(res, b.Add(res, b.i(1, ASRUtils::expr_type(res)))) + b.Assignment(res, b.Add(res, b.i_t(1, ASRUtils::expr_type(res)))) }, {}), }, nullptr); } @@ -546,6 +610,83 @@ namespace LCompilers { } } + ASR::stmt_t* create_do_loop_helper_parity(Allocator &al, const Location &loc, std::vector do_loop_variables, ASR::expr_t* mask, ASR::expr_t* res, int curr_idx) { + ASRUtils::ASRBuilder b(al, loc); + + if (curr_idx == 1) { + std::vector vars; + for (size_t i = 0; i < do_loop_variables.size(); i++) { + vars.push_back(do_loop_variables[i]); + } + return b.DoLoop(do_loop_variables[curr_idx - 1], LBound(mask, curr_idx), UBound(mask, curr_idx), { + b.Assignment(res, b.Xor(res, b.ArrayItem_01(mask, vars))) + }, nullptr); + } + return b.DoLoop(do_loop_variables[curr_idx - 1], LBound(mask, curr_idx), UBound(mask, curr_idx), { + create_do_loop_helper_parity(al, loc, do_loop_variables, mask, res, curr_idx - 1) + }, nullptr); + } + + ASR::stmt_t* create_do_loop_helper_parity_dim(Allocator &al, const Location &loc, std::vector do_loop_variables, + std::vector res_idx, ASR::stmt_t* inner_most_do_loop, + ASR::expr_t* c, ASR::expr_t* mask, ASR::expr_t* res, int curr_idx, int dim) { + ASRUtils::ASRBuilder b(al, loc); + + if (curr_idx == (int) do_loop_variables.size() - 1) { + return b.DoLoop(do_loop_variables[curr_idx], LBound(mask, curr_idx + 1), UBound(mask, curr_idx + 1), { + b.Assignment(c, ASRUtils::EXPR(ASR::make_LogicalConstant_t(al, loc, 0, ASRUtils::TYPE(ASR::make_Logical_t(al, loc, 4))))), + inner_most_do_loop, + b.Assignment(b.ArrayItem_01(res, {res_idx}), c) + }); + } + if (curr_idx != dim - 1) { + return b.DoLoop(do_loop_variables[curr_idx], LBound(mask, curr_idx + 1), UBound(mask, curr_idx + 1), { + create_do_loop_helper_parity_dim(al, loc, do_loop_variables, res_idx, inner_most_do_loop, c, mask, res, curr_idx + 1, dim) + }); + } else { + return create_do_loop_helper_parity_dim(al, loc, do_loop_variables, res_idx, inner_most_do_loop, c, mask, res, curr_idx + 1, dim); + } + } + + ASR::stmt_t* create_do_loop_helper_norm2(Allocator &al, const Location &loc, std::vector do_loop_variables, ASR::expr_t* array, ASR::expr_t* res, int curr_idx) { + ASRUtils::ASRBuilder b(al, loc); + + if (curr_idx == 1) { + std::vector vars; + for (size_t i = 0; i < do_loop_variables.size(); i++) { + vars.push_back(do_loop_variables[i]); + } + return b.DoLoop(do_loop_variables[curr_idx - 1], LBound(array, curr_idx), UBound(array, curr_idx), { + b.Assignment(res, b.Add(res, b.Mul(b.ArrayItem_01(array, vars), b.ArrayItem_01(array, vars)))), + }, nullptr); + } + return b.DoLoop(do_loop_variables[curr_idx - 1], LBound(array, curr_idx), UBound(array, curr_idx), { + create_do_loop_helper_norm2(al, loc, do_loop_variables, array, res, curr_idx - 1) + }, nullptr); + } + + ASR::stmt_t* create_do_loop_helper_norm2_dim(Allocator &al, const Location &loc, std::vector do_loop_variables, + std::vector res_idx, ASR::stmt_t* inner_most_do_loop, + ASR::expr_t* c, ASR::expr_t* array, ASR::expr_t* res, int curr_idx, int dim) { + ASRUtils::ASRBuilder b(al, loc); + + if (curr_idx == (int) do_loop_variables.size() - 1) { + return b.DoLoop(do_loop_variables[curr_idx], LBound(array, curr_idx + 1), UBound(array, curr_idx + 1), { + b.Assignment(c, ASRUtils::EXPR(ASR::make_RealConstant_t(al, loc, 0.0, ASRUtils::TYPE(ASR::make_Real_t(al, loc, 4))))), + inner_most_do_loop, + b.Assignment(b.ArrayItem_01(res, {res_idx}), c) + }); + } + if (curr_idx != dim - 1) { + return b.DoLoop(do_loop_variables[curr_idx], LBound(array, curr_idx + 1), UBound(array, curr_idx + 1), { + create_do_loop_helper_norm2_dim(al, loc, do_loop_variables, res_idx, inner_most_do_loop, c, array, res, curr_idx + 1, dim) + }); + } else { + return create_do_loop_helper_norm2_dim(al, loc, do_loop_variables, res_idx, inner_most_do_loop, c, array, res, curr_idx + 1, dim); + } + } + + ASR::stmt_t* create_do_loop_helper_pack(Allocator &al, const Location &loc, std::vector do_loop_variables, ASR::expr_t* array, ASR::expr_t* mask, ASR::expr_t* res, ASR::expr_t* idx, int curr_idx) { ASRUtils::ASRBuilder b(al, loc); @@ -778,7 +919,7 @@ namespace LCompilers { ASR::expr_t* create_auxiliary_variable_for_expr(ASR::expr_t* expr, std::string& name, Allocator& al, SymbolTable*& current_scope, ASR::stmt_t*& assign_stmt) { - ASR::asr_t* expr_sym = ASR::make_Variable_t(al, expr->base.loc, current_scope, s2c(al, name), nullptr, 0, + ASR::asr_t* expr_sym = ASRUtils::make_Variable_t_util(al, expr->base.loc, current_scope, s2c(al, name), nullptr, 0, ASR::intentType::Local, nullptr, nullptr, ASR::storage_typeType::Default, ASRUtils::duplicate_type(al, ASRUtils::extract_type(ASRUtils::expr_type(expr))), nullptr, ASR::abiType::Source, ASR::accessType::Public, ASR::presenceType::Required, false); @@ -794,11 +935,11 @@ namespace LCompilers { ASR::expr_t* create_auxiliary_variable(const Location& loc, std::string& name, Allocator& al, SymbolTable*& current_scope, ASR::ttype_t* var_type, - ASR::intentType var_intent) { + ASR::intentType var_intent, ASR::symbol_t* var_decl) { ASRUtils::import_struct_t(al, loc, var_type, var_intent, current_scope); - ASR::asr_t* expr_sym = ASR::make_Variable_t(al, loc, current_scope, s2c(al, name), nullptr, 0, + ASR::asr_t* expr_sym = ASRUtils::make_Variable_t_util(al, loc, current_scope, s2c(al, name), nullptr, 0, var_intent, nullptr, nullptr, ASR::storage_typeType::Default, - var_type, nullptr, ASR::abiType::Source, ASR::accessType::Public, + var_type, var_decl, ASR::abiType::Source, ASR::accessType::Public, ASR::presenceType::Required, false); if( current_scope->get_symbol(name) == nullptr ) { current_scope->add_symbol(name, ASR::down_cast(expr_sym)); @@ -862,7 +1003,7 @@ namespace LCompilers { SymbolTable* vector_copy_symtab = al.make_new(global_scope); for( int i = 0; i < num_args; i++ ) { std::string arg_name = "arg" + std::to_string(i); - ASR::symbol_t* arg = ASR::down_cast(ASR::make_Variable_t(al, unit.base.base.loc, vector_copy_symtab, + ASR::symbol_t* arg = ASR::down_cast(ASRUtils::make_Variable_t_util(al, unit.base.base.loc, vector_copy_symtab, s2c(al, arg_name), nullptr, 0, ASR::intentType::In, nullptr, nullptr, ASR::storage_typeType::Default, types[std::min(i, (int) types.size() - 1)], nullptr, ASR::abiType::Source, ASR::accessType::Public, ASR::presenceType::Required, false)); @@ -956,7 +1097,7 @@ namespace LCompilers { } ASRUtils::impl_function instantiate_function = ASRUtils::IntrinsicElementalFunctionRegistry::get_instantiate_function( - static_cast(ASRUtils::IntrinsicElementalFunctions::FMA)); + static_cast(ASRUtils::IntrinsicElementalFunctions::SignFromValue)); Vec arg_types; arg_types.reserve(al, 2); arg_types.push_back(al, ASRUtils::expr_type(arg0)); @@ -991,6 +1132,101 @@ namespace LCompilers { } } + Vec insert_if_stmts_in_loop_body(Allocator& al, + ASR::If_t* if_stmt, + ASR::stmt_t* decrement_stmt) + { + Vec body; body.reserve(al, 0); + Vec if_stmt_body; if_stmt_body.reserve(al, 0); + Vec else_stmt_body; else_stmt_body.reserve(al, 0); + + for (size_t i = 0; i < if_stmt->n_body; i++) { + if (ASR::is_a(*if_stmt->m_body[i])) { + Vec nested_if_stmt_body = insert_if_stmts_in_loop_body(al, + ASR::down_cast(if_stmt->m_body[i]), + decrement_stmt); + for (size_t j = 0; j < nested_if_stmt_body.size(); j++) { + if_stmt_body.push_back(al, nested_if_stmt_body[j]); + } + } else if (ASR::is_a(*if_stmt->m_body[i])) { + if_stmt_body.push_back(al, decrement_stmt); + if_stmt_body.push_back(al, if_stmt->m_body[i]); + break; // dead code ahead, skip it + } else { + if_stmt_body.push_back(al, if_stmt->m_body[i]); + } + } + + if_stmt->m_body = if_stmt_body.p; + if_stmt->n_body = if_stmt_body.n; + + for (size_t i = 0; i < if_stmt->n_orelse; i++) { + if (ASR::is_a(*if_stmt->m_orelse[i])) { + Vec nested_if_stmt_body = insert_if_stmts_in_loop_body(al, + ASR::down_cast(if_stmt->m_orelse[i]), + decrement_stmt); + for (size_t j = 0; j < nested_if_stmt_body.size(); j++) { + else_stmt_body.push_back(al, nested_if_stmt_body[j]); + } + } else if (ASR::is_a(*if_stmt->m_orelse[i])) { + else_stmt_body.push_back(al, decrement_stmt); + else_stmt_body.push_back(al, if_stmt->m_orelse[i]); + break; // dead code ahead, skip it + } else { + else_stmt_body.push_back(al, if_stmt->m_orelse[i]); + } + } + + if_stmt->m_orelse = else_stmt_body.p; + if_stmt->n_orelse = else_stmt_body.n; + + body.push_back(al, ASRUtils::STMT(&if_stmt->base.base)); + return body; + } + + void insert_stmts_in_loop_body(Allocator& al, + const ASR::DoLoop_t& loop, + Vec& body, + ASR::expr_t* increment) + { + Vec new_body; + new_body.from_pointer_n_copy(al, body.p, body.n); + Location loc = loop.base.base.loc; + + ASR::expr_t* target = loop.m_head.m_v; + int a_kind = ASRUtils::extract_kind_from_ttype_t(ASRUtils::expr_type(target)); + ASR::ttype_t* type = ASRUtils::TYPE(ASR::make_Integer_t(al, loc, a_kind)); + + ASR::stmt_t* decrement_stmt = ASRUtils::STMT( + ASR::make_Assignment_t( + al, + loc, + target, + ASRUtils::EXPR( + ASR::make_IntegerBinOp_t( + al, loc, target, ASR::binopType::Sub, + increment, type, nullptr)), + nullptr)); + + for (size_t i = 0; i < loop.n_body; i++) { + if (ASR::is_a(*loop.m_body[i])) { + new_body.push_back(al, decrement_stmt); + new_body.push_back(al, loop.m_body[i]); + break; // dead code ahead, skip it + } else if (ASR::is_a(*loop.m_body[i])) { + Vec if_body = insert_if_stmts_in_loop_body( + al, ASR::down_cast(loop.m_body[i]), decrement_stmt); + for (size_t j = 0; j < if_body.size(); j++) { + new_body.push_back(al, if_body[j]); + } + } else { + new_body.push_back(al, loop.m_body[i]); + } + } + + body = new_body; + } + Vec replace_doloop(Allocator &al, const ASR::DoLoop_t &loop, int comp, bool use_loop_variable_after_loop) { Location loc = loop.base.base.loc; @@ -1037,7 +1273,11 @@ namespace LCompilers { increment = ASR::down_cast(c)->m_n; } else if (c->type == ASR::exprType::IntegerUnaryMinus) { ASR::IntegerUnaryMinus_t *u = ASR::down_cast(c); - increment = - ASR::down_cast(u->m_arg)->m_n; + if (ASR::is_a(*u->m_arg)) { + increment = - ASR::down_cast(u->m_arg)->m_n; + } else { + not_constant_inc = true; + } } else { // This is the case when increment operator is not a // constant, and so we need some conditions to check @@ -1125,9 +1365,15 @@ namespace LCompilers { if( inc_stmt ) { body.push_back(al, inc_stmt); } - for (size_t i=0; i result; @@ -1143,9 +1389,9 @@ namespace LCompilers { return result; } - #define increment_by_one(var, body) ASR::expr_t* inc_by_one = builder.ElementalAdd(var, \ + #define increment_by_one(var, body) ASR::expr_t* inc_by_one = builder.Add(var, \ make_ConstantWithType(make_IntegerConstant_t, 1, \ - ASRUtils::expr_type(var), loc), loc); \ + ASRUtils::expr_type(var), loc)); \ ASR::stmt_t* assign_inc = builder.Assignment(var, inc_by_one); \ body->push_back(al, assign_inc); \ @@ -1156,8 +1402,8 @@ namespace LCompilers { bool perform_cast, ASR::cast_kindType cast_kind, ASR::ttype_t* casted_type) { const Location& loc = arr_var->base.loc; ASRUtils::ASRBuilder builder(al, loc); - for( size_t k = 0; k < x->n_args; k++ ) { - ASR::expr_t* curr_init = x->m_args[k]; + for( size_t k = 0; k < (size_t) ASRUtils::get_fixed_size_of_array(x->m_type); k++ ) { + ASR::expr_t* curr_init = ASRUtils::fetch_ArrayConstant_value(al, x, k); ASR::expr_t* res = PassUtils::create_array_ref(arr_var, idx_var, al, current_scope); if( perform_cast && !ASRUtils::types_equal(ASRUtils::expr_type(curr_init), casted_type) ) { @@ -1223,63 +1469,123 @@ namespace LCompilers { } else if( ASR::is_a(*curr_init) ) { ASR::ArraySection_t* array_section = ASR::down_cast(curr_init); Vec idx_vars; + Vec temp_idx_vars; Vec doloop_body; - create_do_loop(al, loc, array_section, idx_vars, doloop_body, - [=, &idx_vars, &doloop_body, &builder, &al] () { - ASR::expr_t* ref = PassUtils::create_array_ref(array_section, idx_vars, + create_do_loop(al, loc, array_section, idx_vars, temp_idx_vars, doloop_body, + [=, &temp_idx_vars, &doloop_body, &builder, &al] () { + ASR::expr_t* ref = PassUtils::create_array_ref(array_section->m_v, temp_idx_vars, al, current_scope, perform_cast, cast_kind, casted_type); ASR::expr_t* res = PassUtils::create_array_ref(arr_var, idx_var, al, current_scope); ASR::stmt_t* assign = builder.Assignment(res, ref); doloop_body.push_back(al, assign); increment_by_one(idx_var, (&doloop_body)) }, current_scope, result_vec); + } else if (ASR::is_a(*curr_init) ) { + bool contains_array = false; + ASR::ArrayItem_t* array_item = ASR::down_cast(curr_init); + for(size_t i = 0; i < array_item->n_args; i++) { + ASR::expr_t* curr_arg = array_item->m_args[i].m_right; + if(curr_arg && ASRUtils::is_array(ASRUtils::expr_type(curr_arg))) { + contains_array = true; + } + } + if(contains_array) { + Vec idx_vars; + Vec temp_idx_vars; + Vec doloop_body; + create_do_loop(al, loc, array_item, idx_vars, temp_idx_vars, doloop_body, + [=, &temp_idx_vars, &doloop_body, &builder, &al, &perform_cast, &cast_kind, &casted_type] () { + ASR::expr_t* ref = PassUtils::create_array_ref(array_item->m_v, temp_idx_vars, al, + current_scope, perform_cast, cast_kind, casted_type); + ASR::expr_t* res = PassUtils::create_array_ref(arr_var, idx_var, al, current_scope); + ASR::stmt_t* assign = builder.Assignment(res, ref); + doloop_body.push_back(al, assign); + increment_by_one(idx_var, (&doloop_body)) + }, current_scope, result_vec); + } else { + ASR::expr_t* res = PassUtils::create_array_ref(arr_var, idx_var, + al, current_scope); + if( perform_cast ) { + curr_init = ASRUtils::EXPR(ASR::make_Cast_t( + al, curr_init->base.loc, curr_init, cast_kind, casted_type, nullptr)); + } + ASR::stmt_t* assign = builder.Assignment(res, curr_init); + result_vec->push_back(al, assign); + increment_by_one(idx_var, result_vec) + } } else { - ASR::expr_t* res = PassUtils::create_array_ref(arr_var, idx_var, - al, current_scope); - if( perform_cast ) { - curr_init = ASRUtils::EXPR(ASR::make_Cast_t( - al, curr_init->base.loc, curr_init, cast_kind, casted_type, nullptr)); + if( ASRUtils::is_array(ASRUtils::expr_type(curr_init)) ) { + ASRUtils::ExprStmtDuplicator expr_duplicator(al); + ASR::expr_t* int32_one = ASRUtils::EXPR(ASR::make_IntegerConstant_t( + al, loc, 1, ASRUtils::expr_type(idx_var))); + ASR::expr_t* step = int32_one; + ASR::expr_t* start = idx_var; + ASR::expr_t* curr_init_array_size = ASRUtils::get_size( + expr_duplicator.duplicate_expr(curr_init), al, false); + Vec array_section_index; + array_section_index.reserve(al, 1); + ASR::array_index_t index; index.loc = loc; + ASR::expr_t* start_plus_size = ASRUtils::EXPR(ASR::make_IntegerBinOp_t( + al, loc, start, ASR::binopType::Add, curr_init_array_size, + ASRUtils::expr_type(idx_var), nullptr)); + index.m_left = start; index.m_right = ASRUtils::EXPR(ASR::make_IntegerBinOp_t( + al, loc, start_plus_size, ASR::binopType::Sub, int32_one, + ASRUtils::expr_type(idx_var), nullptr)); + index.m_step = step; + array_section_index.push_back(al, index); + + ASR::ttype_t* type = nullptr; + ASR::dimension_t dimension; + dimension.loc = loc; + dimension.m_start = int32_one; + if( (ASRUtils::is_allocatable(ASRUtils::expr_type(curr_init)) || + ASRUtils::is_pointer(ASRUtils::expr_type(curr_init)) || + ASRUtils::is_dimension_empty(ASRUtils::expr_type(curr_init))) && + (ASR::is_a(*curr_init) || + ASR::is_a(*curr_init)) ) { + dimension.m_length = nullptr; + } else { + ASR::expr_t* curr_init_array_size_for_type = ASRUtils::get_size(curr_init, al, true); + dimension.m_length = curr_init_array_size_for_type; + } + Vec dims; dims.reserve(al, 1); + dims.push_back(al, dimension); + bool is_alloc_return_func = false; + if( dimension.m_length && ASR::is_a(*dimension.m_length) ) { + ASR::ArraySize_t* array_size = ASR::down_cast(dimension.m_length); + if( (ASR::is_a(*array_size->m_v) && + ASRUtils::is_allocatable(array_size->m_v)) || + ASR::is_a(*array_size->m_v) ) { + is_alloc_return_func = true; + } + } + type = ASRUtils::make_Array_t_util(al, loc, + ASRUtils::type_get_past_array( + ASRUtils::type_get_past_allocatable_pointer( + ASRUtils::expr_type(arr_var))), + dims.p, dims.size(), ASR::abiType::Source, false, + ASR::array_physical_typeType::DescriptorArray, + false, false, !is_alloc_return_func); + ASR::expr_t* res = ASRUtils::EXPR(ASR::make_ArraySection_t( + al, loc, arr_var, array_section_index.p, 1, type, nullptr)); + ASR::stmt_t* assign = builder.Assignment(res, curr_init); + result_vec->push_back(al, assign); + ASR::stmt_t* inc_stmt = builder.Assignment(idx_var, expr_duplicator.duplicate_expr(start_plus_size)); + result_vec->push_back(al, inc_stmt); + } else { + ASR::expr_t* res = PassUtils::create_array_ref(arr_var, idx_var, + al, current_scope); + if( perform_cast ) { + curr_init = ASRUtils::EXPR(ASR::make_Cast_t( + al, curr_init->base.loc, curr_init, cast_kind, casted_type, nullptr)); + } + ASR::stmt_t* assign = builder.Assignment(res, curr_init); + result_vec->push_back(al, assign); + increment_by_one(idx_var, result_vec) } - ASR::stmt_t* assign = builder.Assignment(res, curr_init); - result_vec->push_back(al, assign); - increment_by_one(idx_var, result_vec) - } - } - } - } - ASR::symbol_t* get_struct_member(Allocator& al, ASR::symbol_t* struct_type_sym, std::string &call_name, - const Location &loc, SymbolTable* current_scope) { - ASR::Struct_t* struct_type = ASR::down_cast(struct_type_sym); - std::string struct_var_name = struct_type->m_name; - std::string struct_member_name = call_name; - ASR::symbol_t* struct_member = struct_type->m_symtab->resolve_symbol(struct_member_name); - ASR::symbol_t* struct_mem_asr_owner = ASRUtils::get_asr_owner(struct_member); - if( !struct_member || !struct_mem_asr_owner || - !ASR::is_a(*struct_mem_asr_owner) ) { - throw LCompilersException(struct_member_name + " not present in " + - struct_var_name + " dataclass"); - } - std::string import_name = struct_var_name + "_" + struct_member_name; - ASR::symbol_t* import_struct_member = current_scope->resolve_symbol(import_name); - bool import_from_struct = true; - if( import_struct_member ) { - if( ASR::is_a(*import_struct_member) ) { - ASR::ExternalSymbol_t* ext_sym = ASR::down_cast(import_struct_member); - if( ext_sym->m_external == struct_member && - std::string(ext_sym->m_module_name) == struct_var_name ) { - import_from_struct = false; } } } - if( import_from_struct ) { - import_name = current_scope->get_unique_name(import_name, false); - import_struct_member = ASR::down_cast(ASR::make_ExternalSymbol_t(al, - loc, current_scope, s2c(al, import_name), - struct_member, s2c(al, struct_var_name), nullptr, 0, - s2c(al, struct_member_name), ASR::accessType::Public)); - current_scope->add_symbol(import_name, import_struct_member); - } - return import_struct_member; } } // namespace PassUtils diff --git a/src/libasr/pass/pass_utils.h b/src/libasr/pass/pass_utils.h index 2025e78113..62276810be 100644 --- a/src/libasr/pass/pass_utils.h +++ b/src/libasr/pass/pass_utils.h @@ -3,8 +3,9 @@ #include #include +#include -#include +#include namespace LCompilers { @@ -43,6 +44,7 @@ namespace LCompilers { ASR::down_cast(x))->m_elemental; } + bool is_args_contains_allocatable(ASR::expr_t* x); void fix_dimension(ASR::Cast_t* x, ASR::expr_t* arg_expr); ASR::ttype_t* get_matching_type(ASR::expr_t* sibling, Allocator& al); @@ -80,7 +82,6 @@ namespace LCompilers { ASR::expr_t* get_bound(ASR::expr_t* arr_expr, int dim, std::string bound, Allocator& al); - ASR::expr_t* get_flipsign(ASR::expr_t* arg0, ASR::expr_t* arg1, Allocator& al, ASR::TranslationUnit_t& unit, const Location& loc, PassOptions& pass_options); @@ -92,7 +93,7 @@ namespace LCompilers { ASR::expr_t* create_auxiliary_variable(const Location& loc, std::string& name, Allocator& al, SymbolTable*& current_scope, ASR::ttype_t* var_type, - ASR::intentType var_intent=ASR::intentType::Local); + ASR::intentType var_intent=ASR::intentType::Local, ASR::symbol_t* var_decl=nullptr); ASR::expr_t* get_fma(ASR::expr_t* arg0, ASR::expr_t* arg1, ASR::expr_t* arg2, Allocator& al, ASR::TranslationUnit_t& unit, Location& loc, @@ -127,6 +128,24 @@ namespace LCompilers { ASR::stmt_t* inner_most_do_loop, ASR::expr_t* c, ASR::expr_t* mask, ASR::expr_t* res, int curr_idx, int dim); + ASR::stmt_t* create_do_loop_helper_norm2(Allocator &al, const Location &loc, + std::vector do_loop_variables, ASR::expr_t* array, ASR::expr_t* res, + int curr_idx); + + ASR::stmt_t* create_do_loop_helper_norm2_dim(Allocator &al, const Location &loc, + std::vector do_loop_variables, std::vector res_idx, + ASR::stmt_t* inner_most_do_loop, ASR::expr_t* c, ASR::expr_t* array, ASR::expr_t* res, + int curr_idx, int dim); + + ASR::stmt_t* create_do_loop_helper_parity(Allocator &al, const Location &loc, + std::vector do_loop_variables, ASR::expr_t* array, ASR::expr_t* res, + int curr_idx); + + ASR::stmt_t* create_do_loop_helper_parity_dim(Allocator &al, const Location &loc, + std::vector do_loop_variables, std::vector res_idx, + ASR::stmt_t* inner_most_do_loop, ASR::expr_t* c, ASR::expr_t* array, ASR::expr_t* res, + int curr_idx, int dim); + ASR::stmt_t* create_do_loop_helper_random_number(Allocator &al, const Location &loc, std::vector do_loop_variables, ASR::symbol_t* s, ASR::expr_t* arr, ASR::ttype_t* return_type, ASR::expr_t* arr_item, ASR::stmt_t* stmt, int curr_idx); @@ -135,11 +154,25 @@ namespace LCompilers { return ASR::is_a(*ASRUtils::expr_type(var)); } + /* Checks for any non-primitive-function-return type + like fixed strings or allocatables. + allocatable string, allocatable integer, etc.. */ + static inline bool is_non_primitive_return_type(ASR::ttype_t* x){ + // TODO : Handle other allocatable types and fixed strings. + return ASRUtils::is_descriptorString(x); + } + static inline bool is_aggregate_or_array_type(ASR::expr_t* var) { return (ASR::is_a(*ASRUtils::expr_type(var)) || ASRUtils::is_array(ASRUtils::expr_type(var)) || ASR::is_a(*ASRUtils::expr_type(var))); } + + static inline bool is_aggregate_or_array_or_nonPrimitive_type(ASR::expr_t* var) { + return is_aggregate_or_array_type(var) || + is_non_primitive_return_type(ASRUtils::expr_type(var)); + } + static inline bool is_symbolic_list_type(ASR::expr_t* var) { if (ASR::is_a(*ASRUtils::expr_type(var))) { @@ -163,19 +196,25 @@ namespace LCompilers { ASR::FunctionCall_t* func_call = ASR::down_cast(func_call_merge); if (ASR::is_a(*func_call->m_args[0].m_value)) { ASR::ArraySize_t *array_size = ASR::down_cast(func_call->m_args[0].m_value); - array_size->m_v = ASR::down_cast(new_args[map[0]].m_value)->m_arg; + if (ASR::is_a(*new_args[map[0]].m_value)) { + array_size->m_v = ASR::down_cast(new_args[map[0]].m_value)->m_arg; + } else { + array_size->m_v = new_args[map[0]].m_value; + } func_call->m_args[0].m_value = ASRUtils::EXPR((ASR::asr_t*) array_size); } if (ASR::is_a(*func_call->m_args[1].m_value)) { ASR::ArraySize_t *array_size = ASR::down_cast(func_call->m_args[1].m_value); - array_size->m_v = ASR::down_cast(new_args[map[1]].m_value)->m_arg; - + if (ASR::is_a(*new_args[map[1]].m_value)) + array_size->m_v = ASR::down_cast(new_args[map[1]].m_value)->m_arg; + else { + array_size->m_v = new_args[map[1]].m_value; + } func_call->m_args[1].m_value = ASRUtils::EXPR((ASR::asr_t*) array_size); } if (ASR::is_a(*func_call->m_args[2].m_value)) { ASR::IntegerCompare_t *integer_compare = ASR::down_cast(func_call->m_args[2].m_value); integer_compare->m_right = new_args[map[2]].m_value; - func_call->m_args[2].m_value = ASRUtils::EXPR((ASR::asr_t*) integer_compare); } res_arr->m_dims[i].m_length = func_call_merge; @@ -551,8 +590,8 @@ namespace LCompilers { if( ASR::is_a(*type) ) { ASR::StructType_t* struct_t = ASR::down_cast(type); vec.push_back(al, ASRUtils::symbol_name(struct_t->m_derived_type)); - } else if( ASR::is_a(*type) ) { - ASR::Enum_t* enum_t = ASR::down_cast(type); + } else if( ASR::is_a(*type) ) { + ASR::EnumType_t* enum_t = ASR::down_cast(type); vec.push_back(al, ASRUtils::symbol_name(enum_t->m_enum_type)); } } @@ -564,15 +603,12 @@ namespace LCompilers { visit_UserDefinedType(x); } - void visit_UnionType(const ASR::UnionType_t& x) { + void visit_Union(const ASR::Union_t& x) { visit_UserDefinedType(x); } */ }; - ASR::symbol_t* get_struct_member(Allocator& al, ASR::symbol_t* struct_type_sym, std::string &call_name, - const Location &loc, SymbolTable* current_scope); - namespace ReplacerUtils { template void replace_StructConstructor(ASR::StructConstructor_t* x, @@ -581,33 +617,6 @@ namespace LCompilers { bool perform_cast=false, ASR::cast_kindType cast_kind=ASR::cast_kindType::IntegerToInteger, ASR::ttype_t* casted_type=nullptr) { - if ( ASR::is_a(*(x->m_dt_sym)) ) { - ASR::Struct_t* st = ASR::down_cast(x->m_dt_sym); - if ( st->n_member_functions > 0 ) { - remove_original_statement = true; - if ( !ASR::is_a(*(replacer->result_var)) ) { - throw LCompilersException("Expected a var here"); - } - ASR::Var_t* target = ASR::down_cast(replacer->result_var); - ASR::call_arg_t first_arg; - first_arg.loc = x->base.base.loc; first_arg.m_value = replacer->result_var; - Vec new_args; new_args.reserve(replacer->al,x->n_args+1); - new_args.push_back(replacer->al, first_arg); - for( size_t i = 0; i < x->n_args; i++ ) { - new_args.push_back(replacer->al, x->m_args[i]); - } - ASR::StructType_t* type = ASR::down_cast( - (ASR::down_cast(target->m_v))->m_type); - std::string call_name = "__init__"; - ASR::symbol_t* call_sym = get_struct_member(replacer->al,type->m_derived_type, call_name, - x->base.base.loc, replacer->current_scope); - result_vec->push_back(replacer->al, ASRUtils::STMT( - ASRUtils::make_SubroutineCall_t_util(replacer->al, - x->base.base.loc, call_sym, nullptr, new_args.p, new_args.size(), - nullptr, nullptr, false, false))); - return; - } - } if( x->n_args == 0 ) { if( !inside_symtab ) { remove_original_statement = true; @@ -615,7 +624,7 @@ namespace LCompilers { return ; } if( replacer->result_var == nullptr ) { - std::string result_var_name = replacer->current_scope->get_unique_name("temp_struct_var__", false); + std::string result_var_name = replacer->current_scope->get_unique_name("temp_struct_var__"); replacer->result_var = PassUtils::create_auxiliary_variable(x->base.base.loc, result_var_name, replacer->al, replacer->current_scope, x->m_type); *replacer->current_expr = replacer->result_var; @@ -628,22 +637,22 @@ namespace LCompilers { } std::deque constructor_arg_syms; - ASR::StructType_t* dt_dertype = ASR::down_cast(x->m_type); - ASR::Struct_t* dt_der = ASR::down_cast( - ASRUtils::symbol_get_past_external(dt_dertype->m_derived_type)); - while( dt_der ) { - for( int i = (int) dt_der->n_members - 1; i >= 0; i-- ) { + ASR::StructType_t* dt_der = ASR::down_cast(x->m_type); + ASR::Struct_t* dt_dertype = ASR::down_cast( + ASRUtils::symbol_get_past_external(dt_der->m_derived_type)); + while( dt_dertype ) { + for( int i = (int) dt_dertype->n_members - 1; i >= 0; i-- ) { constructor_arg_syms.push_front( - dt_der->m_symtab->get_symbol( - dt_der->m_members[i])); + dt_dertype->m_symtab->get_symbol( + dt_dertype->m_members[i])); } - if( dt_der->m_parent != nullptr ) { + if( dt_dertype->m_parent != nullptr ) { ASR::symbol_t* dt_der_sym = ASRUtils::symbol_get_past_external( - dt_der->m_parent); + dt_dertype->m_parent); LCOMPILERS_ASSERT(ASR::is_a(*dt_der_sym)); - dt_der = ASR::down_cast(dt_der_sym); + dt_dertype = ASR::down_cast(dt_der_sym); } else { - dt_der = nullptr; + dt_dertype = nullptr; } } LCOMPILERS_ASSERT(constructor_arg_syms.size() == x->n_args); @@ -687,6 +696,7 @@ namespace LCompilers { result_vec->push_back(replacer->al, assign); } } + replacer->result_var = nullptr; } static inline void create_do_loop(Allocator& al, ASR::ImpliedDoLoop_t* idoloop, @@ -800,23 +810,81 @@ namespace LCompilers { template static inline void create_do_loop(Allocator& al, const Location& loc, - ASR::ArraySection_t* array_section, Vec& idx_vars, + ASR::ArrayItem_t* array_item, Vec& idx_vars, Vec& temp_idx_vars, + Vec& doloop_body, LOOP_BODY loop_body, SymbolTable* current_scope, + Vec* result_vec) { + int value_rank = array_item->n_args; + PassUtils::create_idx_vars(idx_vars, value_rank, loc, al, current_scope, "_t"); + LCOMPILERS_ASSERT(value_rank == (int) idx_vars.size()) + temp_idx_vars.reserve(al, array_item->n_args); + for( int i = 0; i < value_rank; i++ ) { + if(ASRUtils::is_array(ASRUtils::expr_type(array_item->m_args[i].m_right))){ + ASR::expr_t* ref = PassUtils::create_array_ref(array_item->m_args[i].m_right, idx_vars[i], al, current_scope); + temp_idx_vars.push_back(al, ref); + } else { + temp_idx_vars.push_back(al, array_item->m_args[i].m_right); + } + } + ASR::stmt_t* doloop = nullptr; + for( int i = 0; i < value_rank; i++ ) { + ASR::do_loop_head_t head; + head.m_v = idx_vars[i]; + if(ASRUtils::is_array(ASRUtils::expr_type(array_item->m_args[i].m_right))) { + head.m_start = PassUtils::get_bound(array_item->m_args[i].m_right, 1, "lbound", al); + head.m_end = PassUtils::get_bound(array_item->m_args[i].m_right, 1, "ubound", al); + head.m_increment = nullptr; + } else { + continue; + } + head.loc = head.m_v->base.loc; + + doloop_body.reserve(al, 1); + if( doloop == nullptr ) { + loop_body(); + } else { + doloop_body.push_back(al, doloop); + } + doloop = ASRUtils::STMT(ASR::make_DoLoop_t(al, loc, nullptr, head, + doloop_body.p, doloop_body.size(), nullptr, 0)); + } + if(doloop != nullptr) result_vec->push_back(al, doloop); + } + + template + static inline void create_do_loop(Allocator& al, const Location& loc, + ASR::ArraySection_t* array_section, Vec& idx_vars, Vec& temp_idx_vars, Vec& doloop_body, LOOP_BODY loop_body, SymbolTable* current_scope, Vec* result_vec) { PassUtils::create_idx_vars(idx_vars, array_section->n_args, loc, al, current_scope, "_t"); LCOMPILERS_ASSERT(array_section->n_args == idx_vars.size()) + temp_idx_vars.reserve(al, array_section->n_args); + for( size_t i = 0; i < array_section->n_args; i++ ) { + if ( ASRUtils::is_array(ASRUtils::expr_type(array_section->m_args[i].m_right)) ) { + ASR::expr_t* ref = PassUtils::create_array_ref(array_section->m_args[i].m_right, idx_vars[i], al, current_scope); + temp_idx_vars.push_back(al, ref); + } else if ( array_section->m_args[i].m_step != nullptr ) { + temp_idx_vars.push_back(al, idx_vars[i]); + } else { + temp_idx_vars.push_back(al, array_section->m_args[i].m_right); + } + } ASR::stmt_t* doloop = nullptr; for( size_t i = 0; i < array_section->n_args; i++ ) { - if( array_section->m_args[i].m_step == nullptr ) { - continue ; - } // TODO: Add an If debug node to check if the lower and upper bounds of both the arrays are same. ASR::do_loop_head_t head; head.m_v = idx_vars[i]; - head.m_start = array_section->m_args[i].m_left; - head.m_end = array_section->m_args[i].m_right; - head.m_increment = array_section->m_args[i].m_step; + if( ASRUtils::is_array(ASRUtils::expr_type(array_section->m_args[i].m_right)) ) { + head.m_start = PassUtils::get_bound(array_section->m_args[i].m_right, 1, "lbound", al); + head.m_end = PassUtils::get_bound(array_section->m_args[i].m_right, 1, "ubound", al); + head.m_increment = nullptr; + } else if ( array_section->m_args[i].m_step == nullptr ) { + continue ; + } else { + head.m_start = array_section->m_args[i].m_left; + head.m_end = array_section->m_args[i].m_right; + head.m_increment = array_section->m_args[i].m_step; + } head.loc = head.m_v->base.loc; doloop_body.reserve(al, 1); @@ -831,6 +899,116 @@ namespace LCompilers { result_vec->push_back(al, doloop); } + template + static inline void create_do_loop_assign(Allocator& al, const Location& loc, + ASR::expr_t* lhs, ASR::expr_t* rhs, Vec& idx_vars, Vec& temp_idx_vars_lhs, + Vec& temp_idx_vars_rhs, Vec& doloop_body, LOOP_BODY loop_body, + SymbolTable* current_scope, Vec* result_vec) { + if (ASR::is_a(*lhs) && ASR::is_a(*rhs)) { + // Case : A([1,2,3]) = B([1,2,3]) + ASR::ArrayItem_t* lhs_array = ASR::down_cast(lhs); + ASR::ArrayItem_t* rhs_array = ASR::down_cast(rhs); + int n_array_indices = 0; + for( size_t i = 0; i < rhs_array->n_args; i++ ) { + if (ASRUtils::is_array(ASRUtils::expr_type(rhs_array->m_args[i].m_right))) { + n_array_indices++; + } + } + if(n_array_indices == 0) return; + PassUtils::create_idx_vars(idx_vars, n_array_indices, loc, al, current_scope, "_t"); + temp_idx_vars_rhs.reserve(al, rhs_array->n_args); + temp_idx_vars_lhs.reserve(al, lhs_array->n_args); + for( size_t i = 0, j = 0; i < rhs_array->n_args; i++ ) { + if (ASRUtils::is_array(ASRUtils::expr_type(rhs_array->m_args[i].m_right))) { + ASR::expr_t* ref = PassUtils::create_array_ref(rhs_array->m_args[i].m_right, idx_vars[j], al, current_scope); + temp_idx_vars_rhs.push_back(al, ref); + j++; + } else { + temp_idx_vars_rhs.push_back(al, rhs_array->m_args[i].m_right); + } + } + for( size_t i = 0, j = 0; i < lhs_array->n_args; i++ ) { + if (ASRUtils::is_array(ASRUtils::expr_type(lhs_array->m_args[i].m_right))) { + ASR::expr_t* ref = PassUtils::create_array_ref(lhs_array->m_args[i].m_right, idx_vars[j], al, current_scope); + temp_idx_vars_lhs.push_back(al, ref); + j++; + } else { + temp_idx_vars_lhs.push_back(al, lhs_array->m_args[i].m_right); + } + } + + ASR::stmt_t* doloop = nullptr; + for( size_t i = 0, j = 0; i < rhs_array->n_args; i++ ) { + ASR::do_loop_head_t head; + head.m_v = idx_vars[j]; + if (ASRUtils::is_array(ASRUtils::expr_type(rhs_array->m_args[i].m_right))) { + head.m_start = PassUtils::get_bound(rhs_array->m_args[i].m_right, 1, "lbound", al); + head.m_end = PassUtils::get_bound(rhs_array->m_args[i].m_right, 1, "ubound", al); + head.m_increment = nullptr; + j++; + } else { + continue; + } + head.loc = head.m_v->base.loc; + + doloop_body.reserve(al, 1); + if( doloop == nullptr ) { + loop_body(); + } else { + doloop_body.push_back(al, doloop); + } + doloop = ASRUtils::STMT(ASR::make_DoLoop_t(al, loc, nullptr, head, + doloop_body.p, doloop_body.size(), nullptr, 0)); + } + result_vec->push_back(al, doloop); + } else if (ASR::is_a(*lhs) && ASR::is_a(*rhs)) { + // Case : A([1,2,3]) = A2 + ASR::ArrayItem_t* lhs_array = ASR::down_cast(lhs); + int n_array_indices = ASRUtils::extract_n_dims_from_ttype(ASRUtils::expr_type(rhs)); + if(n_array_indices == 0) return; + PassUtils::create_idx_vars(idx_vars, n_array_indices, loc, al, current_scope, "_t"); + temp_idx_vars_rhs.reserve(al, n_array_indices); + temp_idx_vars_lhs.reserve(al, lhs_array->n_args); + for( int i = 0; i < n_array_indices; i++ ) { + temp_idx_vars_rhs.push_back(al, idx_vars[i]); + } + for( size_t i = 0, j = 0; i < lhs_array->n_args; i++ ) { + if (ASRUtils::is_array(ASRUtils::expr_type(lhs_array->m_args[i].m_right))) { + ASR::expr_t* ref = PassUtils::create_array_ref(lhs_array->m_args[i].m_right, idx_vars[j], al, current_scope); + temp_idx_vars_lhs.push_back(al, ref); + j++; + } else { + temp_idx_vars_lhs.push_back(al, lhs_array->m_args[i].m_right); + } + } + + ASR::stmt_t* doloop = nullptr; + for( size_t i = 0, j = 0; i < lhs_array->n_args; i++ ) { + ASR::do_loop_head_t head; + head.m_v = idx_vars[j]; + if (ASRUtils::is_array(ASRUtils::expr_type(lhs_array->m_args[i].m_right))) { + head.m_start = PassUtils::get_bound(lhs_array->m_args[i].m_right, 1, "lbound", al); + head.m_end = PassUtils::get_bound(lhs_array->m_args[i].m_right, 1, "ubound", al); + head.m_increment = nullptr; + j++; + } else { + continue; + } + head.loc = head.m_v->base.loc; + + doloop_body.reserve(al, 1); + if( doloop == nullptr ) { + loop_body(); + } else { + doloop_body.push_back(al, doloop); + } + doloop = ASRUtils::STMT(ASR::make_DoLoop_t(al, loc, nullptr, head, + doloop_body.p, doloop_body.size(), nullptr, 0)); + } + result_vec->push_back(al, doloop); + } + } + void visit_ArrayConstant(ASR::ArrayConstant_t* x, Allocator& al, ASR::expr_t* arr_var, Vec* result_vec, ASR::expr_t* idx_var, SymbolTable* current_scope, @@ -850,7 +1028,7 @@ namespace LCompilers { ASR::cast_kindType cast_kind=ASR::cast_kindType::IntegerToInteger, ASR::ttype_t* casted_type=nullptr) { LCOMPILERS_ASSERT(replacer->result_var != nullptr); - if( x->n_args == 0 ) { + if( ASRUtils::get_fixed_size_of_array(x->m_type) == 0 ) { remove_original_statement = true; return ; } @@ -898,7 +1076,7 @@ namespace LCompilers { ASR::stmt_t* assign_stmt = ASRUtils::STMT(ASR::make_Assignment_t(replacer->al, target_section->base.base.loc, idx_var, lb, nullptr)); result_vec->push_back(replacer->al, assign_stmt); - for( size_t k = 0; k < x->n_args; k++ ) { + for( size_t k = 0; k < (size_t) ASRUtils::get_fixed_size_of_array(x->m_type); k++ ) { Vec args; args.reserve(replacer->al, target_section->n_args); for( size_t i = 0; i < target_section->n_args; i++ ) { @@ -926,7 +1104,7 @@ namespace LCompilers { ASRUtils::type_get_past_pointer( ASRUtils::type_get_past_allocatable(array_ref_type)), ASR::arraystorageType::RowMajor, nullptr)); - ASR::expr_t* x_m_args_k = x->m_args[k]; + ASR::expr_t* x_m_args_k = ASRUtils::fetch_ArrayConstant_value(replacer->al, x, k); if( perform_cast ) { LCOMPILERS_ASSERT(casted_type != nullptr); x_m_args_k = ASRUtils::EXPR(ASR::make_Cast_t(replacer->al, array_ref->base.loc, @@ -943,6 +1121,29 @@ namespace LCompilers { } } + static inline void replace_ArrayConstructor_(Allocator& al, ASR::ArrayConstructor_t* x, + ASR::expr_t* result_var, Vec* result_vec, SymbolTable* current_scope, + bool perform_cast=false, ASR::cast_kindType cast_kind=ASR::cast_kindType::IntegerToInteger, + ASR::ttype_t* casted_type=nullptr) { + LCOMPILERS_ASSERT(result_var != nullptr); + const Location& loc = x->base.base.loc; + LCOMPILERS_ASSERT(ASR::is_a(*result_var)); + [[maybe_unused]] ASR::ttype_t* result_var_type = ASRUtils::expr_type(result_var); + LCOMPILERS_ASSERT_MSG(ASRUtils::extract_n_dims_from_ttype(result_var_type) == 1, + "Initialisation using ArrayConstructor is " + "supported only for single dimensional arrays, found: " + + std::to_string(ASRUtils::extract_n_dims_from_ttype(result_var_type))) + Vec idx_vars; + PassUtils::create_idx_vars(idx_vars, 1, loc, al, current_scope, "__libasr_index_"); + ASR::expr_t* idx_var = idx_vars[0]; + ASR::expr_t* lb = PassUtils::get_bound(result_var, 1, "lbound", al); + ASR::stmt_t* assign_stmt = ASRUtils::STMT(ASR::make_Assignment_t(al, + loc, idx_var, lb, nullptr)); + result_vec->push_back(al, assign_stmt); + visit_ArrayConstructor(x, al, result_var, result_vec, + idx_var, current_scope, perform_cast, cast_kind, casted_type); + } + template static inline void replace_ArrayConstructor(ASR::ArrayConstructor_t* x, T* replacer, bool& remove_original_statement, Vec* result_vec, diff --git a/src/libasr/pass/print_arr.cpp b/src/libasr/pass/print_arr.cpp index ea5416e25e..63bdc7b2e9 100644 --- a/src/libasr/pass/print_arr.cpp +++ b/src/libasr/pass/print_arr.cpp @@ -58,16 +58,11 @@ class PrintArrVisitor : public PassUtils::PassVisitor Vec idx_vars; PassUtils::create_idx_vars(idx_vars, n_dims, loc, al, current_scope); ASR::stmt_t* doloop = nullptr; - ASR::stmt_t* empty_print_endl = ASRUtils::STMT(ASR::make_Print_t(al, loc, - nullptr, 0, nullptr, nullptr)); - ASR::ttype_t *str_type_len_1 = ASRUtils::TYPE(ASR::make_Character_t( - al, loc, 1, 1, nullptr)); - ASR::ttype_t *str_type_len_2 = ASRUtils::TYPE(ASR::make_Character_t( - al, loc, 1, 0, nullptr)); - ASR::expr_t *space = ASRUtils::EXPR(ASR::make_StringConstant_t( - al, loc, s2c(al, " "), str_type_len_1)); + ASR::ttype_t *str_type_len_2 = ASRUtils::TYPE(ASR::make_String_t( + al, loc, 1, 0, nullptr, ASR::string_physical_typeType::PointerString)); ASR::expr_t *empty_space = ASRUtils::EXPR(ASR::make_StringConstant_t( al, loc, s2c(al, ""), str_type_len_2)); + ASR::stmt_t* empty_print_endl = ASRUtils::STMT(ASR::make_Print_t(al, loc, empty_space)); for( int i = n_dims - 1; i >= 0; i-- ) { ASR::do_loop_head_t head; head.m_v = idx_vars[i]; @@ -90,14 +85,14 @@ class PrintArrVisitor : public PassUtils::PassVisitor Vec format_args; format_args.reserve(al, 1); format_args.push_back(al, string_format); - print_stmt = ASRUtils::STMT(ASR::make_Print_t(al, loc, - format_args.p, format_args.size(), nullptr, empty_space)); - } else if (ASR::is_a(*ASRUtils::type_get_past_allocatable(ASRUtils::type_get_past_array(ASRUtils::expr_type(print_args[0]))))) { - print_stmt = ASRUtils::STMT(ASR::make_Print_t(al, loc, - print_args.p, print_args.size(), nullptr, empty_space)); + print_stmt = ASRUtils::STMT(ASRUtils::make_print_t_util(al, loc, + format_args.p, format_args.size())); + } else if (ASR::is_a(*ASRUtils::type_get_past_allocatable(ASRUtils::type_get_past_array(ASRUtils::expr_type(print_args[0]))))) { + print_stmt = ASRUtils::STMT(ASRUtils::make_print_t_util(al, loc, + print_args.p, print_args.size())); } else { - print_stmt = ASRUtils::STMT(ASR::make_Print_t(al, loc, - print_args.p, print_args.size(), nullptr, space)); + print_stmt = ASRUtils::STMT(ASRUtils::make_print_t_util(al, loc, + print_args.p, print_args.size())); } doloop_body.push_back(al, print_stmt); } else { @@ -109,24 +104,46 @@ class PrintArrVisitor : public PassUtils::PassVisitor return doloop; } - void print_fixed_sized_array(ASR::expr_t *arr_expr,std::vector& print_body, const Location &loc) { - ASR::dimension_t* m_dims; - int n_dims = ASRUtils::extract_dimensions_from_ttype(ASRUtils::expr_type(arr_expr), m_dims); - int m_dim_length = ASR::down_cast(m_dims->m_length)->m_n; - Vec idx_vars; - PassUtils::create_idx_vars(idx_vars, n_dims, loc, al, current_scope); + void print_fixed_sized_array_helper(ASR::expr_t *arr_expr, std::vector &print_body, + const Location &loc, std::vector ¤t_indices, + int dim_index, int n_dims, ASR::dimension_t* m_dims, + Allocator &al, SymbolTable *current_scope) { ASR::ttype_t *int32_type = ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)); ASR::expr_t* one = ASRUtils::EXPR(ASR::make_IntegerConstant_t(al, loc, 1, int32_type)); - for (int n = 0; n < n_dims; n++) { - ASR::expr_t* idx_var = idx_vars[n]; - idx_var = one; - for (int m = 0; m < m_dim_length; m++) { - ASR::expr_t* ref = PassUtils::create_array_ref(arr_expr, idx_var, al, current_scope); + + int m_dim_length = ASR::down_cast(m_dims[dim_index].m_length)->m_n; + + for (int i = 0; i < m_dim_length; i++) { + if (dim_index == 0) { + Vec indices; + indices.reserve(al, n_dims); + for (int j = 0; j < n_dims; j++) { + indices.push_back(al, current_indices[j]); + } + + ASR::expr_t* ref = PassUtils::create_array_ref(arr_expr, indices, al, current_scope); print_body.push_back(ref); - idx_var = ASRUtils::EXPR(ASR::make_IntegerBinOp_t(al, loc, idx_var, - ASR::binopType::Add, one, int32_type, nullptr)); + } else { + print_fixed_sized_array_helper(arr_expr, print_body, loc, current_indices, + dim_index - 1, n_dims, m_dims, al, current_scope); } + + current_indices[dim_index] = ASRUtils::EXPR(ASR::make_IntegerBinOp_t( + al, loc, current_indices[dim_index], ASR::binopType::Add, one, int32_type, nullptr)); } + current_indices[dim_index] = PassUtils::get_bound(arr_expr, dim_index + 1, "lbound", al); + } + + void print_fixed_sized_array(ASR::expr_t *arr_expr, std::vector &print_body, const Location &loc) { + ASR::dimension_t* m_dims; + int n_dims = ASRUtils::extract_dimensions_from_ttype(ASRUtils::expr_type(arr_expr), m_dims); + + std::vector current_indices(n_dims); + for (int i = 0; i < n_dims; i++) { + current_indices[i] = PassUtils::get_bound(arr_expr, i + 1, "lbound", al); + } + + print_fixed_sized_array_helper(arr_expr, print_body, loc, current_indices, n_dims - 1, n_dims, m_dims, al, current_scope); } ASR::stmt_t* create_formatstmt(std::vector &print_body, ASR::StringFormat_t* format, const Location &loc, ASR::stmtType _type, @@ -144,8 +161,8 @@ class PrintArrVisitor : public PassUtils::PassVisitor print_args.push_back(al, string_format); ASR::stmt_t* statement = nullptr; if (_type == ASR::stmtType::Print) { - statement = ASRUtils::STMT(ASR::make_Print_t(al, loc, - print_args.p, print_args.size(), nullptr, nullptr)); + statement = ASRUtils::STMT(ASRUtils::make_print_t_util(al, loc, + print_args.p, print_args.size())); } else if (_type == ASR::stmtType::FileWrite) { statement = ASRUtils::STMT(ASR::make_FileWrite_t(al, loc, 0, unit, nullptr, nullptr, nullptr, print_args.p, print_args.size(), separator, end, overloaded)); @@ -155,13 +172,17 @@ class PrintArrVisitor : public PassUtils::PassVisitor } void visit_Print(const ASR::Print_t& x) { - std::vector print_body; - ASR::stmt_t* empty_print_endl; - ASR::stmt_t* print_stmt; - if (x.n_values > 0 && ASR::is_a(*x.m_values[0])) { - empty_print_endl = ASRUtils::STMT(ASR::make_Print_t(al, x.base.base.loc, - nullptr, 0, nullptr, nullptr)); - ASR::StringFormat_t* format = ASR::down_cast(x.m_values[0]); + LCOMPILERS_ASSERT(ASR::is_a(*ASRUtils::expr_type(x.m_text))); + if (ASR::is_a(*x.m_text)) { + std::vector print_body; + ASR::stmt_t* empty_print_endl; + ASR::stmt_t* print_stmt; + ASR::ttype_t *str_type_len_2 = ASRUtils::TYPE(ASR::make_String_t( + al, x.base.base.loc, 1, 0, nullptr, ASR::string_physical_typeType::PointerString)); + ASR::expr_t *empty_space = ASRUtils::EXPR(ASR::make_StringConstant_t( + al, x.base.base.loc, s2c(al, ""), str_type_len_2)); + empty_print_endl = ASRUtils::STMT(ASR::make_Print_t(al, x.base.base.loc, empty_space)); + ASR::StringFormat_t* format = ASR::down_cast(x.m_text); for (size_t i=0; in_args; i++) { if (PassUtils::is_array(format->m_args[i])) { if (ASRUtils::is_fixed_size_array(ASRUtils::expr_type(format->m_args[i]))) { @@ -184,75 +205,8 @@ class PrintArrVisitor : public PassUtils::PassVisitor pass_result.push_back(al, print_stmt); } return; - } - ASR::ttype_t *str_type_len_1 = ASRUtils::TYPE(ASR::make_Character_t( - al, x.base.base.loc, 1, 1, nullptr)); - ASR::expr_t *space = ASRUtils::EXPR(ASR::make_StringConstant_t( - al, x.base.base.loc, s2c(al, " "), str_type_len_1)); - ASR::expr_t *backspace = ASRUtils::EXPR(ASR::make_StringConstant_t( - al, x.base.base.loc, s2c(al, "\b"), str_type_len_1)); - ASR::stmt_t* back = ASRUtils::STMT(ASR::make_Print_t(al, x.base.base.loc, - nullptr, 0, nullptr, backspace)); - for (size_t i=0; i(*ASRUtils::expr_type(x.m_values[i])) && - PassUtils::is_array(x.m_values[i])) { - if (print_body.size() > 0) { - Vec body; - body.reserve(al, print_body.size()); - for (size_t j=0; j 0) { - Vec body; - body.reserve(al, print_body.size()); - for (size_t j=0; j Vec idx_vars; PassUtils::create_idx_vars(idx_vars, n_dims, loc, al, current_scope); ASR::stmt_t* doloop = nullptr; - ASR::ttype_t *str_type_len = ASRUtils::TYPE(ASR::make_Character_t( - al, loc, 1, 0, nullptr)); + ASR::ttype_t *str_type_len = ASRUtils::TYPE(ASR::make_String_t( + al, loc, 1, 0, nullptr, ASR::string_physical_typeType::PointerString)); ASR::expr_t *empty_space = ASRUtils::EXPR(ASR::make_StringConstant_t( al, loc, s2c(al, ""), str_type_len)); ASR::stmt_t* empty_file_write_endl = ASRUtils::STMT(ASR::make_FileWrite_t(al, loc, @@ -317,64 +271,67 @@ class PrintArrVisitor : public PassUtils::PassVisitor write_body.clear(); } - void visit_FileWrite(const ASR::FileWrite_t& x) { - if (x.m_unit && ASRUtils::is_character(*ASRUtils::expr_type(x.m_unit))) { - // Skip for character write - return; - } - std::vector write_body; - ASR::stmt_t* write_stmt; - ASR::stmt_t* empty_file_write_endl = ASRUtils::STMT(ASR::make_FileWrite_t(al, x.base.base.loc, - x.m_label, x.m_unit, nullptr, nullptr, nullptr, nullptr, 0, nullptr, nullptr, nullptr)); - if(x.m_values && x.m_values[0] != nullptr && ASR::is_a(*x.m_values[0])){ - ASR::StringFormat_t* format = ASR::down_cast(x.m_values[0]); - for (size_t i=0; in_args; i++) { - if (PassUtils::is_array(format->m_args[i])) { - if (ASRUtils::is_fixed_size_array(ASRUtils::expr_type(format->m_args[i]))) { - print_fixed_sized_array(format->m_args[i], write_body, x.base.base.loc); - } else { - if (write_body.size() > 0) { - write_stmt = create_formatstmt(write_body, format, - x.base.base.loc, ASR::stmtType::FileWrite, x.m_unit, x.m_separator, - x.m_end, x.m_overloaded); - pass_result.push_back(al, write_stmt); - } - write_stmt = write_array_using_doloop(format->m_args[i], format, x.m_unit, x.base.base.loc); - pass_result.push_back(al, write_stmt); - pass_result.push_back(al, empty_file_write_endl); - } - } else { - write_body.push_back(format->m_args[i]); - } - } - if (write_body.size() > 0) { - write_stmt = create_formatstmt(write_body, format, x.base.base.loc, - ASR::stmtType::FileWrite, x.m_unit, x.m_separator, - x.m_end, x.m_overloaded); - pass_result.push_back(al, write_stmt); - } - return; - } - for (size_t i=0; i 0) { - print_args_apart_from_arrays(write_body, x); - pass_result.push_back(al, empty_file_write_endl); - } - write_stmt = write_array_using_doloop(x.m_values[i], nullptr, x.m_unit, x.base.base.loc); - pass_result.push_back(al, write_stmt); - pass_result.push_back(al, empty_file_write_endl); - } else { - write_body.push_back(x.m_values[i]); - } - } - if (write_body.size() > 0) { - print_args_apart_from_arrays(write_body, x); - } - } + // TODO :: CREATE write visitor to loop on arrays of type `structType` only, + // otherwise arrays are handled by backend. + + // void visit_FileWrite(const ASR::FileWrite_t& x) { + // if (x.m_unit && ASRUtils::is_character(*ASRUtils::expr_type(x.m_unit))) { + // // Skip for character write + // return; + // } + // std::vector write_body; + // ASR::stmt_t* write_stmt; + // ASR::stmt_t* empty_file_write_endl = ASRUtils::STMT(ASR::make_FileWrite_t(al, x.base.base.loc, + // x.m_label, x.m_unit, nullptr, nullptr, nullptr, nullptr, 0, nullptr, nullptr, nullptr)); + // if(x.m_values && x.m_values[0] != nullptr && ASR::is_a(*x.m_values[0])){ + // ASR::StringFormat_t* format = ASR::down_cast(x.m_values[0]); + // for (size_t i=0; in_args; i++) { + // if (PassUtils::is_array(format->m_args[i])) { + // if (ASRUtils::is_fixed_size_array(ASRUtils::expr_type(format->m_args[i]))) { + // print_fixed_sized_array(format->m_args[i], write_body, x.base.base.loc); + // } else { + // if (write_body.size() > 0) { + // write_stmt = create_formatstmt(write_body, format, + // x.base.base.loc, ASR::stmtType::FileWrite, x.m_unit, x.m_separator, + // x.m_end, x.m_overloaded); + // pass_result.push_back(al, write_stmt); + // } + // write_stmt = write_array_using_doloop(format->m_args[i], format, x.m_unit, x.base.base.loc); + // pass_result.push_back(al, write_stmt); + // pass_result.push_back(al, empty_file_write_endl); + // } + // } else { + // write_body.push_back(format->m_args[i]); + // } + // } + // if (write_body.size() > 0) { + // write_stmt = create_formatstmt(write_body, format, x.base.base.loc, + // ASR::stmtType::FileWrite, x.m_unit, x.m_separator, + // x.m_end, x.m_overloaded); + // pass_result.push_back(al, write_stmt); + // } + // return; + // } + // for (size_t i=0; i 0) { + // print_args_apart_from_arrays(write_body, x); + // pass_result.push_back(al, empty_file_write_endl); + // } + // write_stmt = write_array_using_doloop(x.m_values[i], nullptr, x.m_unit, x.base.base.loc); + // pass_result.push_back(al, write_stmt); + // pass_result.push_back(al, empty_file_write_endl); + // } else { + // write_body.push_back(x.m_values[i]); + // } + // } + // if (write_body.size() > 0) { + // print_args_apart_from_arrays(write_body, x); + // } + // } }; diff --git a/src/libasr/pass/print_list_tuple.cpp b/src/libasr/pass/print_list_tuple.cpp index ce47301aab..5b70f56db4 100644 --- a/src/libasr/pass/print_list_tuple.cpp +++ b/src/libasr/pass/print_list_tuple.cpp @@ -76,28 +76,23 @@ class PrintListTupleVisitor print_pass_result_tmp.reserve(al, 1); } - void print_list_helper(ASR::expr_t *list_expr, ASR::expr_t *sep_expr, - ASR::expr_t *end_expr, const Location &loc) { + void print_list_helper(ASR::expr_t *list_expr, const Location &loc) { ASR::List_t *listC = ASR::down_cast(ASRUtils::expr_type(list_expr)); ASR::ttype_t *int_type = ASRUtils::TYPE( ASR::make_Integer_t(al, loc, 4)); ASR::ttype_t *bool_type = ASRUtils::TYPE( ASR::make_Logical_t(al, loc, 4)); - ASR::ttype_t *str_type_len_0 = ASRUtils::TYPE(ASR::make_Character_t( - al, loc, 1, 0, nullptr)); - ASR::ttype_t *str_type_len_1 = ASRUtils::TYPE(ASR::make_Character_t( - al, loc, 1, 1, nullptr)); - ASR::ttype_t *str_type_len_2 = ASRUtils::TYPE(ASR::make_Character_t( - al, loc, 1, 2, nullptr)); + ASR::ttype_t *str_type_len_1 = ASRUtils::TYPE(ASR::make_String_t( + al, loc, 1, 1, nullptr, ASR::string_physical_typeType::PointerString)); + ASR::ttype_t *str_type_len_2 = ASRUtils::TYPE(ASR::make_String_t( + al, loc, 1, 2, nullptr, ASR::string_physical_typeType::PointerString)); ASR::expr_t *comma_space = ASRUtils::EXPR(ASR::make_StringConstant_t( al, loc, s2c(al, ", "), str_type_len_2)); ASR::expr_t *single_quote = ASRUtils::EXPR(ASR::make_StringConstant_t( al, loc, s2c(al, "'"), str_type_len_1)); - ASR::expr_t *empty_str = ASRUtils::EXPR(ASR::make_StringConstant_t( - al, loc, s2c(al, ""), str_type_len_0)); ASR::expr_t *open_bracket = ASRUtils::EXPR(ASR::make_StringConstant_t( al, loc, s2c(al, "["), str_type_len_1)); @@ -114,23 +109,11 @@ class PrintListTupleVisitor list_iter_var_name, al, current_scope, int_type); } - std::string list_var_name; - ASR::expr_t *list_var; - { - list_var_name = - current_scope->get_unique_name("__list_var", false); - list_var = PassUtils::create_auxiliary_variable(loc, - list_var_name, al, current_scope, ASRUtils::expr_type(list_expr)); - } - - ASR::stmt_t *assign_stmt = ASRUtils::STMT( - ASR::make_Assignment_t(al, loc, list_var, list_expr, nullptr)); - ASR::expr_t *list_item = ASRUtils::EXPR( - ASR::make_ListItem_t(al, loc, list_var, + ASR::make_ListItem_t(al, loc, list_expr, list_iter_var, listC->m_type, nullptr)); ASR::expr_t *list_len = ASRUtils::EXPR(ASR::make_ListLen_t( - al, loc, list_var, int_type, nullptr)); + al, loc, list_expr, int_type, nullptr)); ASR::expr_t *constant_one = ASRUtils::EXPR( ASR::make_IntegerConstant_t(al, loc, 1, int_type)); ASR::expr_t *list_len_minus_one = @@ -150,7 +133,7 @@ class PrintListTupleVisitor v3.push_back(al, close_bracket); v4.push_back(al, comma_space); - if (ASR::is_a(*listC->m_type)) { + if (ASR::is_a(*listC->m_type)) { v2.reserve(al, 3); v2.push_back(al, single_quote); v2.push_back(al, list_item); @@ -161,17 +144,13 @@ class PrintListTupleVisitor } ASR::stmt_t *print_open_bracket = ASRUtils::STMT( - ASR::make_Print_t(al, loc, v1.p, v1.size(), - nullptr, empty_str)); + ASRUtils::make_print_t_util(al, loc, v1.p, v1.size())); ASR::stmt_t *print_comma_space = ASRUtils::STMT( - ASR::make_Print_t(al, loc, v4.p, v4.size(), - empty_str, empty_str)); + ASRUtils::make_print_t_util(al, loc, v4.p, v4.size())); ASR::stmt_t *print_item = ASRUtils::STMT( - ASR::make_Print_t(al, loc, v2.p, v2.size(), - empty_str, empty_str)); + ASRUtils::make_print_t_util(al, loc, v2.p, v2.size())); ASR::stmt_t *print_close_bracket = ASRUtils::STMT( - ASR::make_Print_t(al, loc, v3.p, v3.size(), - sep_expr, end_expr)); + ASRUtils::make_print_t_util(al, loc, v3.p, v3.size())); Vec if_body; if_body.reserve(al, 1); @@ -193,11 +172,11 @@ class PrintListTupleVisitor ASRUtils::EXPR(ASR::make_IntegerConstant_t( al, loc, 1, int_type)); if (ASR::is_a(*listC->m_type)){ - print_list_helper(list_item, nullptr, empty_str, loc); + print_list_helper(list_item, loc); loop_body.from_pointer_n_copy(al, print_pass_result_tmp.p, print_pass_result_tmp.size()); print_pass_result_tmp.n = 0; } else if (ASR::is_a(*listC->m_type)) { - print_tuple_helper(list_item, nullptr, empty_str, loc); + print_tuple_helper(list_item, loc); loop_body.from_pointer_n_copy(al, print_pass_result_tmp.p, print_pass_result_tmp.size()); print_pass_result_tmp.n = 0; } else { @@ -211,33 +190,27 @@ class PrintListTupleVisitor al, loc, nullptr, loop_head, loop_body.p, loop_body.size(), nullptr, 0)); { - print_pass_result_tmp.push_back(al, assign_stmt); print_pass_result_tmp.push_back(al, print_open_bracket); print_pass_result_tmp.push_back(al, loop); print_pass_result_tmp.push_back(al, print_close_bracket); } } - void print_tuple_helper(ASR::expr_t *tup_expr, ASR::expr_t *sep_expr, - ASR::expr_t *end_expr, const Location &loc) { + void print_tuple_helper(ASR::expr_t *tup_expr, const Location &loc) { ASR::Tuple_t *tup = ASR::down_cast(ASRUtils::expr_type(tup_expr)); ASR::ttype_t *int_type = ASRUtils::TYPE( ASR::make_Integer_t(al, loc, 4)); - ASR::ttype_t *str_type_len_0 = ASRUtils::TYPE(ASR::make_Character_t( - al, loc, 1, 0, nullptr)); - ASR::ttype_t *str_type_len_1 = ASRUtils::TYPE(ASR::make_Character_t( - al, loc, 1, 1, nullptr)); - ASR::ttype_t *str_type_len_2 = ASRUtils::TYPE(ASR::make_Character_t( - al, loc, 1, 2, nullptr)); + ASR::ttype_t *str_type_len_1 = ASRUtils::TYPE(ASR::make_String_t( + al, loc, 1, 1, nullptr, ASR::string_physical_typeType::PointerString)); + ASR::ttype_t *str_type_len_2 = ASRUtils::TYPE(ASR::make_String_t( + al, loc, 1, 2, nullptr, ASR::string_physical_typeType::PointerString)); ASR::expr_t *comma_space = ASRUtils::EXPR(ASR::make_StringConstant_t( al, loc, s2c(al, ", "), str_type_len_2)); ASR::expr_t *single_quote = ASRUtils::EXPR(ASR::make_StringConstant_t( al, loc, s2c(al, "'"), str_type_len_1)); - ASR::expr_t *empty_str = ASRUtils::EXPR(ASR::make_StringConstant_t( - al, loc, s2c(al, ""), str_type_len_0)); ASR::expr_t *open_bracket = ASRUtils::EXPR(ASR::make_StringConstant_t( al, loc, s2c(al, "("), str_type_len_1)); @@ -258,14 +231,11 @@ class PrintListTupleVisitor Vec tmp_vec; tmp_vec.reserve(al, 3); ASR::stmt_t *print_open_bracket = ASRUtils::STMT( - ASR::make_Print_t(al, loc, v1.p, v1.size(), - nullptr, empty_str)); + ASRUtils::make_print_t_util(al, loc, v1.p, v1.size())); ASR::stmt_t *print_comma_space = ASRUtils::STMT( - ASR::make_Print_t(al, loc, v4.p, v4.size(), - empty_str, empty_str)); + ASRUtils::make_print_t_util(al, loc, v4.p, v4.size())); ASR::stmt_t *print_close_bracket = ASRUtils::STMT( - ASR::make_Print_t(al, loc, v3.p, v3.size(), - sep_expr, end_expr)); + ASRUtils::make_print_t_util(al, loc, v3.p, v3.size())); tmp_vec.push_back(al, print_open_bracket); for (size_t i=0; in_type; i++) { @@ -275,21 +245,21 @@ class PrintListTupleVisitor tup_iter_var, tup->m_type[i], nullptr)); if (ASR::is_a(*tup->m_type[i])) { print_pass_result_tmp.n = 0; - print_list_helper(tup_item, nullptr, empty_str, loc); + print_list_helper(tup_item, loc); for (size_t j=0; j(*tup->m_type[i])) { print_pass_result_tmp.n = 0; - print_tuple_helper(tup_item, nullptr, empty_str, loc); + print_tuple_helper(tup_item, loc); for (size_t j=0; j v2; - if (ASR::is_a(*tup->m_type[i])) { + if (ASR::is_a(*tup->m_type[i])) { v2.reserve(al, 3); v2.push_back(al, single_quote); v2.push_back(al, tup_item); @@ -299,8 +269,7 @@ class PrintListTupleVisitor v2.push_back(al, tup_item); } ASR::stmt_t *print_item = ASRUtils::STMT( - ASR::make_Print_t(al, loc, v2.p, v2.size(), - empty_str, empty_str)); + ASRUtils::make_print_t_util(al, loc, v2.p, v2.size())); tmp_vec.push_back(al, print_item); } if (i != tup->n_type - 1) { @@ -312,14 +281,17 @@ class PrintListTupleVisitor } void visit_Print(const ASR::Print_t &x) { + if(ASR::is_a(*x.m_text)){ + visit_StringFormat(*ASR::down_cast(x.m_text)); + } else { + remove_original_stmt = false; + } + } + void visit_StringFormat(const ASR::StringFormat_t &x) { std::vector print_tmp; - ASR::ttype_t *str_type_len_1 = ASRUtils::TYPE(ASR::make_Character_t( - al, x.base.base.loc, 1, 1, nullptr)); - ASR::expr_t *space = ASRUtils::EXPR(ASR::make_StringConstant_t( - al, x.base.base.loc, s2c(al, " "), str_type_len_1)); - for (size_t i=0; i(*ASRUtils::expr_type(x.m_values[i])) || - ASR::is_a(*ASRUtils::expr_type(x.m_values[i]))) { + for (size_t i=0; i(*ASRUtils::expr_type(x.m_args[i])) || + ASR::is_a(*ASRUtils::expr_type(x.m_args[i]))) { if (!print_tmp.empty()) { Vec tmp_vec; ASR::stmt_t *print_stmt; @@ -327,36 +299,30 @@ class PrintListTupleVisitor for (auto &e: print_tmp) { tmp_vec.push_back(al, e); } - if (x.m_separator) { - print_stmt = ASRUtils::STMT(ASR::make_Print_t(al, - x.base.base.loc, tmp_vec.p, tmp_vec.size(), - x.m_separator, x.m_separator)); - } else { - print_stmt = ASRUtils::STMT(ASR::make_Print_t(al, - x.base.base.loc, tmp_vec.p, tmp_vec.size(), - x.m_separator, space)); - } + print_stmt = ASRUtils::STMT(ASRUtils::make_print_t_util(al, + x.base.base.loc, tmp_vec.p, tmp_vec.size())); print_tmp.clear(); pass_result.push_back(al, print_stmt); } - if (ASR::is_a(*ASRUtils::expr_type(x.m_values[i]))){ - if (i == x.n_values - 1) { - print_list_helper(x.m_values[i], x.m_separator, x.m_end, x.base.base.loc); + if (ASR::is_a(*ASRUtils::expr_type(x.m_args[i]))){ + if (i == x.n_args - 1) { + print_list_helper(x.m_args[i], x.base.base.loc); } else { - print_list_helper(x.m_values[i], x.m_separator, (x.m_separator ? x.m_separator : space), x.base.base.loc); + print_list_helper(x.m_args[i], x.base.base.loc); } } else { - if (i == x.n_values - 1) { - print_tuple_helper(x.m_values[i], x.m_separator, x.m_end, x.base.base.loc); + if (i == x.n_args - 1) { + print_tuple_helper(x.m_args[i],x.base.base.loc); } else { - print_tuple_helper(x.m_values[i], x.m_separator, (x.m_separator ? x.m_separator : space), x.base.base.loc); + print_tuple_helper(x.m_args[i], x.base.base.loc); } } - for (size_t j=0; j(&x); + x_casted->m_args = tmp_vec.p; + x_casted->n_args = tmp_vec.size(); + remove_original_stmt =false; } } }; diff --git a/src/libasr/pass/print_struct_type.cpp b/src/libasr/pass/print_struct_type.cpp index 79b083628d..5999370a3f 100644 --- a/src/libasr/pass/print_struct_type.cpp +++ b/src/libasr/pass/print_struct_type.cpp @@ -55,8 +55,15 @@ class PrintStructVisitor : public PassUtils::PassVisitor *ASRUtils::expr_type(value)) ) \ bool is_struct_type_present = false; - for( size_t i = 0; i < x.n_values; i++ ) { - is_struct_type(x.m_values[i]) + ASR::StringFormat_t* fmt; + if(ASR::is_a(*x.m_text)){ + fmt = (ASR::down_cast(x.m_text)); + } else { + return; + } + + for( size_t i = 0; i < (fmt->n_args); i++ ) { + is_struct_type(fmt->m_args[i]) { is_struct_type_present = true; @@ -73,8 +80,8 @@ class PrintStructVisitor : public PassUtils::PassVisitor */ Vec new_values; new_values.reserve(al, 1); - for( size_t i = 0; i < x.n_values; i++ ) { - ASR::expr_t* x_m_value = x.m_values[i]; + for( size_t i = 0; i < fmt->n_args; i++ ) { + ASR::expr_t* x_m_value = fmt->m_args[i]; if( ASR::is_a(*x_m_value) ) { x_m_value = ASR::down_cast(x_m_value)->m_overloaded; } @@ -92,14 +99,15 @@ class PrintStructVisitor : public PassUtils::PassVisitor } else { - new_values.push_back(al, x.m_values[i]); + new_values.push_back(al, x_m_value); } } - - ASR::Print_t& xx = const_cast(x); - xx.m_values = new_values.p; - xx.n_values = new_values.size(); + fmt->m_args = new_values.p; + fmt->n_args = new_values.size(); + // ASR::Print_t& xx = const_cast(x); + // xx.m_values = new_values.p; + // xx.n_values = new_values.size(); } }; diff --git a/src/libasr/pass/promote_allocatable_to_nonallocatable.cpp b/src/libasr/pass/promote_allocatable_to_nonallocatable.cpp index d7aba6ce3a..bbb1abbba1 100644 --- a/src/libasr/pass/promote_allocatable_to_nonallocatable.cpp +++ b/src/libasr/pass/promote_allocatable_to_nonallocatable.cpp @@ -66,11 +66,29 @@ class IsAllocatedCalled: public ASR::CallReplacerOnExpressionsVisitor(*expr) ) { \ + ASR::ArraySize_t* array_size_t = ASR::down_cast(expr); \ + if( ASRUtils::is_pointer(ASRUtils::expr_type(array_size_t->m_v)) ) { \ + return true; \ + } \ + } \ + + check_pointer_in_array_size(m_dims[i].m_start) + check_pointer_in_array_size(m_dims[i].m_length) + + } + + return false; + } + void visit_Allocate(const ASR::Allocate_t& x) { for( size_t i = 0; i < x.n_args; i++ ) { ASR::alloc_arg_t alloc_arg = x.m_args[i]; if( !ASRUtils::is_dimension_dependent_only_on_arguments( - alloc_arg.m_dims, alloc_arg.n_dims) ) { + alloc_arg.m_dims, alloc_arg.n_dims) || + is_array_size_called_on_pointer(alloc_arg.m_dims, alloc_arg.n_dims) ) { if( ASR::is_a(*alloc_arg.m_a) ) { scope2var[current_scope].push_back( ASR::down_cast(alloc_arg.m_a)->m_v); @@ -207,7 +225,8 @@ class FixArrayPhysicalCast: public ASR::BaseExprReplacer { ASR::BaseExprReplacer::replace_FunctionCall(x); ASR::expr_t* call = ASRUtils::EXPR(ASRUtils::make_FunctionCall_t_util( al, x->base.base.loc, x->m_name, x->m_original_name, x->m_args, - x->n_args, x->m_type, x->m_value, x->m_dt)); + x->n_args, x->m_type, x->m_value, x->m_dt, + ASRUtils::get_class_proc_nopass_val((*x).m_name))); ASR::FunctionCall_t* function_call = ASR::down_cast(call); x->m_args = function_call->m_args; x->n_args = function_call->n_args; diff --git a/src/libasr/pass/python_bind.cpp b/src/libasr/pass/python_bind.cpp index 598ea3cd1b..b502418e8f 100644 --- a/src/libasr/pass/python_bind.cpp +++ b/src/libasr/pass/python_bind.cpp @@ -41,7 +41,7 @@ ASR::expr_t *cpython_to_native(Allocator &al, ASR::expr_t *exp, ASR::ttype_t *ty Vec args_PyLong_AsUnsignedLongLong; args_PyLong_AsUnsignedLongLong.reserve(al, 1); args_PyLong_AsUnsignedLongLong.push_back(al, {f.base.base.loc, exp}); - conv_result = ASRUtils::EXPR(ASR::make_Cast_t(al, f.base.base.loc, + conv_result = ASRUtils::EXPR(ASR::make_Cast_t(al, f.base.base.loc, ASRUtils::EXPR(ASRUtils::make_FunctionCall_t_util(al, f.base.base.loc, sym_PyLong_AsUnsignedLongLong, nullptr, args_PyLong_AsUnsignedLongLong.p, args_PyLong_AsUnsignedLongLong.n, u8_type, nullptr, nullptr)), @@ -61,12 +61,12 @@ ASR::expr_t *cpython_to_native(Allocator &al, ASR::expr_t *exp, ASR::ttype_t *ty Vec args_PyObject_IsTrue; args_PyObject_IsTrue.reserve(al, 1); args_PyObject_IsTrue.push_back(al, {f.base.base.loc, exp}); - conv_result = ASRUtils::EXPR(ASR::make_Cast_t(al, f.base.base.loc, + conv_result = ASRUtils::EXPR(ASR::make_Cast_t(al, f.base.base.loc, ASRUtils::EXPR(ASRUtils::make_FunctionCall_t_util(al, f.base.base.loc, sym_PyObject_IsTrue, nullptr, args_PyObject_IsTrue.p, args_PyObject_IsTrue.n, i4_type, nullptr, nullptr)), ASR::IntegerToLogical, type, nullptr)); - } else if (type->type == ASR::ttypeType::Character) { + } else if (type->type == ASR::ttypeType::String) { ASR::symbol_t *sym_PyUnicode_AsUTF8AndSize = f.m_symtab->resolve_symbol("PyUnicode_AsUTF8AndSize"); Vec args_PyUnicode_AsUTF8AndSize; args_PyUnicode_AsUTF8AndSize.reserve(al, 1); @@ -78,7 +78,7 @@ ASR::expr_t *cpython_to_native(Allocator &al, ASR::expr_t *exp, ASR::ttype_t *ty sym_PyUnicode_AsUTF8AndSize, nullptr, args_PyUnicode_AsUTF8AndSize.p, args_PyUnicode_AsUTF8AndSize.n, i1ptr_type, nullptr, nullptr)), ASR::RealToReal, type, nullptr)); - + } else if (type->type == ASR::ttypeType::List) { ASR::List_t *list = ASR::down_cast(type); Str s; @@ -91,7 +91,7 @@ ASR::expr_t *cpython_to_native(Allocator &al, ASR::expr_t *exp, ASR::ttype_t *ty s.from_str(al, p); ASR::asr_t *pSize = ASR::make_Variable_t(al, f.base.base.loc, f.m_symtab, s.c_str(al), nullptr, 0, ASRUtils::intent_local, nullptr, nullptr, ASR::storage_typeType::Default, i8_type, - nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false); + nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false, false); ASR::expr_t *pSize_ref = ASRUtils::EXPR(ASR::make_Var_t(al, f.base.base.loc, ASR::down_cast(pSize))); f.m_symtab->add_symbol(p, ASR::down_cast(pSize)); @@ -99,23 +99,23 @@ ASR::expr_t *cpython_to_native(Allocator &al, ASR::expr_t *exp, ASR::ttype_t *ty ASRUtils::EXPR(ASRUtils::make_FunctionCall_t_util(al, f.base.base.loc, sym_PyList_Size, nullptr, args_PyList_Size.p, args_PyList_Size.n, i8_type, nullptr, nullptr)), nullptr))); - + p = "_i" + std::to_string(get_random_number()); s.from_str(al, p); ASR::asr_t *pI = ASR::make_Variable_t(al, f.base.base.loc, f.m_symtab, s.c_str(al), nullptr, 0, ASRUtils::intent_local, nullptr, nullptr, ASR::storage_typeType::Default, i8_type, - nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false); + nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false, false); ASR::expr_t *pI_ref = ASRUtils::EXPR(ASR::make_Var_t(al, f.base.base.loc, ASR::down_cast(pI))); f.m_symtab->add_symbol(p, ASR::down_cast(pI)); body.push_back(al, ASRUtils::STMT(ASR::make_Assignment_t(al, f.base.base.loc, pI_ref, ASRUtils::EXPR(ASR::make_IntegerConstant_t(al, f.base.base.loc, 0, i8_type)), nullptr))); - + p = "_result" + std::to_string(get_random_number()); s.from_str(al, p); ASR::asr_t *pResult = ASR::make_Variable_t(al, f.base.base.loc, f.m_symtab, s.c_str(al), nullptr, 0, ASRUtils::intent_local, nullptr, nullptr, ASR::storage_typeType::Default, type, - nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false); + nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false, false); ASR::expr_t *pResult_ref = ASRUtils::EXPR(ASR::make_Var_t(al, f.base.base.loc, ASR::down_cast(pResult))); f.m_symtab->add_symbol(p, ASR::down_cast(pResult)); @@ -124,14 +124,14 @@ ASR::expr_t *cpython_to_native(Allocator &al, ASR::expr_t *exp, ASR::ttype_t *ty Vec while_body; while_body.reserve(al, 2); - + ASR::symbol_t *sym_PyList_GetItem = f.m_symtab->resolve_symbol("PyList_GetItem"); Vec args_PyList_GetItem; args_PyList_GetItem.reserve(al, 2); args_PyList_GetItem.push_back(al, {f.base.base.loc, exp}); args_PyList_GetItem.push_back(al, {f.base.base.loc, pI_ref}); - while_body.push_back(al, ASRUtils::STMT(ASR::make_ListAppend_t(al, f.base.base.loc, pResult_ref, + while_body.push_back(al, ASRUtils::STMT(ASR::make_ListAppend_t(al, f.base.base.loc, pResult_ref, cpython_to_native(al, ASRUtils::EXPR(ASRUtils::make_FunctionCall_t_util(al, f.base.base.loc, sym_PyList_GetItem, nullptr, args_PyList_GetItem.p, args_PyList_GetItem.n, ptr_t, nullptr, nullptr)), list->m_type, f, while_body) @@ -149,7 +149,7 @@ ASR::expr_t *cpython_to_native(Allocator &al, ASR::expr_t *exp, ASR::ttype_t *ty ASRUtils::EXPR(ASR::make_IntegerCompare_t(al, f.base.base.loc, pI_ref, ASR::cmpopType::Lt, pSize_ref, i1_type, nullptr)), while_body.p, while_body.n, nullptr, 0))); - + conv_result = pResult_ref; } else if (type->type == ASR::ttypeType::Tuple) { @@ -160,7 +160,7 @@ ASR::expr_t *cpython_to_native(Allocator &al, ASR::expr_t *exp, ASR::ttype_t *ty s.from_str(al, p); ASR::asr_t *pResult = ASR::make_Variable_t(al, f.base.base.loc, f.m_symtab, s.c_str(al), nullptr, 0, ASRUtils::intent_local, nullptr, nullptr, ASR::storage_typeType::Default, type, - nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false); + nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false, false); ASR::expr_t *pResult_ref = ASRUtils::EXPR(ASR::make_Var_t(al, f.base.base.loc, ASR::down_cast(pResult))); f.m_symtab->add_symbol(p, ASR::down_cast(pResult)); @@ -194,7 +194,7 @@ ASR::expr_t *cpython_to_native(Allocator &al, ASR::expr_t *exp, ASR::ttype_t *ty s.from_str(al, p); ASR::asr_t *pResult = ASR::make_Variable_t(al, f.base.base.loc, f.m_symtab, s.c_str(al), nullptr, 0, ASRUtils::intent_local, nullptr, nullptr, ASR::storage_typeType::Default, type, - nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false); + nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false, false); ASR::expr_t *pResult_ref = ASRUtils::EXPR(ASR::make_Var_t(al, f.base.base.loc, ASR::down_cast(pResult))); f.m_symtab->add_symbol(p, ASR::down_cast(pResult)); @@ -202,7 +202,7 @@ ASR::expr_t *cpython_to_native(Allocator &al, ASR::expr_t *exp, ASR::ttype_t *ty body.push_back(al, ASRUtils::STMT(ASR::make_Assignment_t(al, f.base.base.loc, pResult_ref, ASRUtils::EXPR(ASR::make_SetConstant_t(al, f.base.base.loc, nullptr, 0, type)), nullptr))); - + ASR::symbol_t *sym_PySet_Size = f.m_symtab->resolve_symbol("PySet_Size"); Vec args_PySet_Size; args_PySet_Size.reserve(al, 1); @@ -211,7 +211,7 @@ ASR::expr_t *cpython_to_native(Allocator &al, ASR::expr_t *exp, ASR::ttype_t *ty s.from_str(al, p); ASR::asr_t *pSize = ASR::make_Variable_t(al, f.base.base.loc, f.m_symtab, s.c_str(al), nullptr, 0, ASRUtils::intent_local, nullptr, nullptr, ASR::storage_typeType::Default, i8_type, - nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false); + nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false, false); ASR::expr_t *pSize_ref = ASRUtils::EXPR(ASR::make_Var_t(al, f.base.base.loc, ASR::down_cast(pSize))); f.m_symtab->add_symbol(p, ASR::down_cast(pSize)); @@ -224,7 +224,7 @@ ASR::expr_t *cpython_to_native(Allocator &al, ASR::expr_t *exp, ASR::ttype_t *ty s.from_str(al, p); ASR::asr_t *pI = ASR::make_Variable_t(al, f.base.base.loc, f.m_symtab, s.c_str(al), nullptr, 0, ASRUtils::intent_local, nullptr, nullptr, ASR::storage_typeType::Default, i8_type, - nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false); + nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false, false); ASR::expr_t *pI_ref = ASRUtils::EXPR(ASR::make_Var_t(al, f.base.base.loc, ASR::down_cast(pI))); f.m_symtab->add_symbol(p, ASR::down_cast(pI)); @@ -235,7 +235,7 @@ ASR::expr_t *cpython_to_native(Allocator &al, ASR::expr_t *exp, ASR::ttype_t *ty s.from_str(al, p); ASR::asr_t *pIterator = ASR::make_Variable_t(al, f.base.base.loc, f.m_symtab, s.c_str(al), nullptr, 0, ASRUtils::intent_local, nullptr, nullptr, ASR::storage_typeType::Default, ptr_t, - nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false); + nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false, false); ASR::expr_t *pIterator_ref = ASRUtils::EXPR(ASR::make_Var_t(al, f.base.base.loc, ASR::down_cast(pIterator))); f.m_symtab->add_symbol(p, ASR::down_cast(pIterator)); @@ -244,7 +244,7 @@ ASR::expr_t *cpython_to_native(Allocator &al, ASR::expr_t *exp, ASR::ttype_t *ty Vec args_PyObject_GetIter; args_PyObject_GetIter.reserve(al, 1); args_PyObject_GetIter.push_back(al, {f.base.base.loc, exp}); - body.push_back(al, + body.push_back(al, ASRUtils::STMT(ASR::make_Assignment_t(al, f.base.base.loc, pIterator_ref, ASRUtils::EXPR(ASRUtils::make_FunctionCall_t_util(al, f.base.base.loc, sym_PyObject_GetIter, nullptr, args_PyObject_GetIter.p, args_PyObject_GetIter.n, ptr_t, nullptr, nullptr)), nullptr))); @@ -253,11 +253,11 @@ ASR::expr_t *cpython_to_native(Allocator &al, ASR::expr_t *exp, ASR::ttype_t *ty s.from_str(al, p); ASR::asr_t *pItem = ASR::make_Variable_t(al, f.base.base.loc, f.m_symtab, s.c_str(al), nullptr, 0, ASRUtils::intent_local, nullptr, nullptr, ASR::storage_typeType::Default, ptr_t, - nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false); + nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false, false); ASR::expr_t *pItem_ref = ASRUtils::EXPR(ASR::make_Var_t(al, f.base.base.loc, ASR::down_cast(pItem))); f.m_symtab->add_symbol(p, ASR::down_cast(pItem)); - + Vec while_body; while_body.reserve(al, 3); @@ -267,7 +267,7 @@ ASR::expr_t *cpython_to_native(Allocator &al, ASR::expr_t *exp, ASR::ttype_t *ty ASRUtils::EXPR(ASR::make_IntegerBinOp_t(al, f.base.base.loc, pI_ref, ASR::binopType::Add, ASRUtils::EXPR(ASR::make_IntegerConstant_t(al, f.base.base.loc, 1, i8_type)), i8_type, nullptr)), nullptr))); - + ASR::symbol_t *sym_PyIter_Next = f.m_symtab->resolve_symbol("PyIter_Next"); // TODO: decrement Vec args_PyIter_Next; args_PyIter_Next.reserve(al, 1); @@ -288,7 +288,7 @@ ASR::expr_t *cpython_to_native(Allocator &al, ASR::expr_t *exp, ASR::ttype_t *ty static_cast(ASRUtils::IntrinsicElementalFunctions::SetAdd), args_Set_add.p, args_Set_add.n, 0, nullptr, nullptr))))); - body.push_back(al, ASRUtils::STMT(ASR::make_WhileLoop_t(al, f.base.base.loc, nullptr, + body.push_back(al, ASRUtils::STMT(ASR::make_WhileLoop_t(al, f.base.base.loc, nullptr, ASRUtils::EXPR(ASR::make_IntegerCompare_t(al, f.base.base.loc, pI_ref, ASR::cmpopType::Lt, pSize_ref, i1_type, nullptr)), while_body.p, while_body.n, nullptr, 0))); @@ -303,7 +303,7 @@ ASR::expr_t *cpython_to_native(Allocator &al, ASR::expr_t *exp, ASR::ttype_t *ty s.from_str(al, p); ASR::asr_t *pResult = ASR::make_Variable_t(al, f.base.base.loc, f.m_symtab, s.c_str(al), nullptr, 0, ASRUtils::intent_local, nullptr, nullptr, ASR::storage_typeType::Default, type, - nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false); + nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false, false); ASR::expr_t *pResult_ref = ASRUtils::EXPR(ASR::make_Var_t(al, f.base.base.loc, ASR::down_cast(pResult))); f.m_symtab->add_symbol(p, ASR::down_cast(pResult)); @@ -311,7 +311,7 @@ ASR::expr_t *cpython_to_native(Allocator &al, ASR::expr_t *exp, ASR::ttype_t *ty body.push_back(al, ASRUtils::STMT(ASR::make_Assignment_t(al, f.base.base.loc, pResult_ref, ASRUtils::EXPR(ASR::make_DictConstant_t(al, f.base.base.loc, nullptr, 0, nullptr, 0, type)), nullptr))); - + ASR::symbol_t *sym_PyDict_Size = f.m_symtab->resolve_symbol("PyDict_Size"); Vec args_PyDict_Size; args_PyDict_Size.reserve(al, 1); @@ -320,7 +320,7 @@ ASR::expr_t *cpython_to_native(Allocator &al, ASR::expr_t *exp, ASR::ttype_t *ty s.from_str(al, p); ASR::asr_t *pSize = ASR::make_Variable_t(al, f.base.base.loc, f.m_symtab, s.c_str(al), nullptr, 0, ASRUtils::intent_local, nullptr, nullptr, ASR::storage_typeType::Default, i8_type, - nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false); + nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false, false); ASR::expr_t *pSize_ref = ASRUtils::EXPR(ASR::make_Var_t(al, f.base.base.loc, ASR::down_cast(pSize))); f.m_symtab->add_symbol(p, ASR::down_cast(pSize)); @@ -333,7 +333,7 @@ ASR::expr_t *cpython_to_native(Allocator &al, ASR::expr_t *exp, ASR::ttype_t *ty s.from_str(al, p); ASR::asr_t *pI = ASR::make_Variable_t(al, f.base.base.loc, f.m_symtab, s.c_str(al), nullptr, 0, ASRUtils::intent_local, nullptr, nullptr, ASR::storage_typeType::Default, i8_type, - nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false); + nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false, false); ASR::expr_t *pI_ref = ASRUtils::EXPR(ASR::make_Var_t(al, f.base.base.loc, ASR::down_cast(pI))); f.m_symtab->add_symbol(p, ASR::down_cast(pI)); @@ -344,7 +344,7 @@ ASR::expr_t *cpython_to_native(Allocator &al, ASR::expr_t *exp, ASR::ttype_t *ty s.from_str(al, p); ASR::asr_t *pIterator = ASR::make_Variable_t(al, f.base.base.loc, f.m_symtab, s.c_str(al), nullptr, 0, ASRUtils::intent_local, nullptr, nullptr, ASR::storage_typeType::Default, ptr_t, - nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false); + nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false, false); ASR::expr_t *pIterator_ref = ASRUtils::EXPR(ASR::make_Var_t(al, f.base.base.loc, ASR::down_cast(pIterator))); f.m_symtab->add_symbol(p, ASR::down_cast(pIterator)); @@ -353,7 +353,7 @@ ASR::expr_t *cpython_to_native(Allocator &al, ASR::expr_t *exp, ASR::ttype_t *ty Vec args_PyObject_GetIter; args_PyObject_GetIter.reserve(al, 1); args_PyObject_GetIter.push_back(al, {f.base.base.loc, exp}); - body.push_back(al, + body.push_back(al, ASRUtils::STMT(ASR::make_Assignment_t(al, f.base.base.loc, pIterator_ref, ASRUtils::EXPR(ASRUtils::make_FunctionCall_t_util(al, f.base.base.loc, sym_PyObject_GetIter, nullptr, args_PyObject_GetIter.p, args_PyObject_GetIter.n, ptr_t, nullptr, nullptr)), nullptr))); @@ -362,11 +362,11 @@ ASR::expr_t *cpython_to_native(Allocator &al, ASR::expr_t *exp, ASR::ttype_t *ty s.from_str(al, p); ASR::asr_t *pKey = ASR::make_Variable_t(al, f.base.base.loc, f.m_symtab, s.c_str(al), nullptr, 0, ASRUtils::intent_local, nullptr, nullptr, ASR::storage_typeType::Default, ptr_t, - nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false); + nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false, false); ASR::expr_t *pKey_ref = ASRUtils::EXPR(ASR::make_Var_t(al, f.base.base.loc, ASR::down_cast(pKey))); f.m_symtab->add_symbol(p, ASR::down_cast(pKey)); - + Vec while_body; while_body.reserve(al, 3); @@ -376,7 +376,7 @@ ASR::expr_t *cpython_to_native(Allocator &al, ASR::expr_t *exp, ASR::ttype_t *ty ASRUtils::EXPR(ASR::make_IntegerBinOp_t(al, f.base.base.loc, pI_ref, ASR::binopType::Add, ASRUtils::EXPR(ASR::make_IntegerConstant_t(al, f.base.base.loc, 1, i8_type)), i8_type, nullptr)), nullptr))); - + ASR::symbol_t *sym_PyIter_Next = f.m_symtab->resolve_symbol("PyIter_Next"); // TODO: decrement Vec args_PyIter_Next; args_PyIter_Next.reserve(al, 1); @@ -400,7 +400,7 @@ ASR::expr_t *cpython_to_native(Allocator &al, ASR::expr_t *exp, ASR::ttype_t *ty nullptr)), dict->m_value_type, f, while_body)))); - body.push_back(al, ASRUtils::STMT(ASR::make_WhileLoop_t(al, f.base.base.loc, nullptr, + body.push_back(al, ASRUtils::STMT(ASR::make_WhileLoop_t(al, f.base.base.loc, nullptr, ASRUtils::EXPR(ASR::make_IntegerCompare_t(al, f.base.base.loc, pI_ref, ASR::cmpopType::Lt, pSize_ref, i1_type, nullptr)), while_body.p, while_body.n, nullptr, 0))); @@ -464,7 +464,7 @@ ASR::expr_t *native_to_cpython(Allocator &al, ASR::expr_t *exp, const ASR::Funct ASR::cast_kindType::RealToReal, f8_type, nullptr))}); conv_result = ASRUtils::EXPR(ASRUtils::make_FunctionCall_t_util(al, f.base.base.loc, sym_PyFloat_FromDouble, nullptr, args_PyFloat_FromDouble.p, args_PyFloat_FromDouble.n, ptr_t, nullptr, nullptr)); - } else if (type->type == ASR::ttypeType::Character) { + } else if (type->type == ASR::ttypeType::String) { ASR::symbol_t *sym_PyUnicode_FromString = f.m_symtab->resolve_symbol("PyUnicode_FromString"); Vec args_PyUnicode_FromString; args_PyUnicode_FromString.reserve(al, 1); @@ -485,12 +485,12 @@ ASR::expr_t *native_to_cpython(Allocator &al, ASR::expr_t *exp, const ASR::Funct s.from_str(al, p); ASR::asr_t *pArgs = ASR::make_Variable_t(al, f.base.base.loc, f.m_symtab, s.c_str(al), nullptr, 0, ASRUtils::intent_local, nullptr, nullptr, ASR::storage_typeType::Default, ptr_t, - nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false); + nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false, false); ASR::expr_t *pArgs_ref = ASRUtils::EXPR(ASR::make_Var_t(al, f.base.base.loc, ASR::down_cast(pArgs))); f.m_symtab->add_symbol(p, ASR::down_cast(pArgs)); body.push_back(al, ASRUtils::STMT( - ASR::make_Assignment_t(al, f.base.base.loc, pArgs_ref, + ASR::make_Assignment_t(al, f.base.base.loc, pArgs_ref, ASRUtils::EXPR(ASRUtils::make_FunctionCall_t_util(al, f.base.base.loc, sym_PyTuple_New, nullptr, args_PyTuple_New.p, args_PyTuple_New.n, ptr_t, nullptr, nullptr)), nullptr))); conv_result = pArgs_ref; @@ -502,7 +502,7 @@ ASR::expr_t *native_to_cpython(Allocator &al, ASR::expr_t *exp, const ASR::Funct args_PyTuple_SetItem.push_back(al, {f.base.base.loc, pArgs_ref}); ASR::expr_t *n = ASRUtils::EXPR(ASR::make_IntegerConstant_t(al, f.base.base.loc, i, i4_type)); args_PyTuple_SetItem.push_back(al, {f.base.base.loc, n}); - args_PyTuple_SetItem.push_back(al, {f.base.base.loc, native_to_cpython(al, + args_PyTuple_SetItem.push_back(al, {f.base.base.loc, native_to_cpython(al, ASRUtils::EXPR(ASR::make_TupleItem_t(al, f.base.base.loc, exp, n, tuple->m_type[i], nullptr)), @@ -511,7 +511,7 @@ ASR::expr_t *native_to_cpython(Allocator &al, ASR::expr_t *exp, const ASR::Funct s.from_str(al, p); ASR::asr_t *pA = ASR::make_Variable_t(al, f.base.base.loc, f.m_symtab, s.c_str(al), nullptr, 0, ASRUtils::intent_local, nullptr, nullptr, ASR::storage_typeType::Default, i4_type, - nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false); + nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false, false); ASR::expr_t *pA_ref = ASRUtils::EXPR(ASR::make_Var_t(al, f.base.base.loc, ASR::down_cast(pA))); f.m_symtab->add_symbol(p, ASR::down_cast(pA)); @@ -533,12 +533,12 @@ ASR::expr_t *native_to_cpython(Allocator &al, ASR::expr_t *exp, const ASR::Funct s.from_str(al, p); ASR::asr_t *pArgs = ASR::make_Variable_t(al, f.base.base.loc, f.m_symtab, s.c_str(al), nullptr, 0, ASRUtils::intent_local, nullptr, nullptr, ASR::storage_typeType::Default, ptr_t, - nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false); + nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false, false); ASR::expr_t *pArgs_ref = ASRUtils::EXPR(ASR::make_Var_t(al, f.base.base.loc, ASR::down_cast(pArgs))); f.m_symtab->add_symbol(p, ASR::down_cast(pArgs)); body.push_back(al, ASRUtils::STMT( - ASR::make_Assignment_t(al, f.base.base.loc, pArgs_ref, + ASR::make_Assignment_t(al, f.base.base.loc, pArgs_ref, ASRUtils::EXPR(ASRUtils::make_FunctionCall_t_util(al, f.base.base.loc, sym_PyList_New, nullptr, args_PyList_New.p, args_PyList_New.n, ptr_t, nullptr, nullptr)), nullptr))); conv_result = pArgs_ref; @@ -547,7 +547,7 @@ ASR::expr_t *native_to_cpython(Allocator &al, ASR::expr_t *exp, const ASR::Funct s.from_str(al, p); ASR::asr_t *pSize = ASR::make_Variable_t(al, f.base.base.loc, f.m_symtab, s.c_str(al), nullptr, 0, ASRUtils::intent_local, nullptr, nullptr, ASR::storage_typeType::Default, i4_type, - nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false); + nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false, false); ASR::expr_t *pSize_ref = ASRUtils::EXPR(ASR::make_Var_t(al, f.base.base.loc, ASR::down_cast(pSize))); f.m_symtab->add_symbol(p, ASR::down_cast(pSize)); @@ -558,7 +558,7 @@ ASR::expr_t *native_to_cpython(Allocator &al, ASR::expr_t *exp, const ASR::Funct s.from_str(al, p); ASR::asr_t *pI = ASR::make_Variable_t(al, f.base.base.loc, f.m_symtab, s.c_str(al), nullptr, 0, ASRUtils::intent_local, nullptr, nullptr, ASR::storage_typeType::Default, i4_type, - nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false); + nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false, false); ASR::expr_t *pI_ref = ASRUtils::EXPR(ASR::make_Var_t(al, f.base.base.loc, ASR::down_cast(pI))); f.m_symtab->add_symbol(p, ASR::down_cast(pI)); @@ -570,20 +570,20 @@ ASR::expr_t *native_to_cpython(Allocator &al, ASR::expr_t *exp, const ASR::Funct s.from_str(al, p); ASR::asr_t *pItem = ASR::make_Variable_t(al, f.base.base.loc, f.m_symtab, s.c_str(al), nullptr, 0, ASRUtils::intent_local, nullptr, nullptr, ASR::storage_typeType::Default, list->m_type, - nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false); + nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false, false); ASR::expr_t *pItem_ref = ASRUtils::EXPR(ASR::make_Var_t(al, f.base.base.loc, ASR::down_cast(pItem))); f.m_symtab->add_symbol(p, ASR::down_cast(pItem)); - + Vec while_body; while_body.reserve(al, 3); - + while_body.push_back(al, ASRUtils::STMT( - ASR::make_Assignment_t(al, f.base.base.loc, + ASR::make_Assignment_t(al, f.base.base.loc, pItem_ref, ASRUtils::EXPR(ASR::make_ListItem_t(al, f.base.base.loc, exp, pI_ref, type, nullptr)), nullptr))); - + while_body.push_back(al, ASRUtils::STMT( ASR::make_Assignment_t(al, f.base.base.loc, pI_ref, @@ -619,12 +619,12 @@ ASR::expr_t *native_to_cpython(Allocator &al, ASR::expr_t *exp, const ASR::Funct s.from_str(al, p); ASR::asr_t *pArgs = ASR::make_Variable_t(al, f.base.base.loc, f.m_symtab, s.c_str(al), nullptr, 0, ASRUtils::intent_local, nullptr, nullptr, ASR::storage_typeType::Default, ptr_t, - nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false); + nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false, false); ASR::expr_t *pArgs_ref = ASRUtils::EXPR(ASR::make_Var_t(al, f.base.base.loc, ASR::down_cast(pArgs))); f.m_symtab->add_symbol(p, ASR::down_cast(pArgs)); body.push_back(al, ASRUtils::STMT( - ASR::make_Assignment_t(al, f.base.base.loc, pArgs_ref, + ASR::make_Assignment_t(al, f.base.base.loc, pArgs_ref, ASRUtils::EXPR(ASRUtils::make_FunctionCall_t_util(al, f.base.base.loc, sym_PySet_New, nullptr, args_PySet_New.p, args_PySet_New.n, ptr_t, nullptr, nullptr)), nullptr))); conv_result = pArgs_ref; @@ -633,7 +633,7 @@ ASR::expr_t *native_to_cpython(Allocator &al, ASR::expr_t *exp, const ASR::Funct s.from_str(al, p); ASR::asr_t *pItem = ASR::make_Variable_t(al, f.base.base.loc, f.m_symtab, s.c_str(al), nullptr, 0, ASRUtils::intent_local, nullptr, nullptr, ASR::storage_typeType::Default, set->m_type, - nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false); + nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false, false); ASR::expr_t *pItem_ref = ASRUtils::EXPR(ASR::make_Var_t(al, f.base.base.loc, ASR::down_cast(pItem))); f.m_symtab->add_symbol(p, ASR::down_cast(pItem)); @@ -650,7 +650,7 @@ ASR::expr_t *native_to_cpython(Allocator &al, ASR::expr_t *exp, const ASR::Funct args_PySet_Add.n, nullptr, nullptr, false, false)))); body.push_back(al, ASRUtils::STMT(ASR::make_ForEach_t(al, f.base.base.loc, pItem_ref, exp, for_body.p, for_body.n))); - + } else if (type->type == ASR::ttypeType::Dict) { ASR::Dict_t *dict = ASR::down_cast(type); Str s; @@ -660,12 +660,12 @@ ASR::expr_t *native_to_cpython(Allocator &al, ASR::expr_t *exp, const ASR::Funct s.from_str(al, p); ASR::asr_t *pArgs = ASR::make_Variable_t(al, f.base.base.loc, f.m_symtab, s.c_str(al), nullptr, 0, ASRUtils::intent_local, nullptr, nullptr, ASR::storage_typeType::Default, ptr_t, - nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false); + nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false, false); ASR::expr_t *pArgs_ref = ASRUtils::EXPR(ASR::make_Var_t(al, f.base.base.loc, ASR::down_cast(pArgs))); f.m_symtab->add_symbol(p, ASR::down_cast(pArgs)); body.push_back(al, ASRUtils::STMT( - ASR::make_Assignment_t(al, f.base.base.loc, pArgs_ref, + ASR::make_Assignment_t(al, f.base.base.loc, pArgs_ref, ASRUtils::EXPR(ASRUtils::make_FunctionCall_t_util(al, f.base.base.loc, sym_PyDict_New, nullptr, nullptr, 0, ptr_t, nullptr, nullptr)), nullptr))); conv_result = pArgs_ref; @@ -674,7 +674,7 @@ ASR::expr_t *native_to_cpython(Allocator &al, ASR::expr_t *exp, const ASR::Funct s.from_str(al, p); ASR::asr_t *pItem = ASR::make_Variable_t(al, f.base.base.loc, f.m_symtab, s.c_str(al), nullptr, 0, ASRUtils::intent_local, nullptr, nullptr, ASR::storage_typeType::Default, dict->m_key_type, - nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false); + nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false, false); ASR::expr_t *pItem_ref = ASRUtils::EXPR(ASR::make_Var_t(al, f.base.base.loc, ASR::down_cast(pItem))); f.m_symtab->add_symbol(p, ASR::down_cast(pItem)); @@ -686,7 +686,7 @@ ASR::expr_t *native_to_cpython(Allocator &al, ASR::expr_t *exp, const ASR::Funct args_PyDict_SetItem.reserve(al, 3); args_PyDict_SetItem.push_back(al, {f.base.base.loc, pArgs_ref}); args_PyDict_SetItem.push_back(al, {f.base.base.loc, native_to_cpython(al, pItem_ref, f, for_body)}); // TODO: decrement the reference count of the return value of native_to_cpython after the PyList_Append subroutine call in next line - args_PyDict_SetItem.push_back(al, {f.base.base.loc, native_to_cpython(al, + args_PyDict_SetItem.push_back(al, {f.base.base.loc, native_to_cpython(al, ASRUtils::EXPR(ASR::make_DictItem_t(al, f.base.base.loc, exp, pItem_ref, nullptr, dict->m_value_type, nullptr)) , f, for_body)}); // TODO: decrement the reference count of the return value of native_to_cpython after the PyList_Append subroutine call in next line for_body.push_back(al, ASRUtils::STMT((ASRUtils::make_SubroutineCall_t_util(al, f.base.base.loc, @@ -725,7 +725,7 @@ void generate_body(Allocator &al, ASR::Function_t &f) { ASR::asr_t *call_Py_IsInitialized = ASRUtils::make_FunctionCall_t_util(al, f.base.base.loc, sym_Py_IsInitialized, nullptr, nullptr, 0, i4_type, nullptr, nullptr); ASR::asr_t * if_cond = ASR::make_IntegerCompare_t(al, f.base.base.loc, ASRUtils::EXPR(call_Py_IsInitialized), - ASR::cmpopType::Eq, ASRUtils::EXPR(ASR::make_IntegerConstant_t(al, + ASR::cmpopType::Eq, ASRUtils::EXPR(ASR::make_IntegerConstant_t(al, f.base.base.loc, 0, i4_type)), i4_type, nullptr); Vec if_body; if_body.reserve(al, 2); @@ -737,7 +737,7 @@ void generate_body(Allocator &al, ASR::Function_t &f) { Vec args_Py_DecodeLocale; s.from_str(al, ""); args_Py_DecodeLocale.reserve(al, 1); - ASR::ttype_t *str_type = ASRUtils::TYPE(ASR::make_Character_t(al, f.base.base.loc, 1, s.size(), nullptr)); + ASR::ttype_t *str_type = ASRUtils::TYPE(ASR::make_String_t(al, f.base.base.loc, 1, s.size(), nullptr, ASR::string_physical_typeType::PointerString)); args_Py_DecodeLocale.push_back(al, {f.base.base.loc, ASRUtils::EXPR(ASR::make_StringConstant_t(al, f.base.base.loc, s.c_str(al), str_type))}); args_Py_DecodeLocale.push_back(al, {f.base.base.loc, ASRUtils::EXPR(ASR::make_PointerNullConstant_t(al, @@ -745,7 +745,7 @@ void generate_body(Allocator &al, ASR::Function_t &f) { s.from_str(al, "pA"); ASR::asr_t *pA = ASR::make_Variable_t(al, f.base.base.loc, f.m_symtab, s.c_str(al), nullptr, 0, ASRUtils::intent_local, nullptr, nullptr, ASR::storage_typeType::Default, ptr_t, nullptr, - ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false); + ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false, false); ASR::expr_t *pA_ref = ASRUtils::EXPR(ASR::make_Var_t(al, f.base.base.loc, ASR::down_cast(pA))); f.m_symtab->add_symbol(std::string("pA"), ASR::down_cast(pA)); if_body.push_back(al, ASRUtils::STMT( @@ -753,7 +753,7 @@ void generate_body(Allocator &al, ASR::Function_t &f) { ASRUtils::EXPR(ASRUtils::make_FunctionCall_t_util(al, f.base.base.loc, sym_Py_DecodeLocale, nullptr, args_Py_DecodeLocale.p, args_Py_DecodeLocale.n, ptr_t, nullptr, nullptr)), nullptr))); - + ASR::symbol_t *sym_PySys_SetArgv = f.m_symtab->resolve_symbol("PySys_SetArgv"); Vec args_PySys_SetArgv; s.from_str(al, ""); @@ -779,13 +779,13 @@ void generate_body(Allocator &al, ASR::Function_t &f) { Vec args_PyUnicode_FromString; s.from_str(al, f.m_module_file); args_PyUnicode_FromString.reserve(al, 1); - str_type = ASRUtils::TYPE(ASR::make_Character_t(al, f.base.base.loc, 1, s.size(), nullptr)); + str_type = ASRUtils::TYPE(ASR::make_String_t(al, f.base.base.loc, 1, s.size(), nullptr, ASR::string_physical_typeType::PointerString)); args_PyUnicode_FromString.push_back(al, {f.base.base.loc, ASRUtils::EXPR(ASR::make_StringConstant_t(al, f.base.base.loc, s.c_str(al), str_type))}); s.from_str(al, "pName"); ASR::asr_t *pName = ASR::make_Variable_t(al, f.base.base.loc, f.m_symtab, s.c_str(al), nullptr, 0, ASRUtils::intent_local, nullptr, nullptr, ASR::storage_typeType::Default, ptr_t, nullptr, - ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false); + ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false, false); ASR::expr_t *pName_ref = ASRUtils::EXPR(ASR::make_Var_t(al, f.base.base.loc, ASR::down_cast(pName))); f.m_symtab->add_symbol(std::string("pName"), ASR::down_cast(pName)); body.push_back(al, ASRUtils::STMT( @@ -801,12 +801,12 @@ void generate_body(Allocator &al, ASR::Function_t &f) { s.from_str(al, "pModule"); ASR::asr_t *pModule = ASR::make_Variable_t(al, f.base.base.loc, f.m_symtab, s.c_str(al), nullptr, 0, ASRUtils::intent_local, nullptr, nullptr, ASR::storage_typeType::Default, ptr_t, nullptr, - ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false); + ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false, false); ASR::expr_t *pModule_ref = ASRUtils::EXPR(ASR::make_Var_t(al, f.base.base.loc, ASR::down_cast(pModule))); f.m_symtab->add_symbol(std::string("pModule"), ASR::down_cast(pModule)); body.push_back(al, ASRUtils::STMT( - ASR::make_Assignment_t(al, f.base.base.loc, pModule_ref, + ASR::make_Assignment_t(al, f.base.base.loc, pModule_ref, ASRUtils::EXPR(ASRUtils::make_FunctionCall_t_util(al, f.base.base.loc, sym_PyImport_Import, nullptr, args_PyImport_Import.p, args_PyImport_Import.n, ptr_t, nullptr, nullptr)), nullptr))); @@ -817,17 +817,17 @@ void generate_body(Allocator &al, ASR::Function_t &f) { args_PyObject_GetAttrString.reserve(al, 2); args_PyObject_GetAttrString.push_back(al, {f.base.base.loc, pModule_ref}); s.from_str(al, f.m_name); - str_type = ASRUtils::TYPE(ASR::make_Character_t(al, f.base.base.loc, 1, s.size(), nullptr)); + str_type = ASRUtils::TYPE(ASR::make_String_t(al, f.base.base.loc, 1, s.size(), nullptr, ASR::string_physical_typeType::PointerString)); args_PyObject_GetAttrString.push_back(al, {f.base.base.loc, ASRUtils::EXPR(ASR::make_StringConstant_t(al, f.base.base.loc, s.c_str(al), str_type))}); s.from_str(al, "pFunc"); ASR::asr_t *pFunc = ASR::make_Variable_t(al, f.base.base.loc, f.m_symtab, s.c_str(al), nullptr, 0, ASRUtils::intent_local, nullptr, nullptr, ASR::storage_typeType::Default, ptr_t, nullptr, - ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false); + ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false, false); ASR::expr_t *pFunc_ref = ASRUtils::EXPR(ASR::make_Var_t(al, f.base.base.loc, ASR::down_cast(pFunc))); f.m_symtab->add_symbol(std::string("pFunc"), ASR::down_cast(pFunc)); body.push_back(al, ASRUtils::STMT( - ASR::make_Assignment_t(al, f.base.base.loc, pFunc_ref, + ASR::make_Assignment_t(al, f.base.base.loc, pFunc_ref, ASRUtils::EXPR(ASRUtils::make_FunctionCall_t_util(al, f.base.base.loc, sym_PyObject_GetAttrString, nullptr, args_PyObject_GetAttrString.p, args_PyObject_GetAttrString.n, ptr_t, nullptr, nullptr)), nullptr))); @@ -841,11 +841,11 @@ void generate_body(Allocator &al, ASR::Function_t &f) { s.from_str(al, "pArgs"); ASR::asr_t *pArgs = ASR::make_Variable_t(al, f.base.base.loc, f.m_symtab, s.c_str(al), nullptr, 0, ASRUtils::intent_local, nullptr, nullptr, ASR::storage_typeType::Default, ptr_t, nullptr, - ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false); + ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false, false); ASR::expr_t *pArgs_ref = ASRUtils::EXPR(ASR::make_Var_t(al, f.base.base.loc, ASR::down_cast(pArgs))); f.m_symtab->add_symbol(std::string("pArgs"), ASR::down_cast(pArgs)); body.push_back(al, ASRUtils::STMT( - ASR::make_Assignment_t(al, f.base.base.loc, pArgs_ref, + ASR::make_Assignment_t(al, f.base.base.loc, pArgs_ref, ASRUtils::EXPR(ASRUtils::make_FunctionCall_t_util(al, f.base.base.loc, sym_PyTuple_New, nullptr, args_PyTuple_New.p, args_PyTuple_New.n, ptr_t, nullptr, nullptr)), nullptr))); @@ -862,7 +862,7 @@ void generate_body(Allocator &al, ASR::Function_t &f) { s.from_str(al, p); ASR::asr_t *pA = ASR::make_Variable_t(al, f.base.base.loc, f.m_symtab, s.c_str(al), nullptr, 0, ASRUtils::intent_local, nullptr, nullptr, ASR::storage_typeType::Default, i4_type, nullptr, - ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false); + ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false, false); ASR::expr_t *pA_ref = ASRUtils::EXPR(ASR::make_Var_t(al, f.base.base.loc, ASR::down_cast(pA))); f.m_symtab->add_symbol(p, ASR::down_cast(pA)); body.push_back(al, @@ -880,7 +880,7 @@ void generate_body(Allocator &al, ASR::Function_t &f) { s.from_str(al, "pReturn"); ASR::asr_t *pReturn = ASR::make_Variable_t(al, f.base.base.loc, f.m_symtab, s.c_str(al), nullptr, 0, ASRUtils::intent_local, nullptr, nullptr, ASR::storage_typeType::Default, ptr_t, nullptr, - ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false); + ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false, false); ASR::expr_t *pReturn_ref = ASRUtils::EXPR(ASR::make_Var_t(al, f.base.base.loc, ASR::down_cast(pReturn))); f.m_symtab->add_symbol(std::string("pReturn"), ASR::down_cast(pReturn)); diff --git a/src/libasr/pass/replace_array_passed_in_function_call.h b/src/libasr/pass/replace_array_passed_in_function_call.h new file mode 100644 index 0000000000..101c23062c --- /dev/null +++ b/src/libasr/pass/replace_array_passed_in_function_call.h @@ -0,0 +1,14 @@ +#ifndef LIBASR_PASS_REPLACE_ARRAY_PASSED_IN_FUNCTION_CALL_H +#define LIBASR_PASS_REPLACE_ARRAY_PASSED_IN_FUNCTION_CALL_H + +#include +#include + +namespace LCompilers { + + void pass_replace_array_passed_in_function_call(Allocator &al, ASR::TranslationUnit_t &unit, + const PassOptions &pass_options); + +} // namespace LCompilers + +#endif // LIBASR_PASS_REPLACE_ARRAY_PASSED_IN_FUNCTION_CALL_H diff --git a/src/libasr/pass/replace_openmp.h b/src/libasr/pass/replace_openmp.h new file mode 100644 index 0000000000..6642227013 --- /dev/null +++ b/src/libasr/pass/replace_openmp.h @@ -0,0 +1,14 @@ +#ifndef LIBASR_PASS_REPLACE_OPENMP +#define LIBASR_PASS_REPLACE_OPENMP + +#include +#include + +namespace LCompilers { + + void pass_replace_openmp(Allocator &al, ASR::TranslationUnit_t &unit, + const PassOptions &pass_options); + +} // namespace LCompilers + +#endif // LIBASR_PASS_REPLACE_OPENMP diff --git a/src/libasr/pass/replace_symbolic.cpp b/src/libasr/pass/replace_symbolic.cpp index a9382227fa..577af32b86 100644 --- a/src/libasr/pass/replace_symbolic.cpp +++ b/src/libasr/pass/replace_symbolic.cpp @@ -8,6 +8,8 @@ #include #include +#include + namespace LCompilers { using ASR::down_cast; @@ -57,12 +59,6 @@ class ReplaceSymbolicVisitor : public PassUtils::PassVisitorm_args[0], x->m_args[1], x->m_args[2])); \ - break; } - #define BASIC_BINOP(SYM, name) \ case LCompilers::ASRUtils::IntrinsicElementalFunctions::Symbolic##SYM: { \ pass_result.push_back(al, basic_binop(loc, "basic_"#name, target, \ @@ -79,7 +75,7 @@ class ReplaceSymbolicVisitor : public PassUtils::PassVisitorm_args[0]); \ - return b.iEq(function_call, b.i32(N)); } + return b.Eq(function_call, b.i32(N)); } ASR::stmt_t *SubroutineCall(const Location &loc, ASR::symbol_t *sym, std::vector args) { @@ -104,7 +100,8 @@ class ReplaceSymbolicVisitor : public PassUtils::PassVisitor(*expr)) { ASR::IntrinsicElementalFunction_t* intrinsic_func = ASR::down_cast(expr); @@ -304,8 +282,6 @@ class ReplaceSymbolicVisitor : public PassUtils::PassVisitor( - ASR::make_Variable_t(al, xx.base.base.loc, current_scope, + ASRUtils::make_Variable_t_util(al, xx.base.base.loc, current_scope, s2c(al, placeholder), nullptr, 0, xx.m_intent, nullptr, nullptr, xx.m_storage, @@ -465,7 +441,6 @@ class ReplaceSymbolicVisitor : public PassUtils::PassVisitorm_args[0]); @@ -487,7 +460,7 @@ class ReplaceSymbolicVisitor : public PassUtils::PassVisitorget_unique_name("_lcompilers_symbolic_argument_container"); - ASR::symbol_t* args_sym = ASR::down_cast(ASR::make_Variable_t( + ASR::symbol_t* args_sym = ASR::down_cast(ASRUtils::make_Variable_t_util( al, loc, current_scope, s2c(al, args_str), nullptr, 0, ASR::intentType::Local, nullptr, nullptr, ASR::storage_typeType::Default, CPtr_type, nullptr, ASR::abiType::BindC, ASR::Public, ASR::presenceType::Required, false)); @@ -507,8 +480,8 @@ class ReplaceSymbolicVisitor : public PassUtils::PassVisitorm_args[1], ASRUtils::TYPE(ASR::make_Logical_t(al, loc, 4)), nullptr)); std::string error_str = "tuple index out of range"; - ASR::ttype_t *str_type = ASRUtils::TYPE(ASR::make_Character_t(al, loc, - 1, error_str.size(), nullptr)); + ASR::ttype_t *str_type = ASRUtils::TYPE(ASR::make_String_t(al, loc, + 1, error_str.size(), nullptr, ASR::string_physical_typeType::PointerString)); ASR::expr_t* error = ASRUtils::EXPR(ASR::make_StringConstant_t(al, loc, s2c(al, error_str), str_type)); ASR::stmt_t *stmt3 = ASRUtils::STMT(ASR::make_Assert_t(al, loc, test, error)); pass_result.push_back(al, stmt3); @@ -535,9 +508,6 @@ class ReplaceSymbolicVisitor : public PassUtils::PassVisitorm_args[0], intrinsic_func->m_args[1]); } - case LCompilers::ASRUtils::IntrinsicElementalFunctions::SymbolicIsPositive: { - return basic_is_positive(loc, intrinsic_func->m_args[0]); - } // (sym_name, n) where n = 16, 15, ... as the right value of the // IntegerCompare node as it represents SYMENGINE_ADD through SYMENGINE_ENUM BASIC_ATTR(AddQ, 16) @@ -545,7 +515,6 @@ class ReplaceSymbolicVisitor : public PassUtils::PassVisitor( - ASR::make_Variable_t(al, list_variable->base.base.loc, current_scope, + ASRUtils::make_Variable_t_util(al, list_variable->base.base.loc, current_scope, s2c(al, placeholder), nullptr, 0, list_variable->m_intent, nullptr, nullptr, list_variable->m_storage, @@ -662,7 +631,7 @@ class ReplaceSymbolicVisitor : public PassUtils::PassVisitorget_unique_name("symbolic_list_index"); ASR::ttype_t* int32_type = ASRUtils::TYPE(ASR::make_Integer_t(al, x.base.base.loc, 4)); ASR::symbol_t* index_sym = ASR::down_cast( - ASR::make_Variable_t(al, x.base.base.loc, current_scope, s2c(al, symbolic_list_index), + ASRUtils::make_Variable_t_util(al, x.base.base.loc, current_scope, s2c(al, symbolic_list_index), nullptr, 0, ASR::intentType::Local, nullptr, nullptr, ASR::storage_typeType::Default, int32_type, nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false)); current_scope->add_symbol(symbolic_list_index, index_sym); @@ -788,31 +757,6 @@ class ReplaceSymbolicVisitor : public PassUtils::PassVisitor(*xx.m_test)) { - ASR::LogicalBinOp_t* logical_binop = ASR::down_cast(xx.m_test); - ASR::expr_t* function_call_left = logical_binop->m_left; - ASR::expr_t* function_call_right = logical_binop->m_right; - - if (ASR::is_a(*logical_binop->m_left)) { - ASR::IntrinsicElementalFunction_t* left = ASR::down_cast(logical_binop->m_left); - if (left->m_type->type == ASR::ttypeType::Logical) { - if (is_logical_intrinsic_symbolic(logical_binop->m_left)) { - function_call_left = process_attributes(xx.base.base.loc, logical_binop->m_left); - } - } - } - if (ASR::is_a(*logical_binop->m_right)) { - ASR::IntrinsicElementalFunction_t* right = ASR::down_cast(logical_binop->m_right); - if (right->m_type->type == ASR::ttypeType::Logical) { - if (is_logical_intrinsic_symbolic(logical_binop->m_right)) { - function_call_right = process_attributes(xx.base.base.loc, logical_binop->m_right); - } - } - } - - ASR::expr_t* new_logical_binop = ASRUtils::EXPR(ASR::make_LogicalBinOp_t(al, xx.base.base.loc, - function_call_left, logical_binop->m_op, function_call_right, logical_binop->m_type, logical_binop->m_value)); - xx.m_test = new_logical_binop; } } @@ -826,7 +770,7 @@ class ReplaceSymbolicVisitor : public PassUtils::PassVisitor(val); ASR::ttype_t *type = ASRUtils::TYPE(ASR::make_SymbolicExpression_t(al, x.base.base.loc)); std::string symengine_var = symengine_stack.push(); - ASR::symbol_t *arg = ASR::down_cast(ASR::make_Variable_t( + ASR::symbol_t *arg = ASR::down_cast(ASRUtils::make_Variable_t_util( al, x.base.base.loc, current_scope, s2c(al, symengine_var), nullptr, 0, ASR::intentType::Local, nullptr, nullptr, ASR::storage_typeType::Default, type, nullptr, ASR::abiType::BindC, ASR::Public, ASR::presenceType::Required, false)); @@ -865,98 +809,100 @@ class ReplaceSymbolicVisitor : public PassUtils::PassVisitor print_tmp; - for (size_t i=0; i(*val) && ASR::is_a(*ASRUtils::expr_type(val))) { - ASR::symbol_t *v = ASR::down_cast(val)->m_v; - if ((symbolic_vars_to_free.find(v) == symbolic_vars_to_free.end()) && - (symbolic_vars_to_omit.find(v) == symbolic_vars_to_omit.end())) return; - print_tmp.push_back(basic_str(x.base.base.loc, val)); - } else if (ASR::is_a(*val)) { - ASR::IntrinsicElementalFunction_t* intrinsic_func = ASR::down_cast(val); - if (ASR::is_a(*ASRUtils::expr_type(val))) { - ASR::ttype_t *type = ASRUtils::TYPE(ASR::make_SymbolicExpression_t(al, x.base.base.loc)); - std::string symengine_var = symengine_stack.push(); - ASR::symbol_t *arg = ASR::down_cast(ASR::make_Variable_t( - al, x.base.base.loc, current_scope, s2c(al, symengine_var), nullptr, 0, ASR::intentType::Local, - nullptr, nullptr, ASR::storage_typeType::Default, type, nullptr, - ASR::abiType::BindC, ASR::Public, ASR::presenceType::Required, false)); - current_scope->add_symbol(s2c(al, symengine_var), arg); - for (auto &item : current_scope->get_scope()) { - if (ASR::is_a(*item.second)) { - ASR::Variable_t *s = ASR::down_cast(item.second); - this->visit_Variable(*s); - } - } - - ASR::expr_t* target = ASRUtils::EXPR(ASR::make_Var_t(al, x.base.base.loc, arg)); - process_intrinsic_function(x.base.base.loc, intrinsic_func, target); - - // Now create the FunctionCall node for basic_str - print_tmp.push_back(basic_str(x.base.base.loc, target)); - } else if (ASR::is_a(*ASRUtils::expr_type(val))) { - if (is_logical_intrinsic_symbolic(val)) { - ASR::expr_t* function_call = process_attributes(x.base.base.loc, val); - print_tmp.push_back(function_call); - } - } else { - print_tmp.push_back(val); - } - } else if (ASR::is_a(*val)) { - ASR::Cast_t* cast_t = ASR::down_cast(val); - if(cast_t->m_kind != ASR::cast_kindType::IntegerToSymbolicExpression) return; - this->visit_Cast(*cast_t); - ASR::symbol_t *var_sym = current_scope->get_symbol(symengine_stack.pop()); - ASR::expr_t* target = ASRUtils::EXPR(ASR::make_Var_t(al, x.base.base.loc, var_sym)); - - // Now create the FunctionCall node for basic_str - print_tmp.push_back(basic_str(x.base.base.loc, target)); - } else if (ASR::is_a(*val)) { - ASR::SymbolicCompare_t *s = ASR::down_cast(val); - if (s->m_op == ASR::cmpopType::Eq || s->m_op == ASR::cmpopType::NotEq) { - ASR::expr_t* function_call = nullptr; - if (s->m_op == ASR::cmpopType::Eq) { - function_call = basic_compare(x.base.base.loc, "basic_eq", s->m_left, s->m_right); - } else { - function_call = basic_compare(x.base.base.loc, "basic_neq", s->m_left, s->m_right); - } - print_tmp.push_back(function_call); - } - } else if (ASR::is_a(*val)) { - ASR::ListItem_t* list_item = ASR::down_cast(val); - if (list_item->m_type->type == ASR::ttypeType::SymbolicExpression) { - ASR::expr_t *value = ASRUtils::EXPR(ASR::make_ListItem_t(al, - x.base.base.loc, list_item->m_a, list_item->m_pos, - ASRUtils::TYPE(ASR::make_CPtr_t(al, x.base.base.loc)), nullptr)); - print_tmp.push_back(basic_str(x.base.base.loc, value)); - } else { - print_tmp.push_back(val); - } - } else { - print_tmp.push_back(x.m_values[i]); - } - } - if (!print_tmp.empty()) { - Vec tmp_vec; - tmp_vec.reserve(al, print_tmp.size()); - for (auto &e: print_tmp) { - tmp_vec.push_back(al, e); - } - ASR::stmt_t *print_stmt = ASRUtils::STMT( - ASR::make_Print_t(al, x.base.base.loc, tmp_vec.p, tmp_vec.size(), - x.m_separator, x.m_end)); - print_tmp.clear(); - pass_result.push_back(al, print_stmt); - } - } + //TODO :: Use the below implementation for stringFormat visitor. + + // void visit_Print(const ASR::Print_t &x) { + // std::vector print_tmp; + // for (size_t i=0; i(*val) && ASR::is_a(*ASRUtils::expr_type(val))) { + // ASR::symbol_t *v = ASR::down_cast(val)->m_v; + // if ((symbolic_vars_to_free.find(v) == symbolic_vars_to_free.end()) && + // (symbolic_vars_to_omit.find(v) == symbolic_vars_to_omit.end())) return; + // print_tmp.push_back(basic_str(x.base.base.loc, val)); + // } else if (ASR::is_a(*val)) { + // ASR::IntrinsicElementalFunction_t* intrinsic_func = ASR::down_cast(val); + // if (ASR::is_a(*ASRUtils::expr_type(val))) { + // ASR::ttype_t *type = ASRUtils::TYPE(ASR::make_SymbolicExpression_t(al, x.base.base.loc)); + // std::string symengine_var = symengine_stack.push(); + // ASR::symbol_t *arg = ASR::down_cast(ASRUtils::make_Variable_t_util( + // al, x.base.base.loc, current_scope, s2c(al, symengine_var), nullptr, 0, ASR::intentType::Local, + // nullptr, nullptr, ASR::storage_typeType::Default, type, nullptr, + // ASR::abiType::BindC, ASR::Public, ASR::presenceType::Required, false)); + // current_scope->add_symbol(s2c(al, symengine_var), arg); + // for (auto &item : current_scope->get_scope()) { + // if (ASR::is_a(*item.second)) { + // ASR::Variable_t *s = ASR::down_cast(item.second); + // this->visit_Variable(*s); + // } + // } + + // ASR::expr_t* target = ASRUtils::EXPR(ASR::make_Var_t(al, x.base.base.loc, arg)); + // process_intrinsic_function(x.base.base.loc, intrinsic_func, target); + + // // Now create the FunctionCall node for basic_str + // print_tmp.push_back(basic_str(x.base.base.loc, target)); + // } else if (ASR::is_a(*ASRUtils::expr_type(val))) { + // if (is_logical_intrinsic_symbolic(val)) { + // ASR::expr_t* function_call = process_attributes(x.base.base.loc, val); + // print_tmp.push_back(function_call); + // } + // } else { + // print_tmp.push_back(val); + // } + // } else if (ASR::is_a(*val)) { + // ASR::Cast_t* cast_t = ASR::down_cast(val); + // if(cast_t->m_kind != ASR::cast_kindType::IntegerToSymbolicExpression) return; + // this->visit_Cast(*cast_t); + // ASR::symbol_t *var_sym = current_scope->get_symbol(symengine_stack.pop()); + // ASR::expr_t* target = ASRUtils::EXPR(ASR::make_Var_t(al, x.base.base.loc, var_sym)); + + // // Now create the FunctionCall node for basic_str + // print_tmp.push_back(basic_str(x.base.base.loc, target)); + // } else if (ASR::is_a(*val)) { + // ASR::SymbolicCompare_t *s = ASR::down_cast(val); + // if (s->m_op == ASR::cmpopType::Eq || s->m_op == ASR::cmpopType::NotEq) { + // ASR::expr_t* function_call = nullptr; + // if (s->m_op == ASR::cmpopType::Eq) { + // function_call = basic_compare(x.base.base.loc, "basic_eq", s->m_left, s->m_right); + // } else { + // function_call = basic_compare(x.base.base.loc, "basic_neq", s->m_left, s->m_right); + // } + // print_tmp.push_back(function_call); + // } + // } else if (ASR::is_a(*val)) { + // ASR::ListItem_t* list_item = ASR::down_cast(val); + // if (list_item->m_type->type == ASR::ttypeType::SymbolicExpression) { + // ASR::expr_t *value = ASRUtils::EXPR(ASR::make_ListItem_t(al, + // x.base.base.loc, list_item->m_a, list_item->m_pos, + // ASRUtils::TYPE(ASR::make_CPtr_t(al, x.base.base.loc)), nullptr)); + // print_tmp.push_back(basic_str(x.base.base.loc, value)); + // } else { + // print_tmp.push_back(val); + // } + // } else { + // print_tmp.push_back(x.m_values[i]); + // } + // } + // if (!print_tmp.empty()) { + // Vec tmp_vec; + // tmp_vec.reserve(al, print_tmp.size()); + // for (auto &e: print_tmp) { + // tmp_vec.push_back(al, e); + // } + // ASR::stmt_t *print_stmt = ASRUtils::STMT( + // ASR::make_Print_t(al, x.base.base.loc, tmp_vec.p, tmp_vec.size(), + // x.m_separator, x.m_end)); + // print_tmp.clear(); + // pass_result.push_back(al, print_stmt); + // } + // } void visit_IntrinsicFunction(const ASR::IntrinsicElementalFunction_t &x) { if(x.m_type && x.m_type->type == ASR::ttypeType::SymbolicExpression) { ASR::ttype_t *type = ASRUtils::TYPE(ASR::make_SymbolicExpression_t(al, x.base.base.loc)); std::string symengine_var = symengine_stack.push(); - ASR::symbol_t *arg = ASR::down_cast(ASR::make_Variable_t( + ASR::symbol_t *arg = ASR::down_cast(ASRUtils::make_Variable_t_util( al, x.base.base.loc, current_scope, s2c(al, symengine_var), nullptr, 0, ASR::intentType::Local, nullptr, nullptr, ASR::storage_typeType::Default, type, nullptr, ASR::abiType::BindC, ASR::Public, ASR::presenceType::Required, false)); @@ -979,7 +925,7 @@ class ReplaceSymbolicVisitor : public PassUtils::PassVisitor(ASR::make_Variable_t( + ASR::symbol_t *arg = ASR::down_cast(ASRUtils::make_Variable_t_util( al, x.base.base.loc, current_scope, s2c(al, symengine_var), nullptr, 0, ASR::intentType::Local, nullptr, nullptr, ASR::storage_typeType::Default, type, nullptr, ASR::abiType::BindC, ASR::Public, ASR::presenceType::Required, false)); diff --git a/src/libasr/pass/replace_with_compile_time_values.cpp b/src/libasr/pass/replace_with_compile_time_values.cpp new file mode 100644 index 0000000000..b58140f799 --- /dev/null +++ b/src/libasr/pass/replace_with_compile_time_values.cpp @@ -0,0 +1,123 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +namespace LCompilers { + +class CompileTimeValueReplacer: public ASR::BaseExprReplacer { + + private: + + Allocator& al; + + public: + + bool inside_prohibited_expression; + + + CompileTimeValueReplacer(Allocator& al_): + al(al_), inside_prohibited_expression(false) {} + + void replace_ArrayReshape(ASR::ArrayReshape_t* x) { + ASR::BaseExprReplacer::replace_ArrayReshape(x); + if( ASRUtils::is_fixed_size_array( + ASRUtils::expr_type(x->m_array)) ) { + x->m_type = ASRUtils::duplicate_type(al, x->m_type, nullptr, + ASR::array_physical_typeType::FixedSizeArray, true); + } + } + + template + void replace_ExprMethod(ExprType* x, + void (ASR::BaseExprReplacer::*replacer_function)(ExprType*) ) { + bool inside_prohibited_expression_copy = inside_prohibited_expression; + inside_prohibited_expression = true; + (this->*replacer_function)(x); + inside_prohibited_expression = inside_prohibited_expression_copy; + } + + void replace_ArrayItem(ASR::ArrayItem_t* x) { + replace_ExprMethod(x, &ASR::BaseExprReplacer::replace_ArrayItem); + } + + void replace_expr(ASR::expr_t* x) { + if( x == nullptr || inside_prohibited_expression ) { + return ; + } + + bool is_array_broadcast = ASR::is_a(*x); + if( is_array_broadcast ) { + return ; + } + + ASR::BaseExprReplacer::replace_expr(x); + + ASR::expr_t* compile_time_value = ASRUtils::expr_value(x); + if( compile_time_value == nullptr ) { + return ; + } + + size_t value_rank = ASRUtils::extract_n_dims_from_ttype(ASRUtils::expr_type(compile_time_value)); + size_t expr_rank = ASRUtils::extract_n_dims_from_ttype(ASRUtils::expr_type(x)); + // TODO: Handle with reshape later + if( value_rank != expr_rank ) { + return ; + } + + *current_expr = compile_time_value; + } +}; + +class ExprVisitor: public ASR::CallReplacerOnExpressionsVisitor { + + private: + + CompileTimeValueReplacer replacer; + + public: + + void call_replacer() { + replacer.current_expr = current_expr; + replacer.replace_expr(*current_expr); + } + + ExprVisitor(Allocator& al_): replacer(al_) + {} + + template + void visit_ExprMethod(const ExprType& x, + void (ASR::CallReplacerOnExpressionsVisitor::*visitor_function)(const ExprType&) ) { + bool inside_prohibited_expression_copy = replacer.inside_prohibited_expression; + replacer.inside_prohibited_expression = true; + (this->*visitor_function)(x); + replacer.inside_prohibited_expression = inside_prohibited_expression_copy; + } + + void visit_ArrayItem(const ASR::ArrayItem_t& x) { + visit_ExprMethod(x, &ASR::CallReplacerOnExpressionsVisitor::visit_ArrayItem); + } + +}; + +void pass_replace_with_compile_time_values( + Allocator &al, ASR::TranslationUnit_t &unit, + const LCompilers::PassOptions& /*pass_options*/) { + ExprVisitor v(al); + // v.call_replacer_on_value = false; + v.visit_TranslationUnit(unit); + PassUtils::UpdateDependenciesVisitor u(al); + u.visit_TranslationUnit(unit); +} + + +} // namespace LCompilers diff --git a/src/libasr/pass/replace_with_compile_time_values.h b/src/libasr/pass/replace_with_compile_time_values.h new file mode 100644 index 0000000000..c450fbbe55 --- /dev/null +++ b/src/libasr/pass/replace_with_compile_time_values.h @@ -0,0 +1,14 @@ +#ifndef LIBASR_PASS_REPLACE_WITH_COMPILE_TIME_VALUES_H +#define LIBASR_PASS_REPLACE_WITH_COMPILE_TIME_VALUES_H + +#include +#include + +namespace LCompilers { + + void pass_replace_with_compile_time_values(Allocator &al, ASR::TranslationUnit_t &unit, + const PassOptions &pass_options); + +} // namespace LCompilers + +#endif // LIBASR_PASS_REPLACE_WITH_COMPILE_TIME_VALUES_H diff --git a/src/libasr/pass/select_case.cpp b/src/libasr/pass/select_case.cpp index 0fba2c20e3..5e61202bda 100644 --- a/src/libasr/pass/select_case.cpp +++ b/src/libasr/pass/select_case.cpp @@ -154,7 +154,7 @@ void case_to_if_with_fall_through(Allocator& al, const ASR::Select_t& x, ASR::expr_t* a_test, Vec& body, SymbolTable* scope) { body.reserve(al, x.n_body + 1); const Location& loc = x.base.base.loc; - ASR::symbol_t* case_found_sym = ASR::down_cast(ASR::make_Variable_t( + ASR::symbol_t* case_found_sym = ASR::down_cast(ASRUtils::make_Variable_t_util( al, loc, scope, s2c(al, scope->get_unique_name("case_found")), nullptr, 0, ASR::intentType::Local, nullptr, nullptr, ASR::storage_typeType::Default, ASRUtils::TYPE(ASR::make_Logical_t(al, loc, 4)), nullptr, ASR::abiType::Source, diff --git a/src/libasr/pass/sign_from_value.cpp b/src/libasr/pass/sign_from_value.cpp index ac4a52bb1a..3f6e4fac7d 100644 --- a/src/libasr/pass/sign_from_value.cpp +++ b/src/libasr/pass/sign_from_value.cpp @@ -6,7 +6,6 @@ #include #include -#include #include @@ -31,130 +30,87 @@ This allows backend specific code generation for better performance. c = sign_from_value(a, b) */ -class SignFromValueVisitor : public PassUtils::SkipOptimizationFunctionVisitor -{ + +class SignFromValueReplacer : public ASR::BaseExprReplacer{ private: + Allocator &al; ASR::TranslationUnit_t &unit; - - LCompilers::PassOptions pass_options; - - ASR::expr_t* sign_from_value_var; - - // To make sure that SignFromValue is applied only for - // the nodes implemented in this class - bool from_sign_from_value; - -public: - SignFromValueVisitor(Allocator &al_, ASR::TranslationUnit_t &unit_, - const LCompilers::PassOptions& pass_options_) : SkipOptimizationFunctionVisitor(al_), - unit(unit_), pass_options(pass_options_), sign_from_value_var(nullptr), from_sign_from_value(false) - { - pass_result.reserve(al, 1); - } + const LCompilers::PassOptions& pass_options; bool is_value_one(ASR::expr_t* expr) { double value; - if( ASRUtils::is_value_constant(expr, value) ) { + if( ASRUtils::is_value_constant(ASRUtils::expr_value(expr), value) && + ASRUtils::is_real(*ASRUtils::expr_type(expr)) ) { return value == 1.0; } return false; } ASR::expr_t* is_extract_sign(ASR::expr_t* expr) { - if( !ASR::is_a(*expr) ) { - return nullptr; - } - ASR::FunctionCall_t* func_call = ASR::down_cast(expr); - ASR::symbol_t* func_sym = ASRUtils::symbol_get_past_external(func_call->m_name); - if( !ASR::is_a(*func_sym) ) { - return nullptr; + if( ASR::is_a(*expr) ) { + ASR::RealCopySign_t *real_cpy_sign = ASR::down_cast(expr); + if( !is_value_one(real_cpy_sign->m_target) ) {return nullptr;} + return real_cpy_sign->m_source; } - ASR::Function_t* func = ASR::down_cast(func_sym); - if( ASRUtils::is_intrinsic_procedure(func) && - std::string(func->m_name).find("sign") == std::string::npos ) { - return nullptr; - } - ASR::expr_t *arg0 = func_call->m_args[0].m_value, *arg1 = func_call->m_args[1].m_value; - if( !is_value_one(arg0) ) { - return nullptr; - } - return arg1; - } - - void visit_IntegerBinOp(const ASR::IntegerBinOp_t& x) { - handle_BinOp(x); - } - - void visit_RealBinOp(const ASR::RealBinOp_t& x) { - handle_BinOp(x); - } - - void visit_ComplexBinOp(const ASR::ComplexBinOp_t& x) { - handle_BinOp(x); + return nullptr; } - template - void handle_BinOp(const T& x_const) { - if( !from_sign_from_value ) { - return ; - } - from_sign_from_value = true; - T& x = const_cast(x_const); +public: - sign_from_value_var = nullptr; - visit_expr(*x.m_left); - if( sign_from_value_var ) { - x.m_left = sign_from_value_var; - } + SignFromValueReplacer(Allocator &al, ASR::TranslationUnit_t &unit, + const LCompilers::PassOptions& pass_options) + :al(al),unit(unit), pass_options(pass_options){} - sign_from_value_var = nullptr; - visit_expr(*x.m_right); - if( sign_from_value_var ) { - x.m_right = sign_from_value_var; - } - sign_from_value_var = nullptr; - if( x.m_op != ASR::binopType::Mul ) { - return ; - } + void replace_RealBinOp(ASR::RealBinOp_t* x) { + BaseExprReplacer::replace_RealBinOp(x); + if( x->m_op != ASR::binopType::Mul ) { return; } ASR::expr_t *first_arg = nullptr, *second_arg = nullptr; - - first_arg = is_extract_sign(x.m_left); - second_arg = is_extract_sign(x.m_right); + first_arg = is_extract_sign(x->m_left); + second_arg = is_extract_sign(x->m_right); if( second_arg ) { - first_arg = x.m_left; + first_arg = x->m_left; } else if( first_arg ) { - second_arg = x.m_right; + second_arg = x->m_right; } else { return ; } - - sign_from_value_var = PassUtils::get_sign_from_value(first_arg, second_arg, - al, unit, x.base.base.loc, pass_options); - from_sign_from_value = false; + *current_expr = PassUtils::get_sign_from_value(first_arg, second_arg, + al, unit, x->base.base.loc, + const_cast(pass_options)); } + +}; - void visit_Assignment(const ASR::Assignment_t& x) { - from_sign_from_value = true; - ASR::Assignment_t& xx = const_cast(x); - sign_from_value_var = nullptr; - visit_expr(*x.m_value); - if( sign_from_value_var ) { - xx.m_value = sign_from_value_var; +class SignFromValueVisitor : public ASR::CallReplacerOnExpressionsVisitor{ +private: + SignFromValueReplacer replacer; +public: + SignFromValueVisitor(Allocator &al, ASR::TranslationUnit_t &unit, + const LCompilers::PassOptions& pass_options) + :replacer{al, unit, pass_options}{} + + void call_replacer(){ + if( is_a(**current_expr) ){ + replacer.current_expr = current_expr; + replacer.replace_expr(*current_expr); + } + } + void visit_Function(const ASR::Function_t &x){ + if(std::string(x.m_name).find("_lcompilers_optimization_") + !=std::string::npos){ // Don't visit the optimization functions. + return; } - sign_from_value_var = nullptr; - from_sign_from_value = false; } - }; - void pass_replace_sign_from_value(Allocator &al, ASR::TranslationUnit_t &unit, const LCompilers::PassOptions& pass_options) { - SignFromValueVisitor v(al, unit, pass_options); - v.visit_TranslationUnit(unit); + SignFromValueVisitor sign_from_value_visitor(al, unit, pass_options); + sign_from_value_visitor.visit_TranslationUnit(unit); + } diff --git a/src/libasr/pass/subroutine_from_function.cpp b/src/libasr/pass/subroutine_from_function.cpp index b815869046..dc1c73b659 100644 --- a/src/libasr/pass/subroutine_from_function.cpp +++ b/src/libasr/pass/subroutine_from_function.cpp @@ -8,321 +8,77 @@ #include #include -#include -#include - - namespace LCompilers { using ASR::down_cast; using ASR::is_a; -class CreateFunctionFromSubroutine: public PassUtils::PassVisitor { +class CreateFunctionFromSubroutine: public ASR::BaseWalkVisitor { public: - CreateFunctionFromSubroutine(Allocator &al_) : - PassVisitor(al_, nullptr) - { - pass_result.reserve(al, 1); - } - - void visit_TranslationUnit(const ASR::TranslationUnit_t &x) { - // Transform functions returning arrays to subroutines - for (auto &item : x.m_symtab->get_scope()) { - if (is_a(*item.second)) { - PassUtils::handle_fn_return_var(al, - ASR::down_cast(item.second), - PassUtils::is_aggregate_or_array_type); - } - } - - std::vector build_order - = ASRUtils::determine_module_dependencies(x); - for (auto &item : build_order) { - LCOMPILERS_ASSERT(x.m_symtab->get_symbol(item)); - ASR::symbol_t *mod = x.m_symtab->get_symbol(item); - visit_symbol(*mod); - } - // Now visit everything else - for (auto &item : x.m_symtab->get_scope()) { - if (!ASR::is_a(*item.second)) { - this->visit_symbol(*item.second); - } - } - } - - void visit_Module(const ASR::Module_t &x) { - current_scope = x.m_symtab; - for (auto &item : x.m_symtab->get_scope()) { - if (is_a(*item.second)) { - PassUtils::handle_fn_return_var(al, - ASR::down_cast(item.second), - PassUtils::is_aggregate_or_array_type); - } - } + Allocator& al; - // Now visit everything else - for (auto &item : x.m_symtab->get_scope()) { - this->visit_symbol(*item.second); - } + CreateFunctionFromSubroutine(Allocator &al_): al(al_) + { } - void visit_Program(const ASR::Program_t &x) { - std::vector > replace_vec; - // FIXME: this is a hack, we need to pass in a non-const `x`, - // which requires to generate a TransformVisitor. - ASR::Program_t &xx = const_cast(x); - current_scope = xx.m_symtab; - - for (auto &item : x.m_symtab->get_scope()) { - if (is_a(*item.second)) { - PassUtils::handle_fn_return_var(al, - ASR::down_cast(item.second), - PassUtils::is_aggregate_or_array_type); - } - } - - for (auto &item : x.m_symtab->get_scope()) { - if (is_a(*item.second)) { - ASR::AssociateBlock_t *s = ASR::down_cast(item.second); - visit_AssociateBlock(*s); - } - if (is_a(*item.second)) { - visit_Function(*ASR::down_cast(item.second)); - } - } - - current_scope = xx.m_symtab; - transform_stmts(xx.m_body, xx.n_body); - + void visit_Function(const ASR::Function_t& x) { + ASR::Function_t& xx = const_cast(x); + ASR::Function_t* x_ptr = ASR::down_cast(&(xx.base)); + PassUtils::handle_fn_return_var(al, x_ptr, PassUtils::is_aggregate_or_array_or_nonPrimitive_type); } }; class ReplaceFunctionCallWithSubroutineCall: public ASR::BaseExprReplacer { - - private: - - Allocator& al; - int result_counter; - Vec& pass_result; - std::map& resultvar2value; - - public: - - SymbolTable* current_scope; - ASR::expr_t* result_var; - bool& apply_again; - - ReplaceFunctionCallWithSubroutineCall(Allocator& al_, - Vec& pass_result_, - std::map& resultvar2value_, - bool& apply_again_): - al(al_), result_counter(0), pass_result(pass_result_), - resultvar2value(resultvar2value_), result_var(nullptr), - apply_again(apply_again_) {} - - void replace_FunctionCall(ASR::FunctionCall_t* x) { - // The following checks if the name of a function actually - // points to a subroutine. If true this would mean that the - // original function returned an array and is now a subroutine. - // So the current function call will be converted to a subroutine - // call. In short, this check acts as a signal whether to convert - // a function call to a subroutine call. - if (current_scope == nullptr) { - return ; - } - - const Location& loc = x->base.base.loc; - if( ASR::is_a(*ASRUtils::symbol_get_past_external(x->m_name)) && - ASRUtils::symbol_abi(x->m_name) == ASR::abiType::Source ) { - for( size_t i = 0; i < x->n_args; i++ ) { - if( x->m_args[i].m_value && ASR::is_a(*x->m_args[i].m_value) && - ASR::is_a(* - ASR::down_cast(x->m_args[i].m_value)->m_arg) ) { - x->m_args[i].m_value = ASR::down_cast(x->m_args[i].m_value)->m_arg; - } - if( x->m_args[i].m_value && ASR::is_a(*x->m_args[i].m_value) && - ASRUtils::is_array(ASRUtils::expr_type(x->m_args[i].m_value)) ) { - ASR::expr_t* arg_var = PassUtils::create_var(result_counter, - "_func_call_arg_tmp_", loc, x->m_args[i].m_value, al, current_scope); - result_counter += 1; - apply_again = true; - pass_result.push_back(al, ASRUtils::STMT(ASR::make_Assignment_t(al, loc, - arg_var, x->m_args[i].m_value, nullptr))); - x->m_args[i].m_value = arg_var; - } - } - } - - if (x->m_value) { - *current_expr = x->m_value; - return; - } - - ASR::expr_t* result_var_ = nullptr; - if( resultvar2value.find(result_var) != resultvar2value.end() && - resultvar2value[result_var] == *current_expr ) { - result_var_ = result_var; - } - - bool is_return_var_handled = false; - ASR::symbol_t *fn_name = ASRUtils::symbol_get_past_external(x->m_name); - if (ASR::is_a(*fn_name)) { - ASR::Function_t *fn = ASR::down_cast(fn_name); - is_return_var_handled = fn->m_return_var == nullptr; - } - if (is_return_var_handled) { - ASR::ttype_t* result_var_type = ASRUtils::duplicate_type(al, x->m_type); - bool is_allocatable = false; - bool is_func_call_allocatable = false; - bool is_result_var_allocatable = false; - bool is_created_result_var_type_dependent_on_local_vars = false; - ASR::dimension_t* m_dims_ = nullptr; - size_t n_dims_ = 0; - ASR::Function_t *fn = ASR::down_cast(fn_name); - { - // Assuming the `m_return_var` is appended to the `args`. - ASR::symbol_t *v_sym = ASR::down_cast( - fn->m_args[fn->n_args-1])->m_v; - if (ASR::is_a(*v_sym)) { - ASR::Variable_t *v = ASR::down_cast(v_sym); - is_func_call_allocatable = ASR::is_a(*v->m_type); - if( result_var_ != nullptr ) { - is_result_var_allocatable = ASR::is_a(*ASRUtils::expr_type(result_var_)); - is_allocatable = is_func_call_allocatable || is_result_var_allocatable; - } - n_dims_ = ASRUtils::extract_dimensions_from_ttype(result_var_type, m_dims_); - is_created_result_var_type_dependent_on_local_vars = !ASRUtils::is_dimension_dependent_only_on_arguments(m_dims_, n_dims_); - if( is_allocatable || is_created_result_var_type_dependent_on_local_vars ) { - result_var_type = ASRUtils::duplicate_type_with_empty_dims(al, result_var_type); - result_var_type = ASRUtils::TYPE(ASR::make_Allocatable_t( - al, loc, ASRUtils::type_get_past_allocatable( - ASRUtils::type_get_past_pointer(result_var_type)))); - } - } - - // Don't always create this temporary variable - ASR::expr_t* result_var__ = PassUtils::create_var(result_counter, - "_func_call_res", loc, result_var_type, al, current_scope); - result_counter += 1; - *current_expr = result_var__; - } - - if( !is_func_call_allocatable && is_result_var_allocatable ) { - Vec vec_alloc; - vec_alloc.reserve(al, 1); - ASR::alloc_arg_t alloc_arg; - alloc_arg.m_len_expr = nullptr; - alloc_arg.m_type = nullptr; - alloc_arg.loc = loc; - alloc_arg.m_a = *current_expr; - - ASR::FunctionType_t* fn_type = ASRUtils::get_FunctionType(fn); - ASR::ttype_t* output_type = fn_type->m_arg_types[fn_type->n_arg_types - 1]; - ASR::dimension_t* m_dims = nullptr; - size_t n_dims = ASRUtils::extract_dimensions_from_ttype(output_type, m_dims); - Vec vec_dims; - vec_dims.reserve(al, n_dims); - ASRUtils::ReplaceFunctionParamVisitor replace_function_param_visitor(x->m_args); - ASRUtils::ExprStmtDuplicator expr_duplicator(al); - for( size_t i = 0; i < n_dims; i++ ) { - ASR::dimension_t dim; - dim.loc = loc; - dim.m_start = expr_duplicator.duplicate_expr(m_dims[i].m_start); - dim.m_length = expr_duplicator.duplicate_expr(m_dims[i].m_length); - replace_function_param_visitor.current_expr = &dim.m_start; - replace_function_param_visitor.replace_expr(dim.m_start); - replace_function_param_visitor.current_expr = &dim.m_length; - replace_function_param_visitor.replace_expr(dim.m_length); - vec_dims.push_back(al, dim); - } - - alloc_arg.m_dims = vec_dims.p; - alloc_arg.n_dims = vec_dims.n; - vec_alloc.push_back(al, alloc_arg); - Vec to_be_deallocated; - to_be_deallocated.reserve(al, vec_alloc.size()); - for( size_t i = 0; i < vec_alloc.size(); i++ ) { - to_be_deallocated.push_back(al, vec_alloc.p[i].m_a); - } - pass_result.push_back(al, ASRUtils::STMT(ASR::make_ExplicitDeallocate_t( - al, loc, to_be_deallocated.p, to_be_deallocated.size()))); - pass_result.push_back(al, ASRUtils::STMT(ASR::make_Allocate_t( - al, loc, vec_alloc.p, 1, nullptr, nullptr, nullptr))); - } else if( !is_func_call_allocatable && is_created_result_var_type_dependent_on_local_vars ) { - Vec alloc_dims; - alloc_dims.reserve(al, n_dims_); - for( size_t i = 0; i < n_dims_; i++ ) { - ASR::dimension_t alloc_dim; - alloc_dim.loc = loc; - alloc_dim.m_start = make_ConstantWithKind(make_IntegerConstant_t, make_Integer_t, 1, 4, loc); - if( m_dims_[i].m_length ) { - alloc_dim.m_length = m_dims_[i].m_length; - } else { - alloc_dim.m_length = ASRUtils::get_size(result_var, i + 1, al); - } - alloc_dims.push_back(al, alloc_dim); - } - Vec alloc_args; - alloc_args.reserve(al, 1); - ASR::alloc_arg_t alloc_arg; - alloc_arg.loc = loc; - alloc_arg.m_len_expr = nullptr; - alloc_arg.m_type = nullptr; - alloc_arg.m_a = *current_expr; - alloc_arg.m_dims = alloc_dims.p; - alloc_arg.n_dims = alloc_dims.size(); - alloc_args.push_back(al, alloc_arg); - Vec to_be_deallocated; - to_be_deallocated.reserve(al, alloc_args.size()); - for( size_t i = 0; i < alloc_args.size(); i++ ) { - to_be_deallocated.push_back(al, alloc_args.p[i].m_a); - } - pass_result.push_back(al, ASRUtils::STMT(ASR::make_ExplicitDeallocate_t( - al, loc, to_be_deallocated.p, to_be_deallocated.size()))); - pass_result.push_back(al, ASRUtils::STMT(ASR::make_Allocate_t(al, - loc, alloc_args.p, alloc_args.size(), nullptr, nullptr, nullptr))); - } - - Vec s_args; - s_args.reserve(al, x->n_args + 1); - for( size_t i = 0; i < x->n_args; i++ ) { - ASR::expr_t** current_expr_copy_9 = current_expr; - current_expr = &(x->m_args[i].m_value); - self().replace_expr(x->m_args[i].m_value); - current_expr = current_expr_copy_9; - s_args.push_back(al, x->m_args[i]); - } - ASR::call_arg_t result_arg; - result_arg.loc = loc; - result_arg.m_value = *current_expr; - s_args.push_back(al, result_arg); - ASR::stmt_t* subrout_call = ASRUtils::STMT(ASRUtils::make_SubroutineCall_t_util(al, loc, - x->m_name, nullptr, s_args.p, s_args.size(), nullptr, - nullptr, false, false)); - pass_result.push_back(al, subrout_call); - } +private : +public : + Allocator & al; + int result_counter = 0; + SymbolTable* current_scope; + Vec &pass_result; + ReplaceFunctionCallWithSubroutineCall(Allocator& al_, Vec &pass_result_) : + al(al_),pass_result(pass_result_) {} + + void traverse_functionCall_args(ASR::call_arg_t* call_args, size_t call_args_n){ + for(size_t i = 0; i < call_args_n; i++){ + ASR::expr_t** current_expr_copy = current_expr; + current_expr = &call_args[i].m_value; + replace_expr(call_args[i].m_value); + current_expr = current_expr_copy; } + } - void replace_ArrayPhysicalCast(ASR::ArrayPhysicalCast_t* x) { - ASR::BaseExprReplacer::replace_ArrayPhysicalCast(x); - if( (x->m_old == x->m_new && - x->m_old != ASR::array_physical_typeType::DescriptorArray) || - (x->m_old == x->m_new && x->m_old == ASR::array_physical_typeType::DescriptorArray && - (ASR::is_a(*ASRUtils::expr_type(x->m_arg)) || - ASR::is_a(*ASRUtils::expr_type(x->m_arg)))) || - x->m_old != ASRUtils::extract_physical_type(ASRUtils::expr_type(x->m_arg)) ) { - *current_expr = x->m_arg; - } else { - x->m_old = ASRUtils::extract_physical_type(ASRUtils::expr_type(x->m_arg)); - } + void replace_FunctionCall(ASR::FunctionCall_t* x){ + traverse_functionCall_args(x->m_args, x->n_args); + if(PassUtils::is_non_primitive_return_type(x->m_type)){ // Arrays and structs are handled by the array_struct_temporary. No need to check for them here. + // Create variable in current_scope to be holding the return + Deallocate. + ASR::expr_t* result_var = PassUtils::create_var(result_counter++, + "_func_call_res", x->base.base.loc, ASRUtils::duplicate_type(al, x->m_type), al, current_scope); + if(ASRUtils::is_allocatable(result_var)){ + Vec to_be_deallocated; + to_be_deallocated.reserve(al, 1); + to_be_deallocated.push_back(al, result_var); + pass_result.push_back(al, ASRUtils::STMT( + ASR::make_ImplicitDeallocate_t(al, result_var->base.loc, + to_be_deallocated.p, to_be_deallocated.size()))); + } + // Create new call args with `result_var` as last argument capturing return + Create a `subroutineCall`. + Vec new_call_args; + new_call_args.reserve(al,1); + new_call_args.from_pointer_n_copy(al, x->m_args, x->n_args); + new_call_args.push_back(al, {result_var->base.loc, result_var}); + ASR::stmt_t* subrout_call = ASRUtils::STMT(ASRUtils::make_SubroutineCall_t_util(al, x->base.base.loc, + x->m_name, nullptr, new_call_args.p, new_call_args.size(), x->m_dt, + nullptr, false, false)); + // replace functionCall with `result_var` + push subroutineCall into the body. + *current_expr = result_var; + pass_result.push_back(al, subrout_call); } - + } }; - class ReplaceFunctionCallWithSubroutineCallVisitor: public ASR::CallReplacerOnExpressionsVisitor { @@ -331,21 +87,19 @@ class ReplaceFunctionCallWithSubroutineCallVisitor: Allocator& al; Vec pass_result; ReplaceFunctionCallWithSubroutineCall replacer; - Vec* parent_body; - std::map resultvar2value; + bool remove_original_statement = false; + Vec* parent_body = nullptr; - public: - bool apply_again; + public: - ReplaceFunctionCallWithSubroutineCallVisitor(Allocator& al_): - al(al_), replacer(al, pass_result, resultvar2value, apply_again), - parent_body(nullptr), apply_again(false) + ReplaceFunctionCallWithSubroutineCallVisitor(Allocator& al_): al(al_), replacer(al, pass_result) { pass_result.n = 0; + pass_result.reserve(al, 1); } - void call_replacer() { + void call_replacer(){ replacer.current_expr = current_expr; replacer.current_scope = current_scope; replacer.replace_expr(*current_expr); @@ -354,48 +108,75 @@ class ReplaceFunctionCallWithSubroutineCallVisitor: void transform_stmts(ASR::stmt_t **&m_body, size_t &n_body) { Vec body; body.reserve(al, n_body); - if( parent_body ) { - for (size_t j=0; j < pass_result.size(); j++) { - parent_body->push_back(al, pass_result[j]); + if(!pass_result.empty()){ // Flush `pass_result`. + LCOMPILERS_ASSERT(parent_body != nullptr); + for(size_t i = 0; i < pass_result.size(); i++){ + parent_body->push_back(al, pass_result[i]); } - } - for (size_t i=0; i* parent_body_copy = parent_body; + } + bool remove_original_statement_copy = remove_original_statement; + for (size_t i = 0; i < n_body; i++) { parent_body = &body; + remove_original_statement = false; visit_stmt(*m_body[i]); - parent_body = parent_body_copy; - for (size_t j=0; j < pass_result.size(); j++) { - body.push_back(al, pass_result[j]); + if( pass_result.size() > 0 ) { + for (size_t j=0; j < pass_result.size(); j++) { + body.push_back(al, pass_result[j]); + } + pass_result.n = 0; + } + if (!remove_original_statement){ + body.push_back(al, m_body[i]); } - body.push_back(al, m_body[i]); } + remove_original_statement = remove_original_statement_copy; m_body = body.p; n_body = body.size(); - pass_result.n = 0; + } + + bool is_function_call_returning_aggregate_type(ASR::expr_t* m_value) { + bool is_function_call = ASR::is_a(*m_value); + bool is_aggregate_type = (ASRUtils::is_aggregate_type( + ASRUtils::expr_type(m_value)) || + PassUtils::is_aggregate_or_array_type(m_value)); + return is_function_call && is_aggregate_type; } void visit_Assignment(const ASR::Assignment_t &x) { - if( (ASR::is_a(*ASRUtils::expr_type(x.m_target)) && - ASR::is_a(*x.m_value)) || - (ASR::is_a(*x.m_value) || - ASR::is_a(*x.m_value)) ) { + ASR::CallReplacerOnExpressionsVisitor \ + ::visit_Assignment(x); + if( !is_function_call_returning_aggregate_type(x.m_value)) { return ; } - if( ASR::is_a(*x.m_value) ) { - ASR::CallReplacerOnExpressionsVisitor::visit_Assignment(x); + ASR::FunctionCall_t* fc = ASR::down_cast(x.m_value); + if( PassUtils::is_elemental(fc->m_name) && ASRUtils::is_array(fc->m_type) ) { return ; } - - if( PassUtils::is_array(x.m_target) - || ASR::is_a(*x.m_target)) { - replacer.result_var = x.m_target; - ASR::expr_t* original_value = x.m_value; - resultvar2value[replacer.result_var] = original_value; - } - ASR::CallReplacerOnExpressionsVisitor::visit_Assignment(x); + const Location& loc = x.base.base.loc; + Vec s_args; + s_args.reserve(al, fc->n_args + 1); + for( size_t i = 0; i < fc->n_args; i++ ) { + s_args.push_back(al, fc->m_args[i]); + } + if(ASRUtils::is_allocatable(x.m_value) && + ASRUtils::is_allocatable(x.m_target)){ // Make sure to deallocate the argument that will hold the return of function. + Vec to_be_deallocated; + to_be_deallocated.reserve(al, 1); + to_be_deallocated.push_back(al, x.m_target); + pass_result.push_back(al, ASRUtils::STMT( + ASR::make_ImplicitDeallocate_t(al, x.m_target->base.loc, + to_be_deallocated.p, to_be_deallocated.size()))); + } + ASR::call_arg_t result_arg; + result_arg.loc = x.m_target->base.loc; + result_arg.m_value = x.m_target; + s_args.push_back(al, result_arg); + ASR::stmt_t* subrout_call = ASRUtils::STMT(ASRUtils::make_SubroutineCall_t_util(al, loc, + fc->m_name, fc->m_original_name, s_args.p, s_args.size(), fc->m_dt, nullptr, false, false)); + pass_result.push_back(al, subrout_call); + remove_original_statement = true; } }; @@ -404,11 +185,7 @@ void pass_create_subroutine_from_function(Allocator &al, ASR::TranslationUnit_t CreateFunctionFromSubroutine v(al); v.visit_TranslationUnit(unit); ReplaceFunctionCallWithSubroutineCallVisitor u(al); - u.apply_again = true; - while( u.apply_again ) { - u.apply_again = false; - u.visit_TranslationUnit(unit); - } + u.visit_TranslationUnit(unit); PassUtils::UpdateDependenciesVisitor w(al); w.visit_TranslationUnit(unit); } diff --git a/src/libasr/pass/transform_optional_argument_functions.cpp b/src/libasr/pass/transform_optional_argument_functions.cpp index fd33065da2..655a626dde 100644 --- a/src/libasr/pass/transform_optional_argument_functions.cpp +++ b/src/libasr/pass/transform_optional_argument_functions.cpp @@ -9,8 +9,54 @@ #include #include - - +#include + +/* +Need for the pass +================== + +Since LLVM IR does not directly support optional arguments, this ASR pass converts optional +arguments of a function/subroutine and function call or subroutine call to two +non-optional arguments, the first argument is same as the original argument and the second +boolean argument to denote the presence of the original optional argument (i.e. `is_var_present_`). + +Transformation by the pass +========================== + +Consider a function named 'square' with one integer argument 'x' and 'integer(4)' return type, +and with call made to it, it's Fortran code before this pass would look like: + +```fortran +integer(4) function square(x) + integer(4), intent(in), optional :: x ! one optional argument + if (present(x)) then + square = x*x + else + square = 1 + end if +end function square + +print *, square(4) ! function call with present optional argument '4' +``` + +and after `transform_optional_argument_functions` pass it would look like: + +```fortran +integer(4) function square(x, is_x_present_) + logical(4), intent(in) :: is_x_present_ ! boolean non-optional argument + integer(4), intent(in) :: x ! optional argument 'x' is now non-optional argument + if (is_x_present_) then + square = x*x + else + square = 1 + end if +end function square + +print *, square(4, .true.) ! function call with second boolean argument set to .true. +``` + +This same change is done for every optional argument(s) present in the function/subroutine. +*/ namespace LCompilers { using ASR::down_cast; @@ -28,6 +74,34 @@ class ReplacePresentCalls: public ASR::BaseExprReplacer { ReplacePresentCalls(Allocator& al_, ASR::Function_t* f_) : al{al_}, f{f_} {} + void replace_IntrinsicElementalFunction(ASR::IntrinsicElementalFunction_t* x) { + if (x->m_intrinsic_id == static_cast(ASRUtils::IntrinsicElementalFunctions::Present)) { + ASR::symbol_t* present_arg = ASR::down_cast(x->m_args[0])->m_v; + size_t i; + for( i = 0; i < f->n_args; i++ ) { + if( ASR::down_cast(f->m_args[i])->m_v == present_arg ) { + i++; + break; + } + } + + *current_expr = ASRUtils::EXPR(ASR::make_Var_t(al, x->base.base.loc, + ASR::down_cast(f->m_args[i])->m_v)); + return; + } + for (size_t i = 0; i < x->n_args; i++) { + ASR::expr_t** current_expr_copy_12 = current_expr; + current_expr = &(x->m_args[i]); + replace_expr(x->m_args[i]); + current_expr = current_expr_copy_12; + } + replace_ttype(x->m_type); + ASR::expr_t** current_expr_copy_13 = current_expr; + current_expr = &(x->m_value); + replace_expr(x->m_value); + current_expr = current_expr_copy_13; + } + void replace_FunctionCall(ASR::FunctionCall_t* x) { ASR::symbol_t* x_sym = x->m_name; bool replace_func_call = false; @@ -258,8 +332,26 @@ bool fill_new_args(Vec& new_args, Allocator& al, owning_function = ASR::down_cast( ASR::down_cast(scope->asr_owner)); } + ASR::symbol_t* func_sym = ASRUtils::symbol_get_past_external(x.m_name); - if( !ASR::is_a(*func_sym) ) { + if (ASR::is_a(*x.m_name)) { + // possible it is a `procedure(cb) :: call_back` + ASR::Variable_t* v = ASR::down_cast(x.m_name); + LCOMPILERS_ASSERT(ASR::is_a(*v->m_type)); + func_sym = ASRUtils::symbol_get_past_external(v->m_type_declaration); + v->m_type = ASRUtils::duplicate_type(al, ASR::down_cast( + ASRUtils::symbol_get_past_external(v->m_type_declaration))->m_function_signature); + } + bool is_nopass { false }; + bool is_class_procedure { false }; + if (ASR::is_a(*func_sym)) { + ASR::ClassProcedure_t* class_proc = ASR::down_cast(func_sym); + func_sym = class_proc->m_proc; + is_nopass = class_proc->m_is_nopass; + is_class_procedure = true; + } + + if (!ASR::is_a(*func_sym)) { return false; } @@ -278,16 +370,23 @@ bool fill_new_args(Vec& new_args, Allocator& al, return false; } + // when `func` is a ClassProcedure **without** nopass, then the + // first argument of FunctionType is "this" (i.e. the class instance) + // which is depicted in `func.n_args` while isn't depicted in + // `x.n_args` (as it only represents the "FunctionCall" arguments) + // hence to adjust for that, `is_method` introduces an offset + bool is_method = is_class_procedure && (!is_nopass); + new_args.reserve(al, func->n_args); for( size_t i = 0, j = 0; j < func->n_args; j++, i++ ) { - LCOMPILERS_ASSERT(i < x.n_args); if( std::find(sym2optionalargidx[func_sym].begin(), sym2optionalargidx[func_sym].end(), j) != sym2optionalargidx[func_sym].end() ) { ASR::Variable_t* func_arg_j = ASRUtils::EXPR2VAR(func->m_args[j]); - if( x.m_args[i].m_value == nullptr ) { + if( i - is_method >= x.n_args || x.m_args[i - is_method].m_value == nullptr ) { std::string m_arg_i_name = scope->get_unique_name("__libasr_created_variable_"); ASR::ttype_t* arg_type = func_arg_j->m_type; + ASR::symbol_t* arg_decl = func_arg_j->m_type_declaration; if( ASR::is_a(*arg_type) ) { ASR::Array_t* array_t = ASR::down_cast(arg_type); Vec dims; @@ -305,7 +404,7 @@ bool fill_new_args(Vec& new_args, Allocator& al, array_t->m_type, dims.p, dims.size(), ASR::array_physical_typeType::FixedSizeArray)); } ASR::expr_t* m_arg_i = PassUtils::create_auxiliary_variable( - x.m_args[i].loc, m_arg_i_name, al, scope, arg_type); + x.m_args[i - is_method].loc, m_arg_i_name, al, scope, arg_type, ASR::intentType::Local, arg_decl); arg_type = ASRUtils::expr_type(m_arg_i); if( ASRUtils::is_array(arg_type) && ASRUtils::extract_physical_type(arg_type) != @@ -317,36 +416,36 @@ bool fill_new_args(Vec& new_args, Allocator& al, ASRUtils::extract_physical_type(func_arg_j->m_type), m_type, nullptr)); } ASR::call_arg_t m_call_arg_i; - m_call_arg_i.loc = x.m_args[i].loc; + m_call_arg_i.loc = x.m_args[i - is_method].loc; m_call_arg_i.m_value = m_arg_i; new_args.push_back(al, m_call_arg_i); } else { - new_args.push_back(al, x.m_args[i]); + new_args.push_back(al, x.m_args[i - is_method]); } ASR::ttype_t* logical_t = ASRUtils::TYPE(ASR::make_Logical_t(al, - x.m_args[i].loc, 4)); + x.m_args[i - is_method].loc, 4)); ASR::expr_t* is_present = nullptr; - if( x.m_args[i].m_value == nullptr ) { + if( i - is_method >= x.n_args || x.m_args[i - is_method].m_value == nullptr ) { is_present = ASRUtils::EXPR(ASR::make_LogicalConstant_t( - al, x.m_args[i].loc, false, logical_t)); + al, x.m_args[0].loc, false, logical_t)); } else { if( owning_function != nullptr ) { size_t k; bool k_found = false; + ASR::expr_t* original_expr = nullptr; + if (ASR::is_a(*x.m_args[i - is_method].m_value)) { + ASR::ArrayPhysicalCast_t *x_array_cast = ASR::down_cast(x.m_args[i - is_method].m_value); + original_expr = x_array_cast->m_arg; + } for( k = 0; k < owning_function->n_args; k++ ) { - ASR::expr_t* original_expr = nullptr; - if (ASR::is_a(*x.m_args[i].m_value)) { - ASR::ArrayPhysicalCast_t *x_array_cast = ASR::down_cast(x.m_args[i].m_value); - original_expr = x_array_cast->m_arg; - } if( original_expr && ASR::is_a(*original_expr) && ASR::down_cast(owning_function->m_args[k])->m_v == ASR::down_cast(original_expr)->m_v ) { k_found = true; break ; } - if( ASR::is_a(*x.m_args[i].m_value) && ASR::down_cast(owning_function->m_args[k])->m_v == - ASR::down_cast(x.m_args[i].m_value)->m_v ) { + if( ASR::is_a(*x.m_args[i - is_method].m_value) && ASR::down_cast(owning_function->m_args[k])->m_v == + ASR::down_cast(x.m_args[i - is_method].m_value)->m_v ) { k_found = true; break ; } @@ -361,28 +460,35 @@ bool fill_new_args(Vec& new_args, Allocator& al, if( is_present == nullptr ) { is_present = ASRUtils::EXPR(ASR::make_LogicalConstant_t( - al, x.m_args[i].loc, true, logical_t)); + al, x.m_args[i - is_method].loc, true, logical_t)); } } ASR::call_arg_t present_arg; - present_arg.loc = x.m_args[i].loc; - if( x.m_args[i].m_value && - ASRUtils::is_allocatable(x.m_args[i].m_value) && + present_arg.loc = x.m_args[i - is_method].loc; + if( i - is_method < x.n_args && + x.m_args[i - is_method].m_value && + ASRUtils::is_allocatable(x.m_args[i - is_method].m_value) && !ASRUtils::is_allocatable(func_arg_j->m_type) ) { ASR::expr_t* is_allocated = ASRUtils::EXPR(ASR::make_IntrinsicImpureFunction_t( - al, x.m_args[i].loc, static_cast(ASRUtils::IntrinsicImpureFunctions::Allocated), - &x.m_args[i].m_value, 1, 0, logical_t, nullptr)); - is_present = ASRUtils::EXPR(ASR::make_LogicalBinOp_t(al, x.m_args[i].loc, + al, x.m_args[i - is_method].loc, static_cast(ASRUtils::IntrinsicImpureFunctions::Allocated), + &x.m_args[i - is_method].m_value, 1, 0, logical_t, nullptr)); + is_present = ASRUtils::EXPR(ASR::make_LogicalBinOp_t(al, x.m_args[i - is_method].loc, is_allocated, ASR::logicalbinopType::And, is_present, logical_t, nullptr)); } present_arg.m_value = is_present; new_args.push_back(al, present_arg); j++; - } else { - new_args.push_back(al, x.m_args[i]); + } else if (!is_method) { + // not needed to have `i - is_method` can be simply + // `i` as well, just for consistency with code above + new_args.push_back(al, x.m_args[i - is_method]); } + // not needed to pass the class instance to `new_args` } - LCOMPILERS_ASSERT(func->n_args == new_args.size()); + // new_args.size() is either + // - equal to func->n_args + // - one less than func->n_args (in case of ClassProcedure without nopass) + LCOMPILERS_ASSERT(func->n_args == new_args.size() + is_method); return true; } @@ -412,7 +518,7 @@ class ReplaceFunctionCallsWithOptionalArguments: public ASR::BaseExprReplacerbase.base.loc, x->m_name, x->m_original_name, new_args.p, new_args.size(), x->m_type, x->m_value, - x->m_dt)); + x->m_dt, ASRUtils::get_class_proc_nopass_val((*x).m_name))); new_func_calls.insert(*current_expr); } diff --git a/src/libasr/pass/unique_symbols.cpp b/src/libasr/pass/unique_symbols.cpp index 806c5669b9..3161d13b04 100644 --- a/src/libasr/pass/unique_symbols.cpp +++ b/src/libasr/pass/unique_symbols.cpp @@ -6,7 +6,6 @@ #include #include #include -#include #include @@ -246,15 +245,15 @@ class SymbolRenameVisitor: public ASR::BaseWalkVisitor { visit_symbols_2(x); } - void visit_EnumType(const ASR::EnumType_t &x) { + void visit_Enum(const ASR::Enum_t &x) { visit_symbols_2(x); } - void visit_UnionType(const ASR::UnionType_t &x) { + void visit_Union(const ASR::Union_t &x) { visit_symbols_2(x); } - void visit_ClassType(const ASR::ClassType_t &x) { + void visit_Class(const ASR::Class_t &x) { visit_symbols_2(x); } @@ -448,11 +447,11 @@ class UniqueSymbolVisitor: public ASR::BaseWalkVisitor { update_symbols_2(x); } - void visit_EnumType(const ASR::EnumType_t &x) { + void visit_Enum(const ASR::Enum_t &x) { update_symbols_2(x); } - void visit_UnionType(const ASR::UnionType_t &x) { + void visit_Union(const ASR::Union_t &x) { update_symbols_2(x); } @@ -472,8 +471,8 @@ class UniqueSymbolVisitor: public ASR::BaseWalkVisitor { } } - void visit_ClassType(const ASR::ClassType_t &x) { - ASR::ClassType_t& xx = const_cast(x); + void visit_Class(const ASR::Class_t &x) { + ASR::Class_t& xx = const_cast(x); ASR::symbol_t *sym = ASR::down_cast((ASR::asr_t*)&x); if (sym_to_new_name.find(sym) != sym_to_new_name.end()) { xx.m_name = s2c(al, sym_to_new_name[sym]); diff --git a/src/libasr/pass/unused_functions.cpp b/src/libasr/pass/unused_functions.cpp index d91796707d..5895489f64 100644 --- a/src/libasr/pass/unused_functions.cpp +++ b/src/libasr/pass/unused_functions.cpp @@ -36,6 +36,20 @@ class CollectUnusedFunctionsVisitor : if( ASR::is_a(*arg_var->m_v) ) { uint64_t h = get_hash((ASR::asr_t*)arg_var->m_v); fn_used[h] = ASR::down_cast(arg_var->m_v)->m_name; + } else if( ASR::is_a(*arg_var->m_v) ){ + ASR::Variable_t* v = ASR::down_cast(arg_var->m_v); + if(v->m_type_declaration){ + ASR::symbol_t* func = v->m_type_declaration; + if(ASR::is_a(*func)){ + uint64_t h = get_hash((ASR::asr_t*)func); + fn_used[h] = ASR::down_cast(func)->m_name; + func = ASR::down_cast(func)->m_external; + } + if(ASR::is_a(*func)){ + uint64_t h = get_hash((ASR::asr_t*)func); + fn_used[h] = ASR::down_cast(func)->m_name; + } + } } } diff --git a/src/libasr/pass/update_array_dim_intrinsic_calls.cpp b/src/libasr/pass/update_array_dim_intrinsic_calls.cpp index 845667aa08..11f472779d 100644 --- a/src/libasr/pass/update_array_dim_intrinsic_calls.cpp +++ b/src/libasr/pass/update_array_dim_intrinsic_calls.cpp @@ -4,11 +4,9 @@ #include #include #include +#include #include -#include -#include - namespace LCompilers { @@ -57,13 +55,20 @@ class ReplaceArrayDimIntrinsicCalls: public ASR::BaseExprReplacer(*x->m_v) || + ASR::expr_t* x_m_v = x->m_v; + if ( ASR::is_a(*x_m_v) ) { + ASR::Cast_t* cast = ASR::down_cast(x_m_v); + if( ASR::is_a(*cast->m_arg) ) { + x_m_v = cast->m_arg; + } + } + if( !ASR::is_a(*x_m_v) || (x->m_dim != nullptr && !ASRUtils::is_value_constant(x->m_dim)) ) { return ; } - ASR::Variable_t* v = ASRUtils::EXPR2VAR(x->m_v); - ASR::ttype_t* array_type = ASRUtils::expr_type(x->m_v); + ASR::Variable_t* v = ASRUtils::EXPR2VAR(x_m_v); + ASR::ttype_t* array_type = ASRUtils::expr_type(x_m_v); ASR::dimension_t* dims = nullptr; int n = ASRUtils::extract_dimensions_from_ttype(array_type, dims); bool is_argument = v->m_intent == ASRUtils::intent_in || v->m_intent == ASRUtils::intent_out || v->m_intent == ASRUtils::intent_inout; @@ -109,7 +114,9 @@ class ReplaceArrayDimIntrinsicCalls: public ASR::BaseExprReplacerm_dim, dim); if( x->m_bound == ASR::arrayboundType::LBound ) { + ASRUtils::ASRBuilder b(al, x->base.base.loc); *current_expr = dims[dim - 1].m_start; + *current_expr = b.t2t(*current_expr, ASRUtils::expr_type(*current_expr), x->m_type); } else { ASR::expr_t* ub = ASRUtils::EXPR(ASR::make_IntegerBinOp_t(al, x->base.base.loc, dims[dim - 1].m_length, diff --git a/src/libasr/pass/where.cpp b/src/libasr/pass/where.cpp index d893d69582..7f213c961c 100644 --- a/src/libasr/pass/where.cpp +++ b/src/libasr/pass/where.cpp @@ -36,118 +36,32 @@ The function `pass_replace_where` transforms the ASR tree in-place. end do */ -uint64_t static inline get_hash(ASR::asr_t *node) -{ - return (uint64_t)node; -} - -using ASR::down_cast; -using ASR::is_a; +class TransformWhereVisitor: public ASR::CallReplacerOnExpressionsVisitor { + private: -class ReplaceVar : public ASR::BaseExprReplacer -{ -public: Allocator& al; - SymbolTable* current_scope; - Vec idx_vars; - std::map return_var_hash; - ReplaceVar(Allocator &al_) : al(al_), current_scope(nullptr) {} - - void replace_Var(ASR::Var_t* x) { - ASR::expr_t* expr_ = ASRUtils::EXPR(ASR::make_Var_t(al, x->base.base.loc, x->m_v)); - *current_expr = expr_; - if (ASRUtils::is_array(ASRUtils::expr_type(expr_))) { - ASR::expr_t* new_expr_ = PassUtils::create_array_ref(expr_, idx_vars, al, current_scope); - *current_expr = new_expr_; - } - } - - void replace_ArrayPhysicalCast(ASR::ArrayPhysicalCast_t* x) { - ASR::BaseExprReplacer::replace_ArrayPhysicalCast(x); - if( !ASRUtils::is_array(ASRUtils::expr_type(x->m_arg)) ) { - *current_expr = x->m_arg; - } - } - - void replace_FunctionCall(ASR::FunctionCall_t* x) { - uint64_t h = get_hash((ASR::asr_t*) x->m_name); - if (return_var_hash.find(h) != return_var_hash.end()) { - *current_expr = PassUtils::create_array_ref(return_var_hash[h], idx_vars, al, current_scope); - } - } - - #define BinOpReplacement(Constructor) ASR::expr_t** current_expr_copy = current_expr; \ - current_expr = const_cast(&(x->m_left)); \ - this->replace_expr(x->m_left); \ - ASR::expr_t* left = *current_expr; \ - current_expr = current_expr_copy; \ - current_expr = const_cast(&(x->m_right)); \ - this->replace_expr(x->m_right); \ - ASR::expr_t* right = *current_expr; \ - current_expr = current_expr_copy; \ - *current_expr = ASRUtils::EXPR(ASR::Constructor(al, x->base.base.loc, \ - left, x->m_op, right, x->m_type, nullptr)); \ - - void replace_IntegerBinOp(ASR::IntegerBinOp_t* x) { - BinOpReplacement(make_IntegerBinOp_t) - } - - void replace_RealBinOp(ASR::RealBinOp_t* x) { - BinOpReplacement(make_RealBinOp_t) - } - - void replace_IntrinsicElementalFunction(ASR::IntrinsicElementalFunction_t* x) { - Vec args; - args.reserve(al, x->n_args); - for (size_t i=0; in_args; i++) { - ASR::expr_t* arg = x->m_args[i]; - current_expr = const_cast(&(arg)); - this->replace_expr(arg); - args.push_back(al, *current_expr); - } - ASR::ttype_t* type = ASRUtils::expr_type(args[0]); - ASR::expr_t* new_expr = ASRUtils::EXPR( - ASRUtils::make_IntrinsicElementalFunction_t_util(al, x->base.base.loc, - x->m_intrinsic_id, args.p, x->n_args, x->m_overload_id, type, x->m_value)); - *current_expr = new_expr; - } - - void replace_Array(ASR::Array_t */*x*/) { - // pass - } -}; - -class VarVisitor : public ASR::CallReplacerOnExpressionsVisitor -{ -public: - - Allocator &al; - ReplaceVar replacer; - std::map> &assignment_hash; - std::map &return_var_hash; Vec pass_result; + Vec* parent_body; - VarVisitor(Allocator &al_, std::map> &assignment_hash, std::map &return_var_hash) : - al(al_), replacer(al_), assignment_hash(assignment_hash), return_var_hash(return_var_hash) { - pass_result.reserve(al, 1); - } + public: - void call_replacer_(Vec idx_vars_) { - replacer.current_expr = current_expr; - replacer.current_scope = current_scope; - replacer.idx_vars = idx_vars_; - replacer.return_var_hash = return_var_hash; - replacer.replace_expr(*current_expr); + TransformWhereVisitor(Allocator& al_): + al(al_), parent_body(nullptr) { + pass_result.n = 0; + pass_result.reserve(al, 0); } void transform_stmts(ASR::stmt_t **&m_body, size_t &n_body) { Vec body; - body.reserve(al, n_body); - for (size_t i=0; i* parent_body_copy = parent_body; + parent_body = &body; visit_stmt(*m_body[i]); - if (stmt_->type == ASR::stmtType::Assignment && pass_result.size() > 0) { + parent_body = parent_body_copy; + if( pass_result.size() > 0 ) { for (size_t j=0; j < pass_result.size(); j++) { body.push_back(al, pass_result[j]); } @@ -157,201 +71,52 @@ class VarVisitor : public ASR::CallReplacerOnExpressionsVisitor } m_body = body.p; n_body = body.size(); + pass_result.n = 0; } - void visit_Assignment(const ASR::Assignment_t &x) { - uint64_t h = get_hash((ASR::asr_t*) &x); - if (assignment_hash.find(h) == assignment_hash.end()) { - return; - } - ASR::expr_t** current_expr_copy = current_expr; - current_expr = const_cast(&(x.m_target)); - this->call_replacer_(assignment_hash[h]); - ASR::expr_t* target = *replacer.current_expr; - current_expr = current_expr_copy; - this->visit_expr(*x.m_target); - current_expr = const_cast(&(x.m_value)); - this->call_replacer_(assignment_hash[h]); - ASR::expr_t* value = *replacer.current_expr; - current_expr = current_expr_copy; - this->visit_expr(*x.m_value); - if( !ASRUtils::is_array(ASRUtils::expr_type(target)) ) { - if( ASR::is_a(*value) ) { - value = ASR::down_cast(value)->m_array; - } - } - ASR::stmt_t* tmp_stmt = ASRUtils::STMT(ASR::make_Assignment_t(al, x.base.base.loc, target, value, nullptr)); - pass_result.push_back(al, tmp_stmt); - } -}; - - -class WhereVisitor : public PassUtils::PassVisitor -{ -public: - std::map> &assignment_hash; - std::map &return_var_hash; - WhereVisitor(Allocator &al, std::map> &assignment_hash, std::map &return_var_hash) : - PassVisitor(al, nullptr), assignment_hash(assignment_hash), return_var_hash(return_var_hash) { - pass_result.reserve(al, 1); - } - - ASR::stmt_t* handle_If(ASR::Where_t& x, ASR::expr_t* test, ASR::expr_t* var, Location& loc, Vec idx_vars) { - ASR::IntegerCompare_t* int_cmp = nullptr; - ASR::RealCompare_t* real_cmp = nullptr; - ASR::expr_t* left, *right; - bool is_right_array = false; - ASR::ttype_t* logical_type = ASRUtils::TYPE(ASR::make_Logical_t(al, loc, 4)); - - if (ASR::is_a(*test)) { - int_cmp = ASR::down_cast(test); - left = int_cmp->m_left; - right = int_cmp->m_right; - } else if (ASR::is_a(*test)) { - real_cmp = ASR::down_cast(test); - left = real_cmp->m_left; - right = real_cmp->m_right; - } else { - throw LCompilersException("Unsupported type"); - } - - if (ASRUtils::is_array(ASRUtils::expr_type(right))) { - is_right_array = true; - } - - ASR::expr_t* left_array = PassUtils::create_array_ref(left, idx_vars, al, current_scope); - ASR::expr_t* right_array = PassUtils::create_array_ref(right, idx_vars, al, current_scope); - - ASR::expr_t* test_new = ASRUtils::EXPR( - real_cmp?ASR::make_RealCompare_t(al, loc, left_array, real_cmp->m_op, is_right_array?right_array:right, - logical_type, nullptr): - ASR::make_IntegerCompare_t(al, loc, left_array, int_cmp->m_op, is_right_array?right_array:right, - logical_type, nullptr)); - - - Vec if_body; - if_body.reserve(al, x.n_body); - for (size_t i = 0; i < x.n_body; i++) { - ASR::stmt_t* stmt = x.m_body[i]; - if (stmt->type == ASR::stmtType::Assignment) { - ASR::Assignment_t* assign_ = ASR::down_cast(stmt); - uint64_t h = get_hash((ASR::asr_t*) assign_); - assignment_hash[h] = idx_vars; + ASR::stmt_t* transform_Where_to_If(const ASR::Where_t& x) { + Vec or_else_vec; or_else_vec.reserve(al, x.n_orelse); + Vec body_vec; body_vec.reserve(al, x.n_body); + for( size_t i = 0; i < x.n_body; i++ ) { + if( ASR::is_a(*x.m_body[i]) ) { + LCOMPILERS_ASSERT(parent_body != nullptr); + parent_body->push_back(al, x.m_body[i]); + } else if( ASR::is_a(*x.m_body[i]) ) { + ASR::stmt_t* body_stmt = transform_Where_to_If( + *ASR::down_cast(x.m_body[i])); + body_vec.push_back(al, body_stmt); + } else { + body_vec.push_back(al, x.m_body[i]); } - if_body.push_back(al, stmt); } - - Vec orelse_body; - orelse_body.reserve(al, x.n_orelse); - for (size_t i = 0; i < x.n_orelse; i++) { - if (ASR::is_a(*x.m_orelse[i])) { - ASR::Where_t* where = ASR::down_cast(x.m_orelse[i]); - ASR::stmt_t* if_stmt = handle_If(*where, where->m_test, var, where->base.base.loc, idx_vars); - orelse_body.push_back(al, if_stmt); + for( size_t i = 0; i < x.n_orelse; i++ ) { + if( ASR::is_a(*x.m_orelse[i]) ) { + LCOMPILERS_ASSERT(parent_body != nullptr); + parent_body->push_back(al, x.m_orelse[i]); + } else if( ASR::is_a(*x.m_orelse[i]) ) { + ASR::stmt_t* or_else_stmt = transform_Where_to_If( + *ASR::down_cast(x.m_orelse[i])); + or_else_vec.push_back(al, or_else_stmt); } else { - ASR::stmt_t* stmt = x.m_orelse[i]; - if (stmt->type == ASR::stmtType::Assignment) { - ASR::Assignment_t* assign_ = ASR::down_cast(stmt); - uint64_t h = get_hash((ASR::asr_t*) assign_); - assignment_hash[h] = idx_vars; - } - orelse_body.push_back(al, stmt); + or_else_vec.push_back(al, x.m_orelse[i]); } } - ASR::stmt_t* if_stmt = ASRUtils::STMT(ASR::make_If_t(al, loc, test_new, if_body.p, if_body.size(), orelse_body.p, orelse_body.size())); - return if_stmt; + + return ASRUtils::STMT(ASR::make_If_t(al, x.base.base.loc, + x.m_test, body_vec.p, body_vec.size(), or_else_vec.p, or_else_vec.size())); } void visit_Where(const ASR::Where_t& x) { - ASR::Where_t& xx = const_cast(x); - Location loc = x.base.base.loc; - ASR::expr_t* test = x.m_test; - ASR::IntegerCompare_t* int_cmp = nullptr; - ASR::RealCompare_t* real_cmp = nullptr; - ASR::expr_t* left; - ASR::expr_t* opt_left = nullptr; - ASR::stmt_t* assign_stmt = nullptr; - - if (ASR::is_a(*test)) { - int_cmp = ASR::down_cast(test); - left = int_cmp->m_left; - } else if (ASR::is_a(*test)) { - real_cmp = ASR::down_cast(test); - left = real_cmp->m_left; - } else { - throw LCompilersException("Unsupported type, " + std::to_string(test->type)); - } - - // Construct a do loop - ASR::stmt_t* doloop = nullptr; - - // create a index variable - Vec idx_vars; - PassUtils::create_idx_vars(idx_vars, 1, loc, al, current_scope); - ASR::expr_t* var = idx_vars[0]; - - ASR::ttype_t* int32_type = ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)); - - if (ASR::is_a(*left)) { - // Create an assignment `return_var = left` and replace function call with return_var - ASR::FunctionCall_t* fc = ASR::down_cast(left); - uint64_t h = get_hash((ASR::asr_t*) fc->m_name); - ASR::Function_t* fn = ASR::down_cast(fc->m_name); - ASR::expr_t* return_var_expr = fn->m_return_var; - ASR::Variable_t* return_var = ASRUtils::EXPR2VAR(return_var_expr); - ASR::expr_t* new_return_var_expr = PassUtils::create_var(1, - return_var->m_name, return_var->base.base.loc, - return_var->m_type, al, current_scope); - assign_stmt = ASRUtils::STMT(ASR::make_Assignment_t(al, loc, new_return_var_expr, left, nullptr)); - opt_left = new_return_var_expr; - return_var_hash[h] = opt_left; - } - - if (opt_left && ASR::is_a(*test)) { - int_cmp = ASR::down_cast(test); - int_cmp->m_left = opt_left; - } - if (opt_left && ASR::is_a(*test)) { - real_cmp = ASR::down_cast(test); - real_cmp->m_left = opt_left; - } - - // create do loop head - ASR::do_loop_head_t head; - head.loc = loc; - head.m_v = var; - head.m_start = PassUtils::get_bound(opt_left?opt_left:left, 1, "lbound", al); - head.m_end = PassUtils::get_bound(opt_left?opt_left:left, 1, "ubound", al); - head.m_increment = ASRUtils::EXPR(ASR::make_IntegerConstant_t(al, loc, 1, int32_type)); - - // create do loop body - Vec do_loop_body; - do_loop_body.reserve(al, 1); - - // create an if statement - ASR::stmt_t* if_stmt = handle_If(xx, int_cmp?ASRUtils::EXPR((ASR::asr_t*)int_cmp):ASRUtils::EXPR((ASR::asr_t*)real_cmp), var, loc, idx_vars); - if (assign_stmt) { - pass_result.push_back(al, assign_stmt); - } - do_loop_body.push_back(al, if_stmt); - - doloop = ASRUtils::STMT(ASR::make_DoLoop_t(al, loc, 0, head, do_loop_body.p, do_loop_body.size(), nullptr, 0)); - pass_result.push_back(al, doloop); + ASR::stmt_t* if_stmt = transform_Where_to_If(x); + pass_result.push_back(al, if_stmt); } + }; void pass_replace_where(Allocator &al, ASR::TranslationUnit_t &unit, const LCompilers::PassOptions& /*pass_options*/) { - std::map> assignment_hash; - std::map return_var_hash; - WhereVisitor v(al, assignment_hash, return_var_hash); + TransformWhereVisitor v(al); v.visit_TranslationUnit(unit); - if (assignment_hash.size() > 0) { - VarVisitor w(al, assignment_hash, return_var_hash); - w.visit_TranslationUnit(unit); - PassUtils::UpdateDependenciesVisitor x(al); - x.visit_TranslationUnit(unit); - } } diff --git a/src/libasr/pass/while_else.cpp b/src/libasr/pass/while_else.cpp index 07b2744a85..468200607d 100644 --- a/src/libasr/pass/while_else.cpp +++ b/src/libasr/pass/while_else.cpp @@ -73,8 +73,6 @@ class WhileLoopVisitor : public ASR::StatementWalkVisitor Creating a flag variable in case of a while-else loop Creates an if statement after the loop to check if the flag was changed */ - ASR::WhileLoop_t &xx = const_cast(x); - transform_stmts(xx.m_body, xx.n_body); if (x.n_orelse > 0) { Vec result; result.reserve(al, 3); @@ -86,7 +84,7 @@ class WhileLoopVisitor : public ASR::StatementWalkVisitor ASR::ttype_t *bool_type = ASRUtils::TYPE(ASR::make_Logical_t(al, loc, 4)); ASR::expr_t *true_expr = ASRUtils::EXPR(ASR::make_LogicalConstant_t(al, loc, true, bool_type)); ASR::symbol_t *flag_symbol = LCompilers::ASR::down_cast( - ASR::make_Variable_t( + ASRUtils::make_Variable_t_util( al, loc, target_scope, s.c_str(al), nullptr, 0, ASR::intentType::Local, nullptr, nullptr, ASR::storage_typeType::Default, bool_type, nullptr, diff --git a/src/libasr/pass/while_else.h b/src/libasr/pass/while_else.h index 13ebb2f604..8f43792e84 100644 --- a/src/libasr/pass/while_else.h +++ b/src/libasr/pass/while_else.h @@ -11,4 +11,3 @@ void pass_while_else(Allocator &al, ASR::TranslationUnit_t &unit, } // namespace LCompilers #endif // LIBASR_PASS_WHILE_ELSE_H - diff --git a/src/libasr/pickle.cpp b/src/libasr/pickle.cpp index 79e71713a2..6a1aebf704 100644 --- a/src/libasr/pickle.cpp +++ b/src/libasr/pickle.cpp @@ -2,7 +2,11 @@ #include #include #include +#include #include +#include +#include +#include namespace LCompilers { @@ -48,6 +52,8 @@ class ASRPickleVisitor : } s.append(" "); this->visit_ttype(*x.m_type); + s.append(" "); + this->visit_integerbozType(x.m_intboz_type); s.append(")"); } void visit_Module(const ASR::Module_t &x) { @@ -70,6 +76,62 @@ class ASRPickleVisitor : ASR::PickleBaseVisitor::visit_Module(x); }; } + void visit_ArrayConstant(const ASR::ArrayConstant_t &x) { + s.append("("); + if (use_colors) { + s.append(color(style::bold)); + s.append(color(fg::magenta)); + } + s.append("ArrayConstant"); + if (use_colors) { + s.append(color(fg::reset)); + s.append(color(style::reset)); + } + if(indent) { + inc_indent(); + s.append("\n" + indented); + } else { + s.append(" "); + } + s.append(std::to_string(x.m_n_data)); + if(indent) s.append("\n" + indented); + else s.append(" "); + s.append("["); + int size = x.m_n_data / (ASRUtils::is_character(*x.m_type) ? + ASR::down_cast(ASRUtils::type_get_past_array(x.m_type))->m_len : + ASRUtils::extract_kind_from_ttype_t(x.m_type)); + int curr = 0; + for (int i = 0; i < 3; i++) { + if (curr < size) { + if (i > 0) s.append(", "); + s.append(ASRUtils::fetch_ArrayConstant_value(x, curr)); + curr++; + } + } + if (size > 6) { + s.append(", ...."); + curr = size - 3; + } + for (int i = 0; i < 3; i++) { + if (curr < size) { + s.append(", "); + s.append(ASRUtils::fetch_ArrayConstant_value(x, curr)); + curr++; + } + } + s.append("]"); + if(indent) s.append("\n" + indented); + else s.append(" "); + this->visit_ttype(*x.m_type); + if(indent) s.append("\n" + indented); + else s.append(" "); + visit_arraystorageType(x.m_storage_format); + if(indent) { + dec_indent(); + s.append("\n" + indented); + } + s.append(")"); + } std::string convert_intrinsic_id(int x) { std::string s; @@ -85,6 +147,20 @@ class ASRPickleVisitor : return s; } + std::string convert_sub_intrinsic_id(int x) { + std::string s; + if (use_colors) { + s.append(color(style::bold)); + s.append(color(fg::green)); + } + s.append(ASRUtils::get_intrinsic_subroutine_name(x)); + if (use_colors) { + s.append(color(fg::reset)); + s.append(color(style::reset)); + } + return s; + } + std::string convert_impure_intrinsic_id(int x) { std::string s; if (use_colors) { diff --git a/src/libasr/runtime/lfortran_intrinsics.c b/src/libasr/runtime/lfortran_intrinsics.c index 8bcbe893cb..9781bfd404 100644 --- a/src/libasr/runtime/lfortran_intrinsics.c +++ b/src/libasr/runtime/lfortran_intrinsics.c @@ -10,6 +10,7 @@ #include #include +#define PI 3.14159265358979323846 #if defined(_WIN32) # include # include @@ -18,11 +19,20 @@ # include #endif +#if defined(__APPLE__) +# include +#endif + #include #include #ifdef HAVE_RUNTIME_STACKTRACE +#ifdef COMPILE_TO_WASM + #undef HAVE_LFORTRAN_MACHO + #undef HAVE_LFORTRAN_LINK +#endif + #ifdef HAVE_LFORTRAN_LINK // For dl_iterate_phdr() functionality # include @@ -108,9 +118,10 @@ LFORTRAN_API void _lfortran_random_number(int n, double *v) } } -LFORTRAN_API void _lfortran_init_random_seed(unsigned seed) +LFORTRAN_API int _lfortran_init_random_seed(unsigned seed) { srand(seed); + return seed; } LFORTRAN_API void _lfortran_init_random_clock() @@ -150,7 +161,18 @@ LFORTRAN_API void _lfortran_printf(const char* format, ...) { va_list args; va_start(args, format); - vfprintf(stdout, format, args); + char* str = va_arg(args, char*); + char* end = va_arg(args, char*); + if(str == NULL){ + str = " "; // dummy output + } + // Detect "\b" to raise error + if(str[0] == '\b'){ + str = str+1; + fprintf(stderr, "%s", str); + exit(1); + } + fprintf(stdout, format, str, end); fflush(stdout); va_end(args); } @@ -238,95 +260,187 @@ void handle_logical(char* format, bool val, char** result) { } void handle_float(char* format, double val, char** result) { + if (strcmp(format,"f-64") == 0){ //use c formatting. + char* float_str = (char*)malloc(50 * sizeof(char)); + sprintf(float_str,"%23.17e",val); + *result = append_to_string(*result,float_str); + free(float_str); + return; + } else if(strcmp(format,"f-32") == 0){ //use c formatting. + char* float_str = (char*)malloc(40 * sizeof(char)); + sprintf(float_str,"%13.8e",val); + *result = append_to_string(*result,float_str); + free(float_str); + return; + } int width = 0, decimal_digits = 0; long integer_part = (long)fabs(val); - double decimal_part = fabs(val) - labs(integer_part); + double decimal_part = fabs(val) - integer_part; int sign_width = (val < 0) ? 1 : 0; - int integer_length = (integer_part == 0) ? 1 : (int)log10(llabs(integer_part)) + 1; + int integer_length = (integer_part == 0) ? 1 : (int)log10(integer_part) + 1; + + // parsing the format + char* dot_pos = strchr(format, '.'); + if (dot_pos != NULL) { + decimal_digits = atoi(dot_pos + 1); + width = atoi(format + 1); + } + + double rounding_factor = pow(10, -decimal_digits); + decimal_part = round(decimal_part / rounding_factor) * rounding_factor; + + if (decimal_part >= 1.0) { + integer_part += 1; + decimal_part -= 1.0; + } + char int_str[64]; sprintf(int_str, "%ld", integer_part); - char dec_str[64]; + // TODO: This will work for up to `F65.60` but will fail for: // print "(F67.62)", 1.23456789101112e-62_8 - sprintf(dec_str, "%.*lf", (60-integer_length), decimal_part); - memmove(dec_str,dec_str+2,strlen(dec_str)); + char dec_str[64]; + sprintf(dec_str, "%.*f", decimal_digits, decimal_part); + // removing the leading "0." from the formatted decimal part + memmove(dec_str, dec_str + 2, strlen(dec_str)); - char* dot_pos = strchr(format, '.'); - decimal_digits = atoi(++dot_pos); - width = atoi(format + 1); - if (dot_pos != NULL) { - if (width == 0) { - if (decimal_digits == 0) { - width = integer_length + sign_width + 1; - } else { - width = integer_length + sign_width + decimal_digits + 1; - } - } + // Determine total length needed + int total_length = sign_width + integer_length + 1 + decimal_digits; + if (width == 0) { + width = total_length; } - char formatted_value[64] = ""; - int spaces = width - decimal_digits - sign_width - integer_length - 1; + + char formatted_value[128] = ""; + int spaces = width - total_length; for (int i = 0; i < spaces; i++) { strcat(formatted_value, " "); } if (val < 0) { - strcat(formatted_value,"-"); - } - if ((integer_part != 0 || (atoi(format + 1) != 0 || atoi(dot_pos) == 0))) { - strcat(formatted_value,int_str); + strcat(formatted_value, "-"); } - strcat(formatted_value,"."); - if (decimal_part == 0) { - for(int i=0;i width) { - for(int i=0; i ptr) end_ptr--; + *(end_ptr + 1) = '\0'; + } + + // Allocate a larger buffer + char formatted_value[256]; // Increased size to accommodate larger exponent values + int n = snprintf(formatted_value, sizeof(formatted_value), "%s%s%+03d", val_str, c, exponent); + if (n >= sizeof(formatted_value)) { + fprintf(stderr, "Error: output was truncated. Needed %d characters.\n", n); + } + + // Handle width and padding + char* final_result = malloc(width + 1); + int padding = width - strlen(formatted_value); + if (padding > 0) { + memset(final_result, ' ', padding); + strcpy(final_result + padding, formatted_value); + } else { + strncpy(final_result, formatted_value, width); + final_result[width] = '\0'; + } + + // Assign the result to the output parameter + *result = final_result; +} + +void parse_deciml_format(char* format, int* width_digits, int* decimal_digits, int* exp_digits) { + *width_digits = -1; + *decimal_digits = -1; + *exp_digits = -1; + + char *width_digits_pos = format; + while (!isdigit(*width_digits_pos)) { + width_digits_pos++; + } + *width_digits = atoi(width_digits_pos); + + // dot_pos exists, we previous checked for it in `parse_fortran_format` + char *dot_pos = strchr(format, '.'); + *decimal_digits = atoi(++dot_pos); + + char *exp_pos = strchr(dot_pos, 'e'); + if(exp_pos != NULL) { + *exp_digits = atoi(++exp_pos); + } +} + + void handle_decimal(char* format, double val, int scale, char** result, char* c) { // Consider an example: write(*, "(es10.2)") 1.123e+10 // format = "es10.2", val = 11230000128.00, scale = 0, c = "E" - int width = 0, decimal_digits = 0; + + int width_digits, decimal_digits, exp_digits; + parse_deciml_format(format, &width_digits, &decimal_digits, &exp_digits); + + int width = width_digits; int sign_width = (val < 0) ? 1 : 0; // sign_width = 0 double integer_part = trunc(val); int integer_length = (integer_part == 0) ? 1 : (int)log10(fabs(integer_part)) + 1; // integer_part = 11230000128, integer_length = 11 - - char *num_pos = format ,*dot_pos = strchr(format, '.'); - decimal_digits = atoi(++dot_pos); - while(!isdigit(*num_pos)) num_pos++; - width = atoi(num_pos); // width = 10, decimal_digits = 2 - char val_str[128]; + #define MAX_SIZE 128 + char val_str[MAX_SIZE] = ""; + int avail_len_decimal_digits = MAX_SIZE - integer_length - sign_width - 2 /* 0.*/; // TODO: This will work for up to `E65.60` but will fail for: // print "(E67.62)", 1.23456789101112e-62_8 - sprintf(val_str, "%.*lf", (60-integer_length), val); + sprintf(val_str, "%.*lf", avail_len_decimal_digits, val); // val_str = "11230000128.00..." int i = strlen(val_str) - 1; @@ -337,9 +451,8 @@ void handle_decimal(char* format, double val, int scale, char** result, char* c) // val_str = "11230000128." int exp = 2; - char* exp_loc = strchr(num_pos, 'e'); - if (exp_loc != NULL) { - exp = atoi(++exp_loc); + if (exp_digits != -1) { + exp = exp_digits; } // exp = 2; @@ -355,6 +468,9 @@ void handle_decimal(char* format, double val, int scale, char** result, char* c) } int decimal = 1; + if (val < 0 && val_str[0] == '0') { + decimal = 0; + } while (val_str[0] == '0') { // Used for the case: 1.123e-10 memmove(val_str, val_str + 1, strlen(val_str)); @@ -368,42 +484,47 @@ void handle_decimal(char* format, double val, int scale, char** result, char* c) // decimal = -10, case: 1.123e-10 } - if (dot_pos != NULL) { - if (width == 0) { - if (decimal_digits == 0) { - width = 14 + sign_width; - decimal_digits = 9; - } else { - width = decimal_digits + 5 + sign_width; - } - } - if (decimal_digits > width - 3) { - perror("Specified width is not enough for the specified number of decimal digits.\n"); - } + char exponent[12]; + if (width_digits == 0) { + sprintf(exponent, "%+02d", (integer_length > 0 && integer_part != 0 ? integer_length - scale : decimal)); } else { - width = atoi(format + 1); + sprintf(exponent, "%+0*d", exp+1, (integer_length > 0 && integer_part != 0 ? integer_length - scale : decimal)); + // exponent = "+10" } - if (decimal_digits > strlen(val_str)) { - int k = decimal_digits - (strlen(val_str) - integer_length); - for(int i=0; i < k; i++) { - strcat(val_str, "0"); + + int FIXED_CHARS_LENGTH = 1 + 1 + 1; // digit, ., E + int exp_length = strlen(exponent); + + if (width == 0) { + if (decimal_digits == 0) { + decimal_digits = 9; } + width = sign_width + decimal_digits + FIXED_CHARS_LENGTH + exp_length; + } + if (decimal_digits > width - FIXED_CHARS_LENGTH) { + perror("Specified width is not enough for the specified number of decimal digits.\n"); + } + int zeroes_needed = decimal_digits - (strlen(val_str) - integer_length); + for(int i=0; i < zeroes_needed; i++) { + strcat(val_str, "0"); } char formatted_value[64] = ""; - int spaces = width - sign_width - decimal_digits - 6; + int spaces = width - (sign_width + decimal_digits + FIXED_CHARS_LENGTH + exp_length); // spaces = 2 - if (scale > 1) { - decimal_digits -= scale - 1; - } for (int i = 0; i < spaces; i++) { strcat(formatted_value, " "); } + if (scale > 1) { + decimal_digits -= scale - 1; + } + if (sign_width == 1) { // adds `-` (negative) sign strcat(formatted_value, "-"); } + if (scale <= 0) { strcat(formatted_value, "0."); for (int k = 0; k < abs(scale); k++) { @@ -450,13 +571,7 @@ void handle_decimal(char* format, double val, int scale, char** result, char* c) strcat(formatted_value, c); // formatted_value = " 1.12E" - char exponent[12]; - if (atoi(num_pos) == 0) { - sprintf(exponent, "%+02d", (integer_length > 0 && integer_part != 0 ? integer_length - scale : decimal)); - } else { - sprintf(exponent, "%+0*d", exp+1, (integer_length > 0 && integer_part != 0 ? integer_length - scale : decimal)); - // exponent = "+10" - } + strcat(formatted_value, exponent); // formatted_value = " 1.12E+10" @@ -478,7 +593,59 @@ void handle_decimal(char* format, double val, int scale, char** result, char* c) } } -char** parse_fortran_format(char* format, int *count, int *item_start) { +/* +Ignore blank space characters within format specification, except +within character string edit descriptor + +E.g.; "('Number : ', I 2, 5 X, A)" becomes '('Number : ', I2, 5X, A)' +*/ +char* remove_spaces_except_quotes(const char* format) { + int len = strlen(format); + char* cleaned_format = malloc(len + 1); + + int i = 0, j = 0; + // don't remove blank spaces from within character + // string editor descriptor + bool in_quotes = false; + char current_quote = '\0'; + + while (format[i] != '\0') { + char c = format[i]; + if (c == '"' || c == '\'') { + if (i == 0 || format[i - 1] != '\\') { + // toggle in_quotes and set current_quote on entering or exiting quotes + if (!in_quotes) { + in_quotes = true; + current_quote = c; + } else if (current_quote == c) { + in_quotes = false; + } + } + } + + if (!isspace(c) || in_quotes) { + cleaned_format[j++] = c; // copy non-space characters or any character within quotes + } + + i++; + } + + cleaned_format[j] = '\0'; + return cleaned_format; +} + +/** + * parse fortran format string by extracting individual 'format specifiers' + * (e.g. 'i', 't', '*' etc.) into an array of strings + * + * `char* format`: the string we need to split into format specifiers + * `int* count` : store count of format specifiers (passed by reference from caller) + * `item_start` : + * + * e.g. "(I5, F5.2, T10)" is split separately into "I5", "F5.2", "T10" as + * format specifiers +*/ +char** parse_fortran_format(char* format, int64_t *count, int64_t *item_start) { char** format_values_2 = (char**)malloc((*count + 1) * sizeof(char*)); int format_values_count = *count; int index = 0 , start = 0; @@ -522,9 +689,33 @@ char** parse_fortran_format(char* format, int *count, int *item_start) { format_values_2[format_values_count++] = substring(format, start, index); index--; break; + case 'e' : + start = index++; + bool edot = false; + bool is_en_formatting = false; + if (tolower(format[index]) == 'n') { + index++; // move past the 'N' + is_en_formatting = true; + } + if (tolower(format[index]) == 's') index++; + while (isdigit(format[index])) index++; + if (format[index] == '.') { + edot = true; + index++; + } else { + printf("Error: Period required in format specifier\n"); + exit(1); + } + while (isdigit(format[index])) index++; + if (edot && (tolower(format[index]) == 'e' || tolower(format[index]) == 'n')) { + index++; + while (isdigit(format[index])) index++; + } + format_values_2[format_values_count++] = substring(format, start, index); + index--; + break; case 'i' : case 'd' : - case 'e' : case 'f' : case 'l' : start = index++; @@ -549,6 +740,26 @@ char** parse_fortran_format(char* format, int *count, int *item_start) { format_values_2[format_values_count++] = substring(format, start, index+1); *item_start = format_values_count; break; + case 't' : + // handle 'T', 'TL' & 'TR' editing see section 13.8.1.2 in 24-007.pdf + start = index++; + if (tolower(format[index]) == 'l' || tolower(format[index]) == 'r') { + index++; // move past 'L' or 'R' + } + // raise error when "T/TL/TR" is specified itself or with + // non-positive width + if (!isdigit(format[index])) { + // TODO: if just 'T' is specified the error message will print 'T,', fix it + printf("Error: Positive width required with '%c%c' descriptor in format string\n", + format[start], format[start + 1]); + exit(1); + } + while (isdigit(format[index])) { + index++; + } + format_values_2[format_values_count++] = substring(format, start, index); + index--; + break; default : if ( (format[index] == '-' && isdigit(format[index + 1]) && tolower(format[index + 2]) == 'p') @@ -593,33 +804,238 @@ char** parse_fortran_format(char* format, int *count, int *item_start) { return format_values_2; } + +struct array_iteration_state{ + //Preserve array size and current element index + int64_t array_size; + int64_t current_arr_index; + //Hold array pointers for each type. + int64_t* arr_ptr_int64; + int32_t* arr_ptr_int32; + int16_t* arr_ptr_int16; + int8_t* arr_ptr_int8; + float* arr_ptr_float; + double* arr_ptr_double; + char** arr_ptr_charPtr; + bool* arr_ptr_bool; + //Hold current element (We support array of int64, double, char*, bool) + int64_t current_arr_element_int64; + double current_arr_element_double; + char* current_arr_element_char_ptr; + bool current_arr_element_bool; +}; + +bool check_array_iteration(int* count, int* current_arg_type_int, va_list* args,struct array_iteration_state* state){ + bool is_array = true; + switch (*current_arg_type_int){ + case 9 : //arr[i64] + if(state->current_arr_index != state->array_size){ + state->current_arr_element_int64 = state->arr_ptr_int64[state->current_arr_index++]; + } else { + state->array_size = va_arg(*args,int64_t); + state->current_arr_index = 0; + state->arr_ptr_int64 = va_arg(*args,int64_t*); + state->current_arr_element_int64 = state->arr_ptr_int64[state->current_arr_index++]; + *count+= state->array_size - 2; + } + break; + case 10 : //arr[i32] + if(state->current_arr_index != state->array_size){ + int32_t temp_val = state->arr_ptr_int32[state->current_arr_index++]; + state->current_arr_element_int64 = (int64_t)temp_val; + } else { + state->array_size = va_arg(*args,int64_t); + state->current_arr_index = 0; + state->arr_ptr_int32 = va_arg(*args,int32_t*); + int32_t temp_val = state->arr_ptr_int32[state->current_arr_index++]; + state->current_arr_element_int64 = (int64_t)temp_val; + *count+= state->array_size - 2; + } + break; + case 11 : //arr[i16] + if(state->current_arr_index != state->array_size){ + int16_t temp_val = state->arr_ptr_int16[state->current_arr_index++]; + state->current_arr_element_int64 = (int64_t)temp_val; + } else { + state->array_size = va_arg(*args,int64_t); + state->current_arr_index = 0; + state->arr_ptr_int16 = va_arg(*args,int16_t*); + int16_t temp_val = state->arr_ptr_int16[state->current_arr_index++]; + state->current_arr_element_int64 = (int64_t)temp_val; + *count+= state->array_size - 2; + } + break; + case 12 : //arr[i8] + if(state->current_arr_index != state->array_size){ + int8_t temp_val = state->arr_ptr_int8[state->current_arr_index++]; + state->current_arr_element_int64 = (int64_t)temp_val; + } else { + state->array_size = va_arg(*args,int64_t); + state->current_arr_index = 0; + state->arr_ptr_int8 = va_arg(*args,int8_t*); + int8_t temp_val = state->arr_ptr_int8[state->current_arr_index++]; + state->current_arr_element_int64 = (int64_t)temp_val; + *count+= state->array_size - 2; + } + break; + case 13: // arr[f64] + if(state->current_arr_index != state->array_size){ + state->current_arr_element_double = state->arr_ptr_double[state->current_arr_index++]; + } else { + state->array_size = va_arg(*args,int64_t); + state->current_arr_index = 0; + state->arr_ptr_double = va_arg(*args,double*); + state->current_arr_element_double = state->arr_ptr_double[state->current_arr_index++]; + *count+= state->array_size - 2; + } + break; + case 14: // arr[f32] + if(state->current_arr_index != state->array_size){ + float temp_val = state->arr_ptr_float[state->current_arr_index++]; + state->current_arr_element_double = (double)temp_val; + } else { + state->array_size = va_arg(*args,int64_t); + state->current_arr_index = 0; + state->arr_ptr_float = va_arg(*args,float*); + float temp_val = state->arr_ptr_float[state->current_arr_index++]; + state->current_arr_element_double = (double)temp_val; + *count+= state->array_size - 2; + } + break; + case 15: //arr[character] + if(state->current_arr_index != state->array_size){ + state->current_arr_element_char_ptr = state->arr_ptr_charPtr[state->current_arr_index++]; + } else { + state->array_size = va_arg(*args,int64_t); + state->current_arr_index = 0; + state->arr_ptr_charPtr = va_arg(*args,char**); + state->current_arr_element_char_ptr = state->arr_ptr_charPtr[state->current_arr_index++]; + *count+= state->array_size - 2; + } + break; + case 16: //arr[logical] + if(state->current_arr_index != state->array_size){ + state->current_arr_element_bool = state->arr_ptr_bool[state->current_arr_index++]; + } else { + state->array_size = va_arg(*args,int64_t); + state->current_arr_index = 0; + state->arr_ptr_bool = va_arg(*args,bool*); + state->current_arr_element_bool = state->arr_ptr_bool[state->current_arr_index++]; + *count+= state->array_size - 2; + } + break; + //To DO : handle --> arr[cptr], arr[enumType] + default: + is_array = false; + break; + } + return is_array; + +} +char* int_to_format_specifier(int32_t type_as_int){ + switch(type_as_int){ + case 1: + case 2: + case 3: + case 4: + case 9: + case 10: + case 11: + case 12: + case 19: + return "i0"; + case 5: + case 13: + return "f-64"; //special handling in `handle_float` + case 6: + case 14: + return "f-32"; //special handling in `handle_float` + case 7: + case 15: + return "a"; + case 8: + case 16: + return "l"; + default: + fprintf(stderr,"Unidentified number %d\n",type_as_int); + exit(0); + } +} + +bool is_format_match(char format_value, int32_t current_arg_type_int){ + char* current_arg_correct_format = int_to_format_specifier(current_arg_type_int); + char lowered_format_value = tolower(format_value); + if(lowered_format_value == 'd' || lowered_format_value == 'e'){ + lowered_format_value = 'f'; + } + // Special conditions that are allowed by gfortran. + bool special_conditions = (lowered_format_value == 'l' && current_arg_correct_format[0] == 'a') || + (lowered_format_value == 'a' && current_arg_correct_format[0] == 'l'); + if(lowered_format_value != current_arg_correct_format[0] && !special_conditions){ + return false; + } else { + return true; + } +} + LFORTRAN_API char* _lcompilers_string_format_fortran(int count, const char* format, ...) { va_list args; va_start(args, format); - int len = strlen(format); - char* modified_input_string = (char*)malloc((len+1) * sizeof(char)); - strncpy(modified_input_string, format, len); - modified_input_string[len] = '\0'; - if (format[0] == '(' && format[len-1] == ')') { - memmove(modified_input_string, modified_input_string + 1, strlen(modified_input_string)); - modified_input_string[len-2] = '\0'; - } - int format_values_count = 0,item_start_idx=0; - char** format_values = parse_fortran_format(modified_input_string,&format_values_count,&item_start_idx); + bool default_formatting = (format == NULL); + char* default_spacing = " "; + int64_t format_values_count = 0,item_start_idx=0; + char** format_values; + char* modified_input_string; + if (default_formatting){ + format_values_count = INT64_MAX; // Termination would depend on count of args, so set to maximum looping. + } else { + char* cleaned_format = remove_spaces_except_quotes(format); + if (!cleaned_format) { + va_end(args); + return NULL; + } + int len = strlen(cleaned_format); + modified_input_string = (char*)malloc((len+1) * sizeof(char)); + strncpy(modified_input_string, cleaned_format, len); + modified_input_string[len] = '\0'; + if (cleaned_format[0] == '(' && cleaned_format[len-1] == ')') { + memmove(modified_input_string, modified_input_string + 1, strlen(modified_input_string)); + modified_input_string[len-2] = '\0'; + } + format_values = parse_fortran_format(modified_input_string,&format_values_count,&item_start_idx); + } char* result = (char*)malloc(sizeof(char)); result[0] = '\0'; int item_start = 0; bool array = false; + //initialize array_state to hold information about any passed array pointer arg. + struct array_iteration_state array_state; + array_state.array_size = -1; + array_state.current_arr_index = -1; + int32_t current_arg_type_int = -1; // holds int that represents type of argument. while (1) { int scale = 0; + bool is_array = false; + bool array_looping = false; for (int i = item_start; i < format_values_count; i++) { - if(format_values[i] == NULL) continue; - char* value = format_values[i]; + char* value; + array_looping = (array_state.current_arr_index != array_state.array_size); + if(default_formatting && !array_looping){ + if(count <=0) break; + current_arg_type_int = va_arg(args,int32_t); + count--; + value = int_to_format_specifier(current_arg_type_int); + } else if (!default_formatting) { + if(format_values[i] == NULL) continue; + value = format_values[i]; + } else { + // Array is being looped on. + } if (value[0] == '(' && value[strlen(value)-1] == ')') { value[strlen(value)-1] = '\0'; - int new_fmt_val_count = 0; + int64_t new_fmt_val_count = 0; char** new_fmt_val = parse_fortran_format(++value,&new_fmt_val_count,&item_start_idx); char** ptr = (char**)realloc(format_values, (format_values_count + new_fmt_val_count + 1) * sizeof(char*)); @@ -658,65 +1074,173 @@ LFORTRAN_API char* _lcompilers_string_format_fortran(int count, const char* form value = substring(value, 1, strlen(value) - 1); result = append_to_string(result, value); free(value); - } else if (tolower(value[0]) == 'a') { - // Character Editing (A[n]) - if ( count == 0 ) break; - count--; - char* arg = va_arg(args, char*); - if (arg == NULL) continue; - if (strlen(value) == 1) { - result = append_to_string(result, arg); - } else { - char* str = (char*)malloc((strlen(value)) * sizeof(char)); - memmove(str, value+1, strlen(value)); - int buffer_size = 20; - char* s = (char*)malloc(buffer_size * sizeof(char)); - snprintf(s, buffer_size, "%%%s.%ss", str, str); - char* string = (char*)malloc((atoi(str) + 1) * sizeof(char)); - sprintf(string,s, arg); - result = append_to_string(result, string); - free(str); - free(s); - free(string); - } } else if (tolower(value[strlen(value) - 1]) == 'x') { result = append_to_string(result, " "); - } else if (tolower(value[0]) == 'i') { - // Integer Editing ( I[w[.m]] ) - if ( count == 0 ) break; - count--; - int64_t val = va_arg(args, int64_t); - handle_integer(value, val, &result); - } else if (tolower(value[0]) == 'd') { - // D Editing (D[w[.d]]) - if ( count == 0 ) break; - count--; - double val = va_arg(args, double); - handle_decimal(value, val, scale, &result, "D"); - } else if (tolower(value[0]) == 'e') { - // E Editing E[w[.d][Ee]] - // Only (E[w[.d]]) has been implemented yet - if ( count == 0 ) break; - count--; - double val = va_arg(args, double); - handle_decimal(value, val, scale, &result, "E"); - } else if (tolower(value[0]) == 'f') { - if ( count == 0 ) break; - count--; - double val = va_arg(args, double); - handle_float(value, val, &result); - } else if (tolower(value[0]) == 'l') { - if ( count == 0 ) break; - count--; - char* val_str = va_arg(args, char*); - bool val = (strcmp(val_str, "True") == 0); - handle_logical(value, val, &result); - } else if (strlen(value) != 0) { - if ( count == 0 ) break; - count--; - printf("Printing support is not available for %s format.\n",value); + } else if (tolower(value[0]) == 't') { + if (tolower(value[1]) == 'l') { + // handle "TL" format specifier + int tab_left_pos = atoi(value + 2); + int current_length = strlen(result); + if (tab_left_pos > current_length) { + result[0] = '\0'; + } else { + result[current_length - tab_left_pos] = '\0'; + } + } else if (tolower(value[1]) == 'r') { + // handle "TR" format specifier + int tab_right_pos = atoi(value + 2); + int current_length = strlen(result); + int spaces_needed = tab_right_pos; + if (spaces_needed > 0) { + char* spaces = (char*)malloc((spaces_needed + 1) * sizeof(char)); + memset(spaces, ' ', spaces_needed); + spaces[spaces_needed] = '\0'; + result = append_to_string(result, spaces); + free(spaces); + } + } else { + if (count <= 0) break; + int tab_position = atoi(value + 1); + int current_length = strlen(result); + int spaces_needed = tab_position - current_length - 1; + if (spaces_needed > 0) { + char* spaces = (char*)malloc((spaces_needed + 1) * sizeof(char)); + memset(spaces, ' ', spaces_needed); + spaces[spaces_needed] = '\0'; + result = append_to_string(result, spaces); + free(spaces); + } else if (spaces_needed < 0) { + // Truncate the string to the length specified by Tn + // if the current position exceeds it + if (tab_position < current_length) { + // Truncate the string at the position specified by Tn + result[tab_position] = '\0'; + } + } + } + } else { + if (count <= 0) break; + if (!array_looping && !default_formatting) { + // Fetch type integer when we don't have an array. + current_arg_type_int = va_arg(args,int32_t); + count--; + } + if(!default_formatting){ + if (!is_format_match(value[0], current_arg_type_int)){ + char* type; + switch (int_to_format_specifier(current_arg_type_int)[0]) + { + case 'i': + type = "INTEGER"; + break; + case 'f': + type = "REAL"; + break; + case 'l': + type = "LOGICAL"; + break; + case 'a': + type = "CHARACTER"; + break; + } + free(result); + result = (char*)malloc(150 * sizeof(char)); + sprintf(result, " Runtime Error : Got argument of type (%s), while the format specifier is (%c)\n",type ,value[0]); + // Special indication for error --> "\b" to be handled by `lfortran_print` or `lfortran_file_write` + result[0] = '\b'; + count = 0; // Break while loop. + break; + } + } + is_array = check_array_iteration(&count, ¤t_arg_type_int, &args,&array_state); + if (tolower(value[0]) == 'a') { + // String Editing (A[n]) + count--; + char* arg = NULL; + if(is_array){ + arg = array_state.current_arr_element_char_ptr; + } else { + arg = va_arg(args, char*); + } + if (arg == NULL) continue; + if (strlen(value) == 1) { + result = append_to_string(result, arg); + } else { + char* str = (char*)malloc((strlen(value)) * sizeof(char)); + memmove(str, value+1, strlen(value)); + int buffer_size = 20; + char* s = (char*)malloc(buffer_size * sizeof(char)); + snprintf(s, buffer_size, "%%%s.%ss", str, str); + char* string = (char*)malloc((atoi(str) + 1) * sizeof(char)); + sprintf(string,s, arg); + result = append_to_string(result, string); + free(str); + free(s); + free(string); + } + } else if (tolower(value[0]) == 'i') { + // Integer Editing ( I[w[.m]] ) + count--; + if(is_array){ + handle_integer(value, array_state.current_arr_element_int64, &result); + } else { + int64_t val = va_arg(args, int64_t); + handle_integer(value, val, &result); + } + } else if (tolower(value[0]) == 'd') { + // D Editing (D[w[.d]]) + count--; + if(is_array){ + handle_decimal(value, array_state.current_arr_element_double, scale, &result, "D");; + } else { + double val = va_arg(args, double); + handle_decimal(value, val, scale, &result, "D"); + } + } else if (tolower(value[0]) == 'e') { + // Check if the next character is 'N' for EN format + char format_type = tolower(value[1]); + count--; + if (format_type == 'n') { + if(is_array){ + handle_en(value, array_state.current_arr_element_double, scale, &result, "E"); + } else { + double val = va_arg(args, double); + handle_en(value, val, scale, &result, "E"); + } + } else { + if(is_array){ + handle_decimal(value, array_state.current_arr_element_double, scale, &result, "E"); + } else { + double val = va_arg(args, double); + handle_decimal(value, val, scale, &result, "E"); + } + } + } else if (tolower(value[0]) == 'f') { + count--; + if(is_array){ + handle_float(value,array_state.current_arr_element_double, &result); + } else { + double val = va_arg(args, double); + handle_float(value, val, &result); + } + } else if (tolower(value[0]) == 'l') { + count--; + if(is_array){ + bool val = array_state.current_arr_element_bool; + handle_logical(value, val, &result); + } else { + char* val_str = va_arg(args, char*); + bool val = (strcmp(val_str, "True") == 0); + handle_logical(value, val, &result); + } + } else if (strlen(value) != 0) { + count--; + printf("Printing support is not available for %s format.\n",value); + } + if( default_formatting && (count > 0) ){ //append spacing after each element. + result = append_to_string(result,default_spacing); + } } - } if ( count > 0 ) { if (!array) { @@ -727,12 +1251,13 @@ LFORTRAN_API char* _lcompilers_string_format_fortran(int count, const char* form break; } } - - free(modified_input_string); - for (int i = 0;i> shift) | cutoff_extra_bits(val1 << (bits_size - shift), bits_size, max_bits_size); } else { - y = 8.0 / w; - y2 = y * y; - rc = besselj1_rational_pcqc( y2 ); - rs = besselj1_rational_psqs( y2 ); - f = 1.0 / ( sqrt(w) * SQRT_PI ); - - // __sincos(w, &si, &co); - si = sin(w); - co = cos(w); - value = f * ( ( rc * (si-co) ) + ( (y*rs) * (si+co) ) ); - } - if ( x < 0.0 ) { - value = -1.0 * value; - } - return value; -} - -LFORTRAN_API float _lfortran_sbesselj1( float x ) { - return (float)_lfortran_dbesselj1((double)x); -} - -static double bessely0_rational_p1q1( double x ) { - double ax; - double s1; - double s2; - if ( x == 0.0 ) { - return 0.18214429522164177; - } - if ( x < 0.0 ) { - ax = -x; - } else { - ax = x; - } - if ( ax <= 1.0 ) { - s1 = 107235387820.03177 + (x * (-8371625545.12605 + (x * (204222743.5737662 + (x * (-2128754.84744018 + (x * (10102.532948020907 + (x * -18.402381979244993))))))))); - s2 = 588738657389.9703 + (x * (8161718777.729036 + (x * (55662956.624278255 + (x * (238893.93209447255 + (x * (664.7598668924019 + (x * 1.0))))))))); - } else { - x = 1.0 / x; - s1 = -18.402381979244993 + (x * (10102.532948020907 + (x * (-2128754.84744018 + (x * (204222743.5737662 + (x * (-8371625545.12605 + (x * 107235387820.03177))))))))); - s2 = 1.0 + (x * (664.7598668924019 + (x * (238893.93209447255 + (x * (55662956.624278255 + (x * (8161718777.729036 + (x * 588738657389.9703))))))))); - } - return s1 / s2; -} - -static double bessely0_rational_p2q2( double x ) { - double ax; - double s1; - double s2; - if ( x == 0.0 ) { - return -0.051200622130023854; - } - if ( x < 0.0 ) { - ax = -x; - } else { - ax = x; - } - if ( ax <= 1.0 ) { - s1 = -22213976967566.19 + (x * (-551074352067.2264 + (x * (43600098638.60306 + (x * (-695904393.9461962 + (x * (4690528.861167863 + (x * (-14566.865832663636 + (x * 17.427031242901595))))))))))); - s2 = 433861465807072.6 + (x * (5426682441941.234 + (x * (34015103849.97124 + (x * (139602027.7098683 + (x * (406699.82352539554 + (x * (830.3085761207029 + (x * 1.0))))))))))); - } else { - x = 1.0 / x; - s1 = 17.427031242901595 + (x * (-14566.865832663636 + (x * (4690528.861167863 + (x * (-695904393.9461962 + (x * (43600098638.60306 + (x * (-551074352067.2264 + (x * -22213976967566.19))))))))))); - s2 = 1.0 + (x * (830.3085761207029 + (x * (406699.82352539554 + (x * (139602027.7098683 + (x * (34015103849.97124 + (x * (5426682441941.234 + (x * 433861465807072.6))))))))))); - } - return s1 / s2; -} - -static double bessely0_rational_p3q3( double x ) { - double ax; - double s1; - double s2; - if ( x == 0.0 ) { - return -0.023356489432789604; - } - if ( x < 0.0 ) { - ax = -x; - } else { - ax = x; - } - if ( ax <= 1.0 ) { - s1 = -8072872690515021.0 + (x * (670166418691732.4 + (x * (-128299123640.88687 + (x * (-193630512667.72083 + (x * (2195882717.0518103 + (x * (-10085539.923498211 + (x * (21363.5341693139 + (x * -17.439661319197498))))))))))))); - s2 = 345637246288464600.0 + (x * (3927242556964031.0 + (x * (22598377924042.9 + (x * (86926121104.20982 + (x * (247272194.75672302 + (x * (539247.3920976806 + (x * (879.0336216812844 + (x * 1.0))))))))))))); - } else { - x = 1.0 / x; - s1 = -17.439661319197498 + (x * (21363.5341693139 + (x * (-10085539.923498211 + (x * (2195882717.0518103 + (x * (-193630512667.72083 + (x * (-128299123640.88687 + (x * (670166418691732.4 + (x * -8072872690515021.0))))))))))))); - s2 = 1.0 + (x * (879.0336216812844 + (x * (539247.3920976806 + (x * (247272194.75672302 + (x * (86926121104.20982 + (x * (22598377924042.9 + (x * (3927242556964031.0 + (x * 345637246288464600.0))))))))))))); - } - return s1 / s2; -} - -static double bessely0_rational_pcqc( double x ) { - double ax; - double s1; - double s2; - if ( x == 0.0 ) { - return 1.0; - } - if ( x < 0.0 ) { - ax = -x; - } else { - ax = x; - } - if ( ax <= 1.0 ) { - s1 = 22779.090197304686 + (x * (41345.38663958076 + (x * (21170.523380864943 + (x * (3480.648644324927 + (x * (153.76201909008356 + (x * 0.8896154842421046))))))))); // eslint-disable-line max-len - s2 = 22779.090197304686 + (x * (41370.41249551042 + (x * (21215.350561880117 + (x * (3502.8735138235606 + (x * (157.11159858080893 + (x * 1.0))))))))); // eslint-disable-line max-len - } else { - x = 1.0 / x; - s1 = 0.8896154842421046 + (x * (153.76201909008356 + (x * (3480.648644324927 + (x * (21170.523380864943 + (x * (41345.38663958076 + (x * 22779.090197304686))))))))); // eslint-disable-line max-len - s2 = 1.0 + (x * (157.11159858080893 + (x * (3502.8735138235606 + (x * (21215.350561880117 + (x * (41370.41249551042 + (x * 22779.090197304686))))))))); // eslint-disable-line max-len - } - return s1 / s2; -} - -static double bessely0_rational_psqs( double x ) { - double ax; - double s1; - double s2; - if ( x == 0.0 ) { - return -0.015625; - } - if ( x < 0.0 ) { - ax = -x; - } else { - ax = x; - } - if ( ax <= 1.0 ) { - s1 = -89.22660020080009 + (x * (-185.91953644342993 + (x * (-111.83429920482737 + (x * (-22.300261666214197 + (x * (-1.244102674583564 + (x * -0.008803330304868075))))))))); // eslint-disable-line max-len - s2 = 5710.502412851206 + (x * (11951.131543434614 + (x * (7264.278016921102 + (x * (1488.7231232283757 + (x * (90.59376959499312 + (x * 1.0))))))))); // eslint-disable-line max-len - } else { - x = 1.0 / x; - s1 = -0.008803330304868075 + (x * (-1.244102674583564 + (x * (-22.300261666214197 + (x * (-111.83429920482737 + (x * (-185.91953644342993 + (x * -89.22660020080009))))))))); // eslint-disable-line max-len - s2 = 1.0 + (x * (90.59376959499312 + (x * (1488.7231232283757 + (x * (7264.278016921102 + (x * (11951.131543434614 + (x * 5710.502412851206))))))))); // eslint-disable-line max-len - } - return s1 / s2; -} - -LFORTRAN_API double _lfortran_dbessely0( double x ) { - - double PI = 3.14159265358979323846; - double SQRT_PI = 1.7724538509055160273; - double ONE_DIV_SQRT_PI = 1.0 / SQRT_PI; - double TWO_DIV_PI = 2.0 / PI; - - double x1 = 8.9357696627916752158e-01; - double x2 = 3.9576784193148578684e+00; - double x3 = 7.0860510603017726976e+00; - double x11 = 2.280e+02; - double x12 = 2.9519662791675215849e-03; - double x21 = 1.0130e+03; - double x22 = 6.4716931485786837568e-04; - double x31 = 1.8140e+03; - double x32 = 1.1356030177269762362e-04; - - double rc; - double rs; - double y2; - double r; - double y; - double z; - double f; - double si; - double co; - - if ( x < 0.0 ) { - return nan("1"); - } - if ( x == 0.0 ) { - return -1*HUGE_VAL; - } - if ( x == HUGE_VAL ) { - return 0.0; - } - if ( x <= 3.0 ) { - y = x * x; - z = ( _lfortran_dlog(x/x1) * _lfortran_dbesselj0(x) ) * TWO_DIV_PI; - r = bessely0_rational_p1q1( y ); - f = ( x+x1 ) * ( ( x - (x11/256.0) ) - x12 ); - return z + ( f*r ); - } - if ( x <= 5.5 ) { - y = x * x; - z = ( _lfortran_dlog(x/x1) * _lfortran_dbesselj0(x) ) * TWO_DIV_PI; - r = bessely0_rational_p2q2( y ); - f = ( x+x2 ) * ( (x - (x21/256.0)) - x22 ); - return z + ( f*r ); - } - if ( x <= 8.0 ) { - y = x * x; - z = ( _lfortran_dlog(x/x1) * _lfortran_dbesselj0(x) ) * TWO_DIV_PI; - r = bessely0_rational_p3q3( y ); - f = ( x+x3 ) * ( (x - (x31/256.0)) - x32 ); - return z + ( f*r ); - } - y = 8.0 / x; - y2 = y * y; - rc = bessely0_rational_pcqc( y2 ); - rs = bessely0_rational_psqs( y2 ); - f = ONE_DIV_SQRT_PI / sqrt( x ); - - // __sincos(w, &si, &co); - si = sin(x); - co = cos(x); - return f * ( ( rc * (si-co) ) + ( (y*rs) * (si+co) ) ); -} - -LFORTRAN_API float _lfortran_sbessely0( float x ) { - return (float)_lfortran_dbessely0((double)x); + result = cutoff_extra_bits(val1 << shift, bits_size, max_bits_size) | ((val1 >> (bits_size - shift))); + } + return result; +} + +LFORTRAN_API int64_t _lfortran_dishftc(int64_t val, int64_t shift_signed, int64_t bits_size) { + uint32_t max_bits_size = 64; + bool negative_shift = (shift_signed < 0); + uint32_t shift = llabs(shift_signed); + + uint64_t val1 = cutoff_extra_bits((uint64_t)val, (uint32_t)bits_size, max_bits_size); + uint64_t result; + if (negative_shift) { + result = (val1 >> shift) | cutoff_extra_bits(val1 << (bits_size - shift), bits_size, max_bits_size); + } else { + result = cutoff_extra_bits(val1 << shift, bits_size, max_bits_size) | ((val1 >> (bits_size - shift))); + } + return result; } // sin ------------------------------------------------------------------------- @@ -1633,6 +1639,18 @@ LFORTRAN_API double_complex_t _lfortran_zsin(double_complex_t x) return csin(x); } +LFORTRAN_API float _lfortran_ssind(float x) +{ + float radians = (x * PI) / 180.0; + return sin(radians); +} + +LFORTRAN_API double _lfortran_dsind(double x) +{ + double radians = (x * PI) / 180.0; + return sin(radians); +} + // cos ------------------------------------------------------------------------- LFORTRAN_API float _lfortran_scos(float x) @@ -1655,6 +1673,18 @@ LFORTRAN_API double_complex_t _lfortran_zcos(double_complex_t x) return ccos(x); } +LFORTRAN_API float _lfortran_scosd(float x) +{ + float radians = (x * PI) / 180.0; + return cos(radians); +} + +LFORTRAN_API double _lfortran_dcosd(double x) +{ + double radians = (x * PI) / 180.0; + return cos(radians); +} + // tan ------------------------------------------------------------------------- LFORTRAN_API float _lfortran_stan(float x) @@ -1677,6 +1707,18 @@ LFORTRAN_API double_complex_t _lfortran_ztan(double_complex_t x) return ctan(x); } +LFORTRAN_API float _lfortran_stand(float x) +{ + float radians = (x * PI) / 180.0; + return tan(radians); +} + +LFORTRAN_API double _lfortran_dtand(double x) +{ + double radians = (x * PI) / 180.0; + return tan(radians); +} + // sinh ------------------------------------------------------------------------ LFORTRAN_API float _lfortran_ssinh(float x) @@ -1766,6 +1808,16 @@ LFORTRAN_API double_complex_t _lfortran_zasin(double_complex_t x) return casin(x); } +LFORTRAN_API float _lfortran_sasind(float x) +{ + return (asin(x)*180)/PI; +} + +LFORTRAN_API double _lfortran_dasind(double x) +{ + return (asin(x)*180)/PI; +} + // acos ------------------------------------------------------------------------ LFORTRAN_API float _lfortran_sacos(float x) @@ -1788,6 +1840,16 @@ LFORTRAN_API double_complex_t _lfortran_zacos(double_complex_t x) return cacos(x); } +LFORTRAN_API float _lfortran_sacosd(float x) +{ + return (acos(x)*180)/PI; +} + +LFORTRAN_API double _lfortran_dacosd(double x) +{ + return (acos(x)*180)/PI; +} + // atan ------------------------------------------------------------------------ LFORTRAN_API float _lfortran_satan(float x) @@ -1810,6 +1872,16 @@ LFORTRAN_API double_complex_t _lfortran_zatan(double_complex_t x) return catan(x); } +LFORTRAN_API float _lfortran_satand(float x) +{ + return (atan(x)*180)/PI; +} + +LFORTRAN_API double _lfortran_datand(double x) +{ + return (atan(x)*180)/PI; +} + // atan2 ----------------------------------------------------------------------- LFORTRAN_API float _lfortran_satan2(float y, float x) @@ -1960,34 +2032,104 @@ LFORTRAN_API void _lfortran_strcat(char** s1, char** s2, char** dest) dest_char[cntr] = trmn; *dest = &(dest_char[0]); } +// Allocate_allocatable-strings + Extend String ----------------------------------------------------------- + +void extend_string(char** ptr, int32_t new_size /*Null-Character Counted*/, int64_t* string_capacity){ + ASSERT_MSG(string_capacity != NULL, "%s", "string capacity is NULL"); + int64_t new_capacity; + if((*string_capacity)*2 < new_size){ + new_capacity = new_size; + } else { + new_capacity = (*string_capacity)*2; + } + + *ptr = realloc(*ptr, new_capacity); + ASSERT_MSG(*ptr != NULL, "%s", "pointer reallocation failed!"); + + *string_capacity = new_capacity; +} + +LFORTRAN_API void _lfortran_alloc(char** ptr, int32_t desired_size /*Null-Character Counted*/ + , int64_t* string_size, int64_t* string_capacity) { + if(*ptr == NULL && *string_size == 0 && *string_capacity == 0){ + // Start off with (inital_capacity >= 100). + int32_t inital_capacity; + if(100 < desired_size){ + inital_capacity = desired_size; + } else { + inital_capacity = 100; + } + *ptr = (char*)malloc(inital_capacity); + *string_capacity = inital_capacity; + const int8_t null_terminated_char_len = 1; + *string_size = desired_size - null_terminated_char_len; + } else if(*ptr != NULL && *string_capacity != 0){ + printf("runtime error: Attempting to allocate already allocated variable\n"); + exit(1); + } else { + printf("Compiler Internal Error :Invalid state of string descriptor\n"); + exit(1); + } +} // strcpy ----------------------------------------------------------- -LFORTRAN_API void _lfortran_strcpy(char** x, char *y, int8_t free_target) + +LFORTRAN_API void _lfortran_strcpy_descriptor_string(char** x, char *y, int64_t* x_string_size, int64_t* x_string_capacity) { - if (free_target) { - if (*x) { - free((void *)*x); + ASSERT_MSG(x_string_size != NULL,"%s", "string size is NULL"); + ASSERT_MSG(x_string_capacity != NULL, "%s", "string capacity is NULL"); + ASSERT_MSG(((*x != NULL) && (*x_string_size <= (*x_string_capacity - 1))) || + (*x == NULL && *x_string_size == 0 && *x_string_capacity == 0) , "%s", + "compiler-behavior error : string x_string_capacity < string size"); + + if(y == NULL){ + fprintf(stderr, + "Runtime Error : RHS allocatable-character variable must be allocated before assignment.\n"); + exit(1); + } + size_t y_len, x_len; + y_len = strlen(y); + x_len = y_len; + + if (*x == NULL) { + _lfortran_alloc(x, y_len+1, x_string_size, x_string_capacity); // Allocate new memory for x. + } else { + int8_t null_char_len = 1; + if(*x_string_capacity < (y_len + null_char_len)){ + extend_string(x, y_len+1, x_string_capacity); } - // *x = (char*) malloc((strlen(y) + 1) * sizeof(char)); - // _lfortran_string_init(strlen(y) + 1, *x); } - if (y == NULL) { - *x = NULL; - return; + int64_t null_character_index = x_len; + (*x)[null_character_index] = '\0'; + for (size_t i = 0; i < x_len; i++) { + (*x)[i] = y[i]; } - // if( *x == NULL ) { - *x = (char*) malloc((strlen(y) + 1) * sizeof(char)); - _lfortran_string_init(strlen(y) + 1, *x); - // } - size_t y_len = strlen(y); - size_t x_len = strlen(*x); - size_t i = 0; - for (; i < x_len && i < y_len; i++) { - x[0][i] = y[i]; + *x_string_size = y_len; +} + +LFORTRAN_API void _lfortran_strcpy_pointer_string(char** x, char *y) +{ + if(y == NULL){ + fprintf(stderr, + "Runtime Error : RHS allocatable-character variable must be allocated before assignment.\n"); + exit(1); } - for (; i < x_len; i++) { - x[0][i] = ' '; + size_t y_len; + y_len = strlen(y); + // A workaround : + // every LHS string that's not allocatable should have been + // allocated a fixed-size-memory space that stays there for the whole life time of the program. + if( *x == NULL ) { + *x = (char*) malloc((y_len + 1) * sizeof(char)); + _lfortran_string_init(y_len + 1, *x); + } + for (size_t i = 0; i < strlen(*x); i++) { + if (i < y_len) { + x[0][i] = y[i]; + } else { + x[0][i] = ' '; + } } } @@ -2135,6 +2277,7 @@ LFORTRAN_API int32_t _lpython_bit_length8(int64_t num) //repeat str for n time LFORTRAN_API void _lfortran_strrepeat(char** s, int32_t n, char** dest) { + int cntr = 0; char trmn = '\0'; int s_len = strlen(*s); int trmn_size = sizeof(trmn); @@ -2142,22 +2285,13 @@ LFORTRAN_API void _lfortran_strrepeat(char** s, int32_t n, char** dest) if (f_len < 0) f_len = 0; char* dest_char = (char*)malloc(f_len+trmn_size); - - if (s_len == 1) { - memset(dest_char, *(*s), f_len); - } else { - memcpy(dest_char, *s, s_len); - int chars_copied = s_len; - int copy_length; - while (chars_copied < f_len) { - copy_length = (chars_copied <= f_len-chars_copied) - ? chars_copied : f_len-chars_copied; - memcpy(dest_char+chars_copied, dest_char, copy_length); - chars_copied += copy_length; + for (int i = 0; i < n; i++) { + for (int j = 0; j < s_len; j++) { + dest_char[cntr] = (*s)[j]; + cntr++; } } - - dest_char[f_len] = trmn; + dest_char[cntr] = trmn; *dest = &(dest_char[0]); } @@ -2182,13 +2316,14 @@ LFORTRAN_API char* _lfortran_strrepeat_c(char* s, int32_t n) } // idx starts from 1 -LFORTRAN_API char* _lfortran_str_item(char* s, int32_t idx) { +LFORTRAN_API char* _lfortran_str_item(char* s, int64_t idx) { int s_len = strlen(s); - int original_idx = idx - 1; + // TODO: Remove bound check in Release mode + int64_t original_idx = idx - 1; if (idx < 1) idx += s_len; if (idx < 1 || idx >= s_len + 1) { - printf("String index: %d is out of Bounds\n", original_idx); + printf("String index: %" PRId64 "is out of Bounds\n", original_idx); exit(1); } char* res = (char*)malloc(2); @@ -2197,12 +2332,6 @@ LFORTRAN_API char* _lfortran_str_item(char* s, int32_t idx) { return res; } -/// Find a substring in a string -LFORTRAN_API bool _lfortran_str_contains(char* str, char* substr) { - char* res = strstr(str, substr); - return res != NULL; -} - // idx1 and idx2 both start from 1 LFORTRAN_API char* _lfortran_str_copy(char* s, int32_t idx1, int32_t idx2) { @@ -2304,7 +2433,7 @@ LFORTRAN_API char* _lfortran_str_slice_assign(char* s, char *r, int32_t idx1, in return s; } - char* dest_char = (char*)malloc(s_len); + char* dest_char = (char*)malloc(s_len + 1); strcpy(dest_char, s); int s_i = idx1, d_i = 0; while((step > 0 && s_i >= idx1 && s_i < idx2) || @@ -2365,9 +2494,6 @@ LFORTRAN_API void _lfortran_free(char* ptr) { free((void*)ptr); } -LFORTRAN_API void _lfortran_alloc(char** ptr, int32_t size) { - *ptr = (char *) malloc(size); -} // size_plus_one is the size of the string including the null character LFORTRAN_API void _lfortran_string_init(int size_plus_one, char *s) { @@ -2418,102 +2544,269 @@ LFORTRAN_API int64_t _lfortran_ibits64(int64_t i, int32_t pos, int32_t len) { return ((ui << (BITS_64 - pos - len)) >> (BITS_64 - len)); } -// cpu_time ------------------------------------------------------------------- - -LFORTRAN_API void _lfortran_cpu_time(double *t) { - *t = ((double) clock()) / CLOCKS_PER_SEC; +// cpu_time ------------------------------------------------------------------- + +LFORTRAN_API double _lfortran_d_cpu_time() { + return ((double) clock()) / CLOCKS_PER_SEC; +} + +LFORTRAN_API float _lfortran_s_cpu_time() { + return ((float) clock()) / CLOCKS_PER_SEC; +} + +// system_time ----------------------------------------------------------------- + +LFORTRAN_API int32_t _lfortran_i32sys_clock_count() { +#if defined(_WIN32) + return - INT_MAX; +#else + struct timespec ts; + if(clock_gettime(CLOCK_MONOTONIC, &ts) == 0) { + return (int32_t)(ts.tv_nsec / 1000000) + ((int32_t)ts.tv_sec * 1000); + } else { + return - INT_MAX; + } +#endif +} + +LFORTRAN_API int32_t _lfortran_i32sys_clock_count_rate() { +#if defined(_WIN32) + return - INT_MAX; +#else + struct timespec ts; + if(clock_gettime(CLOCK_MONOTONIC, &ts) == 0) { + return 1e3; // milliseconds + } else { + return 0; + } +#endif +} + +LFORTRAN_API int32_t _lfortran_i32sys_clock_count_max() { +#if defined(_WIN32) + return 0; +#else + struct timespec ts; + if(clock_gettime(CLOCK_MONOTONIC, &ts) == 0) { + return INT_MAX; + } else { + return 0; + } +#endif } -// system_time ----------------------------------------------------------------- - -LFORTRAN_API void _lfortran_i32sys_clock( - int32_t *count, int32_t *rate, int32_t *max) { +LFORTRAN_API uint64_t _lfortran_i64sys_clock_count() { #if defined(_WIN32) - *count = - INT_MAX; - *rate = 0; - *max = 0; + return 0; #else struct timespec ts; if(clock_gettime(CLOCK_MONOTONIC, &ts) == 0) { - *count = (int32_t)(ts.tv_nsec / 1000000) + ((int32_t)ts.tv_sec * 1000); - *rate = 1e3; // milliseconds - *max = INT_MAX; + return (uint64_t)(ts.tv_nsec) + ((uint64_t)ts.tv_sec * 1000000000); } else { - *count = - INT_MAX; - *rate = 0; - *max = 0; + return - LLONG_MAX; } #endif } -LFORTRAN_API void _lfortran_i64sys_clock( - uint64_t *count, int64_t *rate, int64_t *max) { +LFORTRAN_API int64_t _lfortran_i64sys_clock_count_rate() { #if defined(_WIN32) - *count = - INT_MAX; - *rate = 0; - *max = 0; + return 0; #else struct timespec ts; if(clock_gettime(CLOCK_MONOTONIC, &ts) == 0) { - *count = (uint64_t)(ts.tv_nsec) + ((uint64_t)ts.tv_sec * 1000000000); // FIXME: Rate can be in microseconds or nanoseconds depending on // resolution of the underlying platform clock. - *rate = 1e9; // nanoseconds - *max = LLONG_MAX; + return 1e9; // nanoseconds } else { - *count = - LLONG_MAX; - *rate = 0; - *max = 0; + return 0; } #endif } -LFORTRAN_API void _lfortran_i64r64sys_clock( - uint64_t *count, double *rate, int64_t *max) { -double ratev; -int64_t maxv; -if( rate == NULL ) { - rate = &ratev; +LFORTRAN_API int64_t _lfortran_i64sys_clock_count_max() { +#if defined(_WIN32) + return 0; +#else + struct timespec ts; + if(clock_gettime(CLOCK_MONOTONIC, &ts) == 0) { + return LLONG_MAX; + } else { + return 0; + } +#endif } -if( max == NULL ) { - max = &maxv; + +LFORTRAN_API float _lfortran_i32r32sys_clock_count_rate() { +#if defined(_WIN32) + return 0; +#else + struct timespec ts; + if(clock_gettime(CLOCK_MONOTONIC, &ts) == 0) { + return 1e3; // milliseconds + } else { + return 0; + } +#endif } + +LFORTRAN_API double _lfortran_i64r64sys_clock_count_rate() { #if defined(_WIN32) - *count = - INT_MAX; - *rate = 0; - *max = 0; + return 0; #else struct timespec ts; if(clock_gettime(CLOCK_MONOTONIC, &ts) == 0) { - *count = (uint64_t)(ts.tv_nsec) + ((uint64_t)ts.tv_sec * 1000000000); - // FIXME: Rate can be in microseconds or nanoseconds depending on - // resolution of the underlying platform clock. - *rate = 1e9; // nanoseconds - *max = LLONG_MAX; + return 1e9; // nanoseconds } else { - *count = - LLONG_MAX; - *rate = 0; - *max = 0; + return 0; } #endif } -LFORTRAN_API double _lfortran_time() -{ +LFORTRAN_API char* _lfortran_zone() { + char* result = (char*)malloc(12 * sizeof(char)); // "(+|-)hhmm\0" = 5 + 1 + + if (result == NULL) { + return NULL; + } + +#if defined(_WIN32) + // Windows doesn't provide timezone offset directly, so we calculate it + TIME_ZONE_INFORMATION tzinfo; + DWORD retval = GetTimeZoneInformation(&tzinfo); + + // Calculate the total offset in minutes + int offset_minutes = -tzinfo.Bias; // Bias is in minutes; negative for UTC+ + + if (retval == TIME_ZONE_ID_DAYLIGHT) { + offset_minutes -= tzinfo.DaylightBias; // Apply daylight saving if applicable + } else if (retval == TIME_ZONE_ID_STANDARD) { + offset_minutes -= tzinfo.StandardBias; // Apply standard bias if applicable + } + +#elif defined(__APPLE__) && !defined(__aarch64__) + // For non-ARM-based Apple platforms + time_t t = time(NULL); + struct tm* ptm = localtime(&t); + + // The tm_gmtoff field holds the time zone offset in seconds + long offset_seconds = ptm->tm_gmtoff; + int offset_minutes = offset_seconds / 60; + +#else + // For Linux and other platforms + time_t t = time(NULL); + struct tm* ptm = localtime(&t); + + // The tm_gmtoff field holds the time zone offset in seconds + long offset_seconds = ptm->tm_gmtoff; + int offset_minutes = offset_seconds / 60; +#endif + char sign = offset_minutes >= 0 ? '+' : '-'; + int offset_hours = abs(offset_minutes / 60); + int remaining_minutes = abs(offset_minutes % 60); + snprintf(result, 12, "%c%02d%02d", sign, offset_hours, remaining_minutes); + return result; +} + +LFORTRAN_API char* _lfortran_time() { + char* result = (char*)malloc(13 * sizeof(char)); // "hhmmss.sss\0" = 12 + 1 + + if (result == NULL) { + return NULL; + } + +#if defined(_WIN32) + SYSTEMTIME st; + GetLocalTime(&st); // Gets the current local time + sprintf(result, "%02d%02d%02d.%03d", st.wHour, st.wMinute, st.wSecond, st.wMilliseconds); +#elif defined(__APPLE__) && !defined(__aarch64__) + // For non-ARM-based Apple platforms, use current time functions + struct timeval tv; + gettimeofday(&tv, NULL); + struct tm* ptm = localtime(&tv.tv_sec); + int milliseconds = tv.tv_usec / 1000; + sprintf(result, "%02d%02d%02d.%03d", ptm->tm_hour, ptm->tm_min, ptm->tm_sec, milliseconds); +#else + // For Linux and other platforms + struct timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + struct tm* ptm = localtime(&ts.tv_sec); + int milliseconds = ts.tv_nsec / 1000000; + sprintf(result, "%02d%02d%02d.%03d", ptm->tm_hour, ptm->tm_min, ptm->tm_sec, milliseconds); +#endif + return result; +} + +LFORTRAN_API char* _lfortran_date() { + // Allocate memory for the output string (8 characters minimum) + char* result = (char*)malloc(32 * sizeof(char)); // "ccyymmdd\0" = 8 + 1 + + if (result == NULL) { + return NULL; // Handle memory allocation failure + } + #if defined(_WIN32) - FILETIME ft; - ULARGE_INTEGER uli; - GetSystemTimeAsFileTime(&ft); - uli.LowPart = ft.dwLowDateTime; - uli.HighPart = ft.dwHighDateTime; - return (double)uli.QuadPart / 10000000.0 - 11644473600.0; + SYSTEMTIME st; + GetLocalTime(&st); // Get the current local date + sprintf(result, "%04d%02d%02d", st.wYear, st.wMonth, st.wDay); #elif defined(__APPLE__) && !defined(__aarch64__) - return 0.0; + // For non-ARM-based Apple platforms + time_t t = time(NULL); + struct tm* ptm = localtime(&t); + sprintf(result, "%04d%02d%02d", ptm->tm_year + 1900, ptm->tm_mon + 1, ptm->tm_mday); #else + // For Linux and other platforms + time_t t = time(NULL); + struct tm* ptm = localtime(&t); + snprintf(result, 32, "%04d%02d%02d", ptm->tm_year + 1900, ptm->tm_mon + 1, ptm->tm_mday); +#endif + + return result; // Return the formatted date string +} + +LFORTRAN_API int32_t _lfortran_values(int32_t n) +{ int32_t result = 0; +#if defined(_WIN32) + SYSTEMTIME st; + GetLocalTime(&st); // Get the current local date + if (n == 1) result = st.wYear; + else if (n == 2) result = st.wMonth; + else if (n == 3) result = st.wDay; + else if (n == 4) result = 330; + else if (n == 5) result = st.wHour; + else if (n == 6) result = st.wMinute; + else if (n == 7) result = st.wSecond; + else if (n == 8) result = st.wMilliseconds; +#elif defined(__APPLE__) && !defined(__aarch64__) + // For non-ARM-based Apple platforms + struct timeval tv; + gettimeofday(&tv, NULL); + struct tm* ptm = localtime(&tv.tv_sec); + int milliseconds = tv.tv_usec / 1000; + if (n == 1) result = ptm->tm_year + 1900; + else if (n == 2) result = ptm->tm_mon + 1; + else if (n == 3) result = ptm->tm_mday; + else if (n == 4) result = 330; + else if (n == 5) result = ptm->tm_hour; + else if (n == 6) result = ptm->tm_min; + else if (n == 7) result = ptm->tm_sec; + else if (n == 8) result = milliseconds; +#else + // For Linux and other platforms + time_t t = time(NULL); + struct tm* ptm = localtime(&t); struct timespec ts; clock_gettime(CLOCK_REALTIME, &ts); - return (double)ts.tv_sec + (double)ts.tv_nsec / 1000000000.0; + if (n == 1) result = ptm->tm_year + 1900; + else if (n == 2) result = ptm->tm_mon + 1; + else if (n == 3) result = ptm->tm_mday; + else if (n == 4) result = 330; + else if (n == 5) result = ptm->tm_hour; + else if (n == 6) result = ptm->tm_min; + else if (n == 7) result = ptm->tm_sec; + else if (n == 8) result = ts.tv_nsec / 1000000; #endif + return result; } LFORTRAN_API float _lfortran_sp_rand_num() { @@ -2524,6 +2817,31 @@ LFORTRAN_API double _lfortran_dp_rand_num() { return rand() / (double) RAND_MAX; } +LFORTRAN_API int32_t _lfortran_int32_rand_num() { + return rand(); +} + +LFORTRAN_API int64_t _lfortran_int64_rand_num() { + return rand(); +} + +LFORTRAN_API bool _lfortran_random_init(bool repeatable, bool image_distinct) { + if (repeatable) { + srand(0); + } else { + srand(time(NULL)); + } + return false; +} + +LFORTRAN_API int64_t _lfortran_random_seed(unsigned seed) +{ + srand(seed); + // The seed array size is typically 8 elements because Fortran's RNG often uses a seed with a fixed length of 8 integers to ensure sufficient randomness and repeatability in generating sequences of random numbers. + return 8; + +} + LFORTRAN_API int64_t _lpython_open(char *path, char *flags) { FILE *fd; @@ -2541,6 +2859,7 @@ LFORTRAN_API int64_t _lpython_open(char *path, char *flags) struct UNIT_FILE { int32_t unit; + char* filename; FILE* filep; bool unit_file_bin; }; @@ -2549,7 +2868,7 @@ int32_t last_index_used = -1; struct UNIT_FILE unit_to_file[MAXUNITS]; -void store_unit_file(int32_t unit_num, FILE* filep, bool unit_file_bin) { +void store_unit_file(int32_t unit_num, char* filename, FILE* filep, bool unit_file_bin) { for( int i = 0; i <= last_index_used; i++ ) { if( unit_to_file[i].unit == unit_num ) { unit_to_file[i].unit = unit_num; @@ -2563,6 +2882,7 @@ void store_unit_file(int32_t unit_num, FILE* filep, bool unit_file_bin) { exit(1); } unit_to_file[last_index_used].unit = unit_num; + unit_to_file[last_index_used].filename = filename; unit_to_file[last_index_used].filep = filep; unit_to_file[last_index_used].unit_file_bin = unit_file_bin; } @@ -2578,6 +2898,17 @@ FILE* get_file_pointer_from_unit(int32_t unit_num, bool *unit_file_bin) { return NULL; } +char* get_file_name_from_unit(int32_t unit_num, bool *unit_file_bin) { + *unit_file_bin = false; + for (int i = 0; i <= last_index_used; i++) { + if (unit_to_file[i].unit == unit_num) { + *unit_file_bin = unit_to_file[i].unit_file_bin; + return unit_to_file[i].filename; + } + } + return NULL; +} + void remove_from_unit_to_file(int32_t unit_num) { int index = -1; for( int i = 0; i <= last_index_used; i++ ) { @@ -2591,6 +2922,7 @@ void remove_from_unit_to_file(int32_t unit_num) { } for( int i = index; i < last_index_used; i++ ) { unit_to_file[i].unit = unit_to_file[i + 1].unit; + unit_to_file[i].filename = unit_to_file[i + 1].filename; unit_to_file[i].filep = unit_to_file[i + 1].filep; unit_to_file[i].unit_file_bin = unit_to_file[i + 1].unit_file_bin; } @@ -2611,7 +2943,18 @@ LFORTRAN_API int64_t _lfortran_open(int32_t unit_num, char *f_name, char *status form = "formatted"; } bool file_exists[1] = {false}; - _lfortran_inquire(f_name, file_exists, -1, NULL); + + size_t len = strlen(f_name); + if (*(f_name + len - 1) == ' ') { + // trim trailing spaces + char* end = f_name + len - 1; + while (end > f_name && isspace((unsigned char) *end)) { + end--; + } + *(end + 1) = '\0'; + } + + _lfortran_inquire(f_name, file_exists, -1, NULL, NULL); char *access_mode = NULL; /* STATUS=`specifier` in the OPEN statement @@ -2659,8 +3002,6 @@ LFORTRAN_API int64_t _lfortran_open(int32_t unit_num, char *f_name, char *status if (streql(form, "formatted")) { unit_file_bin = false; } else if (streql(form, "unformatted")) { - // TODO: Handle unformatted write to a file - access_mode = "rb"; unit_file_bin = true; } else { printf("Runtime error: FORM specifier in OPEN statement has " @@ -2675,22 +3016,44 @@ LFORTRAN_API int64_t _lfortran_open(int32_t unit_num, char *f_name, char *status perror(f_name); exit(1); } - store_unit_file(unit_num, fd, unit_file_bin); + store_unit_file(unit_num, f_name, fd, unit_file_bin); return (int64_t)fd; } LFORTRAN_API void _lfortran_flush(int32_t unit_num) { - bool unit_file_bin; - FILE* filep = get_file_pointer_from_unit(unit_num, &unit_file_bin); - if( filep == NULL ) { - printf("Specified UNIT %d in FLUSH is not connected.\n", unit_num); - exit(1); + // special case: flush all open units + if (unit_num == -1) { + for (int i = 0; i <= last_index_used; i++) { + if (unit_to_file[i].filep != NULL) { + fflush(unit_to_file[i].filep); + } + } + } else { + bool unit_file_bin; + FILE* filep = get_file_pointer_from_unit(unit_num, &unit_file_bin); + if( filep == NULL ) { + if ( unit_num == 6 ) { + // special case: flush OUTPUT_UNIT + fflush(stdout); + return; + } else if ( unit_num == 5 ) { + // special case: flush INPUT_UNIT + fflush(stdin); + return; + } else if ( unit_num == 0 ) { + // special case: flush ERROR_UNIT + fflush(stderr); + return; + } + printf("Specified UNIT %d in FLUSH is not connected.\n", unit_num); + exit(1); + } + fflush(filep); } - fflush(filep); } -LFORTRAN_API void _lfortran_inquire(char *f_name, bool *exists, int32_t unit_num, bool *opened) { +LFORTRAN_API void _lfortran_inquire(char *f_name, bool *exists, int32_t unit_num, bool *opened, int32_t *size) { if (f_name && unit_num != -1) { printf("File name and file unit number cannot be specifed together.\n"); exit(1); @@ -2699,6 +3062,10 @@ LFORTRAN_API void _lfortran_inquire(char *f_name, bool *exists, int32_t unit_num FILE *fp = fopen(f_name, "r"); if (fp != NULL) { *exists = true; + if (size != NULL) { + fseek(fp, 0, SEEK_END); + *size = ftell(fp); + } fclose(fp); // close the file return; } @@ -2775,7 +3142,7 @@ LFORTRAN_API void _lfortran_read_int64(int64_t *p, int32_t unit_num) { if (unit_num == -1) { // Read from stdin - (void)!scanf(INT64, p); + (void)!scanf("%" PRId64, p); return; } @@ -2789,7 +3156,7 @@ LFORTRAN_API void _lfortran_read_int64(int64_t *p, int32_t unit_num) if (unit_file_bin) { (void)!fread(p, sizeof(*p), 1, filep); } else { - (void)!fscanf(filep, INT64, p); + (void)!fscanf(filep, "%" PRId64, p); } } @@ -2847,10 +3214,19 @@ LFORTRAN_API void _lfortran_read_array_int32(int32_t *p, int array_size, int32_t LFORTRAN_API void _lfortran_read_char(char **p, int32_t unit_num) { + const char SPACE = ' '; + int n = strlen(*p); if (unit_num == -1) { // Read from stdin - *p = (char*)malloc(strlen(*p) * sizeof(char)); - (void)!scanf("%s", *p); + *p = (char*)malloc(n * sizeof(char)); + (void)!fgets(*p, n + 1, stdin); + (*p)[strcspn(*p, "\n")] = 0; + size_t input_length = strlen(*p); + while (input_length < n) { + strncat(*p, &SPACE, 1); + input_length++; + } + (*p)[n] = '\0'; return; } @@ -2861,12 +3237,54 @@ LFORTRAN_API void _lfortran_read_char(char **p, int32_t unit_num) exit(1); } - int n = strlen(*p); - *p = (char*)malloc(n * sizeof(char)); if (unit_file_bin) { - (void)!fread(*p, sizeof(char), n, filep); + // read the record marker for data length + int32_t data_length; + if (fread(&data_length, sizeof(int32_t), 1, filep) != 1) { + printf("Error reading data length from file.\n"); + exit(1); + } + + // allocate memory for the data based on data length + *p = (char*)malloc((data_length + 1) * sizeof(char)); + if (*p == NULL) { + printf("Memory allocation failed.\n"); + exit(1); + } + + // read the actual data + if (fread(*p, sizeof(char), data_length, filep) != data_length) { + printf("Error reading data from file.\n"); + free(*p); + exit(1); + } + (*p)[data_length] = '\0'; + + // read the record marker after data + int32_t check_length; + if (fread(&check_length, sizeof(int32_t), 1, filep) != 1) { + printf("Error reading end data length from file.\n"); + free(*p); + exit(1); + } + + // verify that the start and end markers match + if (check_length != data_length) { + printf("Data length mismatch between start and end markers.\n"); + free(*p); + exit(1); + } } else { - (void)!fscanf(filep, "%s", *p); + char *tmp_buffer = (char*)malloc((n + 1) * sizeof(char)); + (void)!fscanf(filep, "%s", tmp_buffer); + size_t input_length = strlen(tmp_buffer); + strcpy(*p, tmp_buffer); + free(tmp_buffer); + while (input_length < n) { + strncat(*p, &SPACE, 1); + input_length++; + } + (*p)[n] = '\0'; } if (streql(*p, "")) { printf("Runtime error: End of file!\n"); @@ -2950,12 +3368,23 @@ LFORTRAN_API void _lfortran_read_array_double(double *p, int array_size, int32_t LFORTRAN_API void _lfortran_read_array_char(char **p, int array_size, int32_t unit_num) { + // TODO: Add support for initializing character arrays to read more than one character + int n = 1; + const char SPACE = ' '; if (unit_num == -1) { // Read from stdin for (int i = 0; i < array_size; i++) { - int n = 1; // TODO: Support character length > 1 - p[i] = (char*) malloc(n * sizeof(char)); - (void)!scanf("%s", p[i]); + p[i] = (char*) malloc((n + 1) * sizeof(char)); + char *tmp_buffer = (char*)malloc((n + 1) * sizeof(char)); + (void)!fscanf(stdin, "%s", tmp_buffer); + size_t input_length = strlen(tmp_buffer); + strcpy(p[i], tmp_buffer); + free(tmp_buffer); + while (input_length < n) { + strncat(p[i], &SPACE, 1); + input_length++; + } + p[i][n] = '\0'; } return; } @@ -2968,12 +3397,21 @@ LFORTRAN_API void _lfortran_read_array_char(char **p, int array_size, int32_t un } for (int i = 0; i < array_size; i++) { - int n = 1; // TODO: Support character length > 1 - p[i] = (char*) malloc(n * sizeof(char)); + p[i] = (char*) malloc((n + 1) * sizeof(char)); if (unit_file_bin) { (void)!fread(p[i], sizeof(char), n, filep); + p[i][1] = '\0'; } else { - (void)!fscanf(filep, "%s", p[i]); + char *tmp_buffer = (char*)malloc((n + 1) * sizeof(char)); + (void)!fscanf(filep, "%s", tmp_buffer); + size_t input_length = strlen(tmp_buffer); + strcpy(p[i], tmp_buffer); + free(tmp_buffer); + while (input_length < n) { + strncat(p[i], &SPACE, 1); + input_length++; + } + p[i][n] = '\0'; } } } @@ -3015,14 +3453,35 @@ LFORTRAN_API void _lfortran_formatted_read(int32_t unit_num, int32_t* iostat, in char** arg = va_arg(args, char**); int n = strlen(*arg); - *arg = (char*)malloc(n * sizeof(char)); + *arg = (char*)malloc((n + 1) * sizeof(char)); + const char SPACE = ' '; if (unit_num == -1) { // Read from stdin - *iostat = !(fgets(*arg, n, stdin) == *arg); - (*arg)[strcspn(*arg, "\n")] = 0; - va_end(args); - return; + char *buffer = (char*)malloc((n + 1) * sizeof(char)); + if (fgets(buffer, n + 1, stdin) == NULL) { + *iostat = -1; + va_end(args); + free(buffer); + return; + } else { + if (streql(buffer, "\n")) { + *iostat = -2; + } else { + *iostat = 0; + } + + size_t input_length = strcspn(buffer, "\n"); + + *chunk = input_length; + while (input_length < n) { + buffer[input_length] = SPACE; + input_length++; + } + strcpy(*arg, buffer); + va_end(args); + free(buffer); + } } bool unit_file_bin; @@ -3030,16 +3489,33 @@ LFORTRAN_API void _lfortran_formatted_read(int32_t unit_num, int32_t* iostat, in if (!filep) { printf("No file found with given unit\n"); exit(1); - } + } else { + char *buffer = (char*)malloc((n + 1) * sizeof(char)); + if (fgets(buffer, n + 1, filep) == NULL) { + *iostat = -1; + va_end(args); + free(buffer); + return; + } else { + if (streql(buffer, "\n")) { + *iostat = -2; + } else { + *iostat = 0; + } - *iostat = !(fgets(*arg, n+1, filep) == *arg); - if (streql(*arg, "\n")) { - *iostat = -2; + (buffer)[strcspn(buffer, "\n")] = 0; + + size_t input_length = strlen(buffer); + *chunk = input_length; + while (input_length < n) { + strncat(buffer, &SPACE, 1); + input_length++; + } + strcpy(*arg, buffer); + va_end(args); + free(buffer); + } } - int len = strcspn(*arg, "\n"); - *chunk = len; - (*arg)[len] = 0; - va_end(args); } LFORTRAN_API void _lfortran_empty_read(int32_t unit_num, int32_t* iostat) { @@ -3092,32 +3568,149 @@ LFORTRAN_API void _lfortran_file_write(int32_t unit_num, int32_t* iostat, const if (!filep) { filep = stdout; } - if (unit_file_bin) { - printf("Binary content is not handled by write(..)\n"); - exit(1); - } va_list args; va_start(args, format); - vfprintf(filep, format, args); - va_end(args); + char* str = va_arg(args, char*); + // Detect "\b" to raise error + if(str[0] == '\b'){ + if(iostat == NULL){ + str = str+1; + fprintf(stderr, "%s",str); + exit(1); + } else { // Delegate error handling to the user. + *iostat = 11; + return; + } + } + if (unit_file_bin) { + // size the size of `str_len` to bytes + size_t str_len = strlen(str); + + // calculate record marker size + int32_t record_marker = (int32_t)str_len; + // write record marker before the data + fwrite(&record_marker, sizeof(record_marker), 1, filep); + + size_t written = fwrite(str, sizeof(char), str_len, filep); // write as binary data + + // write the record marker after the data + fwrite(&record_marker, sizeof(record_marker), 1, filep); + + if (written != str_len) { + printf("Error writing data to file.\n"); + // TODO: not sure what is the right value of "iostat" in this case + // it should be a positive value unique from other predefined iostat values + // like IOSTAT_INQUIRE_INTERNAL_UNIT, IOSTAT_END, and IOSTAT_EOR. + // currently, I've set it to 11 + if(iostat != NULL) *iostat = 11; + exit(1); + } else { + if(iostat != NULL) *iostat = 0; + } + } else { + if(strcmp(format, "%s%s") == 0){ + char* end = va_arg(args, char*); + fprintf(filep, format, str, end); + } else { + fprintf(filep, format, str); + } + if(iostat != NULL) *iostat = 0; + } + va_end(args); (void)!ftruncate(fileno(filep), ftell(filep)); - *iostat = 0; } -LFORTRAN_API void _lfortran_string_write(char **str, int32_t* iostat, const char *format, ...) { +LFORTRAN_API void _lfortran_string_write(char **str_holder, int64_t* size, int64_t* capacity, int32_t* iostat, const char *format, ...) { va_list args; va_start(args, format); - char *s = (char *) malloc(strlen(*str)*sizeof(char)); - vsprintf(s, format, args); - _lfortran_strcpy(str, s, 0); + char* str; + char* end = ""; + if(strcmp(format, "%s%s") == 0){ + str = va_arg(args, char*); + end = va_arg(args, char*); + } else if(strcmp(format, "%s") == 0){ + str = va_arg(args, char*); + } else { + fprintf(stderr,"Compiler Error : Undefined Format"); + exit(1); + } + + // Detect "\b" to raise error + if(str[0] == '\b'){ + if(iostat == NULL){ + str = str+1; + fprintf(stderr, "%s",str); + exit(1); + } else { // Delegate error handling to the user. + *iostat = 11; + return; + } + } + + char *s = (char *) malloc(strlen(str)*sizeof(char) + strlen(end)*sizeof(char) + 1); + sprintf(s, format, str, end); + + if(((*size) == -1) && ((*capacity) == -1)){ + _lfortran_strcpy_pointer_string(str_holder, s); + } else { + _lfortran_strcpy_descriptor_string(str_holder, s, size, capacity); + } free(s); va_end(args); - *iostat = 0; + if(iostat != NULL) *iostat = 0; +} + +LFORTRAN_API void _lfortran_string_read_i32(char *str, char *format, int32_t *i) { + sscanf(str, format, i); +} + +LFORTRAN_API void _lfortran_string_read_i64(char *str, char *format, int64_t *i) { + sscanf(str, format, i); +} + +LFORTRAN_API void _lfortran_string_read_f32(char *str, char *format, float *f) { + sscanf(str, format, f); +} + +LFORTRAN_API void _lfortran_string_read_f64(char *str, char *format, double *f) { + sscanf(str, format, f); +} + +LFORTRAN_API void _lfortran_string_read_str(char *str, char *format, char **s) { + sscanf(str, format, *s); } -LFORTRAN_API void _lfortran_string_read(char *str, char *format, int *i) { +LFORTRAN_API void _lfortran_string_read_bool(char *str, char *format, int32_t *i) { sscanf(str, format, i); + printf("%s\n", str); +} + +void lfortran_error(const char *message) { + fprintf(stderr, "LFORTRAN ERROR: %s\n", message); + exit(EXIT_FAILURE); +} + +// TODO: add support for reading comma separated string, into `_arr` functions +// by accepting array size as an argument as well +LFORTRAN_API void _lfortran_string_read_i32_array(char *str, char *format, int32_t *arr) { + lfortran_error("Reading into an array of int32_t is not supported."); +} + +LFORTRAN_API void _lfortran_string_read_i64_array(char *str, char *format, int64_t *arr) { + lfortran_error("Reading into an array of int64_t is not supported."); +} + +LFORTRAN_API void _lfortran_string_read_f32_array(char *str, char *format, float *arr) { + lfortran_error("Reading into an array of float is not supported."); +} + +LFORTRAN_API void _lfortran_string_read_f64_array(char *str, char *format, double *arr) { + lfortran_error("Reading into an array of double is not supported."); +} + +LFORTRAN_API void _lfortran_string_read_str_array(char *str, char *format, char **arr) { + lfortran_error("Reading into an array of strings is not supported."); } LFORTRAN_API void _lpython_close(int64_t fd) @@ -3129,7 +3722,7 @@ LFORTRAN_API void _lpython_close(int64_t fd) } } -LFORTRAN_API void _lfortran_close(int32_t unit_num) +LFORTRAN_API void _lfortran_close(int32_t unit_num, char* status) { bool unit_file_bin; FILE* filep = get_file_pointer_from_unit(unit_num, &unit_file_bin); @@ -3141,6 +3734,13 @@ LFORTRAN_API void _lfortran_close(int32_t unit_num) printf("Error in closing the file!\n"); exit(1); } + // TODO: Support other `status` specifiers + if (status && strcmp(status, "delete") == 0) { + if (remove(get_file_name_from_unit(unit_num, &unit_file_bin)) != 0) { + printf("Error in deleting file!\n"); + exit(1); + } + } remove_from_unit_to_file(unit_num); } @@ -3152,15 +3752,6 @@ LFORTRAN_API int32_t _lfortran_iachar(char *c) { return (int32_t) (uint8_t)(c[0]); } -LFORTRAN_API int32_t _lfortran_all(bool *mask, int32_t n) { - for (size_t i = 0; i < n; i++) { - if (!mask[i]) { - return false; - } - } - return true; -} - // Command line arguments int32_t _argc; char **_argv; @@ -3173,14 +3764,70 @@ LFORTRAN_API void _lpython_set_argv(int32_t argc_1, char *argv_1[]) { _argc = argc_1; } +LFORTRAN_API void _lpython_free_argv() { + if (_argv != NULL) { + for (size_t i = 0; i < _argc; i++) { + free(_argv[i]); + } + free(_argv); + _argv = NULL; + } +} + LFORTRAN_API int32_t _lpython_get_argc() { return _argc; } +LFORTRAN_API int32_t _lfortran_get_argc() { + return _argc - 1; +} + LFORTRAN_API char *_lpython_get_argv(int32_t index) { return _argv[index]; } +// get_command_argument +LFORTRAN_API char *_lfortran_get_command_argument_value(int n) { + if (n >= 0 && n < _argc) { + return strdup(_argv[n]); // Return a copy of the nth argument + } else { + return ""; + } +} + +LFORTRAN_API int32_t _lfortran_get_command_argument_length(int n) { + char* out = _lfortran_get_command_argument_value(n); + return strlen(out); +} + +LFORTRAN_API int32_t _lfortran_get_command_argument_status() { + return 0; +} + +// get_command +LFORTRAN_API char *_lfortran_get_command_command() { + char* out; + for(int i=0; i<_argc; i++) { + if(i == 0) { + out = strdup(_argv[i]); + } else { + out = realloc(out, strlen(out) + strlen(_argv[i]) + 1); + strcat(out, " "); + strcat(out, _argv[i]); + } + } + return out; +} + +LFORTRAN_API int32_t _lfortran_get_command_length() { + char* out = _lfortran_get_command_command(); + return strlen(out); +} + +LFORTRAN_API int32_t _lfortran_get_command_status() { + return 1; +} + // << Command line arguments << ------------------------------------------------ // Initial setup @@ -3188,6 +3835,10 @@ LFORTRAN_API void _lpython_call_initial_functions(int32_t argc_1, char *argv_1[] _lpython_set_argv(argc_1, argv_1); _lfortran_init_random_clock(); } + +LFORTRAN_API int32_t _lfortran_command_argument_count() { + return _argc - 1; +} // << Initial setup << --------------------------------------------------------- // >> Runtime Stacktrace >> ---------------------------------------------------- @@ -3319,7 +3970,7 @@ void get_local_address_mac(struct Stacktrace *d) { printf("The stack address was not found in any shared library or" " the main program, the stack is probably corrupted.\n" "Aborting...\n"); - exit(1); + abort(); } #endif // HAVE_LFORTRAN_MACHO @@ -3335,7 +3986,7 @@ void get_local_address(struct Stacktrace *d) { printf("The stack address was not found in any shared library or" " the main program, the stack is probably corrupted.\n" "Aborting...\n"); - exit(1); + abort(); } #else #ifdef HAVE_LFORTRAN_MACHO @@ -3367,7 +4018,7 @@ uint32_t get_file_size(int64_t fp) { void get_local_info_dwarfdump(struct Stacktrace *d) { // TODO: Read the contents of lines.dat from here itself. char *base_name = get_base_name(source_filename); - char *filename = malloc(strlen(base_name) + 14); + char *filename = malloc(strlen(base_name) + 15); strcpy(filename, base_name); strcat(filename, "_lines.dat.txt"); int64_t fd = _lpython_open(filename, "r"); @@ -3495,6 +4146,15 @@ LFORTRAN_API void print_stacktrace_addresses(char *filename, bool use_colors) { // << Runtime Stacktrace << ---------------------------------------------------- +LFORTRAN_API char *_lfortran_get_environment_variable(char *name) { + // temporary solution, the below function _lfortran_get_env_variable should be used + if (name == NULL) { + return NULL; + } else { + return getenv("HOME"); + } +} + LFORTRAN_API char *_lfortran_get_env_variable(char *name) { return getenv(name); } diff --git a/src/libasr/runtime/lfortran_intrinsics.h b/src/libasr/runtime/lfortran_intrinsics.h index e857171da5..cdc17181ff 100644 --- a/src/libasr/runtime/lfortran_intrinsics.h +++ b/src/libasr/runtime/lfortran_intrinsics.h @@ -68,7 +68,7 @@ typedef double _Complex double_complex_t; LFORTRAN_API double _lfortran_sum(int n, double *v); LFORTRAN_API void _lfortran_random_number(int n, double *v); LFORTRAN_API void _lfortran_init_random_clock(); -LFORTRAN_API void _lfortran_init_random_seed(unsigned seed); +LFORTRAN_API int _lfortran_init_random_seed(unsigned seed); LFORTRAN_API double _lfortran_random(); LFORTRAN_API int _lfortran_randrange(int lower, int upper); LFORTRAN_API int _lfortran_random_int(int lower, int upper); @@ -105,8 +105,8 @@ LFORTRAN_API float_complex_t _lfortran_cexp(float_complex_t x); LFORTRAN_API double_complex_t _lfortran_zexp(double_complex_t x); LFORTRAN_API float _lfortran_slog(float x); LFORTRAN_API double _lfortran_dlog(double x); -LFORTRAN_API bool _lfortran_rsp_is_nan(float x); -LFORTRAN_API bool _lfortran_rdp_is_nan(double x); +LFORTRAN_API bool _lfortran_sis_nan(float x); +LFORTRAN_API bool _lfortran_dis_nan(double x); LFORTRAN_API float_complex_t _lfortran_clog(float_complex_t x); LFORTRAN_API double_complex_t _lfortran_zlog(double_complex_t x); LFORTRAN_API float _lfortran_serf(float x); @@ -195,7 +195,8 @@ LFORTRAN_API int32_t _lpython_bit_length8(int64_t num); LFORTRAN_API void _lfortran_strrepeat(char** s, int32_t n, char** dest); LFORTRAN_API char* _lfortran_strrepeat_c(char* s, int32_t n); LFORTRAN_API void _lfortran_strcat(char** s1, char** s2, char** dest); -LFORTRAN_API void _lfortran_strcpy(char** x, char *y, int8_t free_target); +LFORTRAN_API void _lfortran_strcpy_pointer_string(char** x, char *y); +LFORTRAN_API void _lfortran_strcpy_descriptor_string(char** x, char *y, int64_t* x_string_size, int64_t* x_string_capacity); LFORTRAN_API int32_t _lfortran_str_len(char** s); LFORTRAN_API int _lfortran_str_ord(char** s); LFORTRAN_API int _lfortran_str_ord_c(char* s); @@ -206,10 +207,9 @@ LFORTRAN_API void _lfortran_memset(void* s, int32_t c, int32_t size); LFORTRAN_API int8_t* _lfortran_realloc(int8_t* ptr, int32_t size); LFORTRAN_API int8_t* _lfortran_calloc(int32_t count, int32_t size); LFORTRAN_API void _lfortran_free(char* ptr); -LFORTRAN_API void _lfortran_alloc(char** ptr, int32_t len); +LFORTRAN_API void _lfortran_alloc(char** ptr, int32_t len, int64_t* size, int64_t* capacity); LFORTRAN_API void _lfortran_string_init(int size_plus_one, char *s); -LFORTRAN_API char* _lfortran_str_item(char* s, int32_t idx); -LFORTRAN_API bool _lfortran_str_contains(char* str, char* substr); +LFORTRAN_API char* _lfortran_str_item(char* s, int64_t idx); LFORTRAN_API char* _lfortran_str_copy(char* s, int32_t idx1, int32_t idx2); // idx1 and idx2 both start from 1 LFORTRAN_API char* _lfortran_str_slice(char* s, int32_t idx1, int32_t idx2, int32_t step, bool idx1_present, bool idx2_present); @@ -221,20 +221,24 @@ LFORTRAN_API int64_t _lfortran_mvbits64(int64_t from, int32_t frompos, int32_t len, int64_t to, int32_t topos); LFORTRAN_API int32_t _lfortran_ibits32(int32_t i, int32_t pos, int32_t len); LFORTRAN_API int64_t _lfortran_ibits64(int64_t i, int32_t pos, int32_t len); -LFORTRAN_API void _lfortran_cpu_time(double *t); +LFORTRAN_API double _lfortran_d_cpu_time(); +LFORTRAN_API float _lfortran_s_cpu_time(); LFORTRAN_API void _lfortran_i32sys_clock( int32_t *count, int32_t *rate, int32_t *max); LFORTRAN_API void _lfortran_i64sys_clock( uint64_t *count, int64_t *rate, int64_t *max); LFORTRAN_API void _lfortran_i64r64sys_clock( uint64_t *count, double *rate, int64_t *max); -LFORTRAN_API double _lfortran_time(); +LFORTRAN_API char* _lfortran_date(); +LFORTRAN_API char* _lfortran_time(); +LFORTRAN_API char* _lfortran_zone(); +LFORTRAN_API int32_t _lfortran_values(int32_t n); LFORTRAN_API float _lfortran_sp_rand_num(); LFORTRAN_API double _lfortran_dp_rand_num(); LFORTRAN_API int64_t _lpython_open(char *path, char *flags); LFORTRAN_API int64_t _lfortran_open(int32_t unit_num, char *f_name, char *status, char* form); LFORTRAN_API void _lfortran_flush(int32_t unit_num); -LFORTRAN_API void _lfortran_inquire(char *f_name, bool *exists, int32_t unit_num, bool *opened); +LFORTRAN_API void _lfortran_inquire(char *f_name, bool *exists, int32_t unit_num, bool *opened, int32_t *size); LFORTRAN_API void _lfortran_formatted_read(int32_t unit_num, int32_t* iostat, int32_t* chunk, char* fmt, int32_t no_of_args, ...); LFORTRAN_API char* _lpython_read(int64_t fd, int64_t n); LFORTRAN_API void _lfortran_read_int32(int32_t *p, int32_t unit_num); @@ -245,21 +249,32 @@ LFORTRAN_API void _lfortran_read_float(float *p, int32_t unit_num); LFORTRAN_API void _lfortran_read_array_float(float *p, int array_size, int32_t unit_num); LFORTRAN_API void _lfortran_read_array_double(double *p, int array_size, int32_t unit_num); LFORTRAN_API void _lfortran_read_char(char **p, int32_t unit_num); -LFORTRAN_API void _lfortran_string_write(char **str, int32_t* iostat, const char *format, ...); +LFORTRAN_API void _lfortran_string_write(char **str, int64_t* size, int64_t* capacity, int32_t* iostat, const char *format, ...); LFORTRAN_API void _lfortran_file_write(int32_t unit_num, int32_t* iostat, const char *format, ...); -LFORTRAN_API void _lfortran_string_read(char *str, char *format, int *i); +LFORTRAN_API void _lfortran_string_read_i32(char *str, char *format, int32_t *i); +LFORTRAN_API void _lfortran_string_read_i32_array(char *str, char *format, int32_t *arr); +LFORTRAN_API void _lfortran_string_read_i64(char *str, char *format, int64_t *i); +LFORTRAN_API void _lfortran_string_read_i64_array(char *str, char *format, int64_t *arr); +LFORTRAN_API void _lfortran_string_read_f32(char *str, char *format, float *f); +LFORTRAN_API void _lfortran_string_read_f32_array(char *str, char *format, float *arr); +LFORTRAN_API void _lfortran_string_read_f64(char *str, char *format, double *f); +LFORTRAN_API void _lfortran_string_read_f64_array(char *str, char *format, double *arr); +LFORTRAN_API void _lfortran_string_read_str(char *str, char *format, char **s); +LFORTRAN_API void _lfortran_string_read_str_array(char *str, char *format, char **arr); +LFORTRAN_API void _lfortran_string_read_bool(char *str, char *format, int32_t *i); LFORTRAN_API void _lfortran_empty_read(int32_t unit_num, int32_t* iostat); LFORTRAN_API void _lpython_close(int64_t fd); -LFORTRAN_API void _lfortran_close(int32_t unit_num); +LFORTRAN_API void _lfortran_close(int32_t unit_num, char* status); LFORTRAN_API int32_t _lfortran_ichar(char *c); LFORTRAN_API int32_t _lfortran_iachar(char *c); -LFORTRAN_API int32_t _lfortran_all(bool *mask, int32_t n); LFORTRAN_API void _lpython_set_argv(int32_t argc_1, char *argv_1[]); +LFORTRAN_API void _lpython_free_argv(); LFORTRAN_API int32_t _lpython_get_argc(); LFORTRAN_API char *_lpython_get_argv(int32_t index); LFORTRAN_API void _lpython_call_initial_functions(int32_t argc_1, char *argv_1[]); LFORTRAN_API void print_stacktrace_addresses(char *filename, bool use_colors); LFORTRAN_API char *_lfortran_get_env_variable(char *name); +LFORTRAN_API char *_lfortran_get_environment_variable(char *name); LFORTRAN_API int _lfortran_exec_command(char *cmd); LFORTRAN_API char* _lcompilers_string_format_fortran(int count, const char* format, ...); diff --git a/src/libasr/semantic_exception.h b/src/libasr/semantic_exception.h index 9a4d4fd299..db662228fa 100644 --- a/src/libasr/semantic_exception.h +++ b/src/libasr/semantic_exception.h @@ -8,20 +8,6 @@ namespace LCompilers { // This exception is only used internally in the lfortran/semantics/ directory // and in lfortran/asr_utils.h/cpp. Nowhere else. -class SemanticError -{ -public: - diag::Diagnostic d; -public: - SemanticError(const std::string &msg, const Location &loc) - : d{diag::Diagnostic(msg, diag::Level::Error, diag::Stage::Semantic, { - diag::Label("", {loc}) - })} - { } - - SemanticError(const diag::Diagnostic &d) : d{d} { } -}; - class SemanticAbort { }; diff --git a/src/libasr/serialization.cpp b/src/libasr/serialization.cpp index 3b5148fc09..843c04f68e 100644 --- a/src/libasr/serialization.cpp +++ b/src/libasr/serialization.cpp @@ -7,6 +7,8 @@ #include #include #include +#include +#include using LCompilers::ASRUtils::symbol_parent_symtab; using LCompilers::ASRUtils::symbol_name; @@ -59,13 +61,13 @@ class ASRDeserializationVisitor : { public: ASRDeserializationVisitor(Allocator &al, const std::string &s, - bool load_symtab_id) : + bool load_symtab_id, uint32_t offset) : #ifdef WITH_LFORTRAN_BINARY_MODFILES BinaryReader(s), #else TextReader(s), #endif - DeserializationBaseVisitor(al, load_symtab_id) {} + DeserializationBaseVisitor(al, load_symtab_id, offset) {} bool read_bool() { uint8_t b = read_int8(); @@ -232,7 +234,7 @@ class FixParentSymtabVisitor : public BaseWalkVisitor current_symtab = parent_symtab; } - void visit_EnumType(const EnumType_t &x) { + void visit_Enum(const Enum_t &x) { SymbolTable *parent_symtab = current_symtab; current_symtab = x.m_symtab; x.m_symtab->parent = parent_symtab; @@ -361,8 +363,8 @@ class FixExternalSymbolsVisitor : public BaseWalkVisitor(m_sym); sym = m->m_symtab->find_scoped_symbol(original_name, x.n_scope_names, x.m_scope_names); - } else if( ASR::is_a(*m_sym) ) { - EnumType_t *m = down_cast(m_sym); + } else if( ASR::is_a(*m_sym) ) { + Enum_t *m = down_cast(m_sym); sym = m->m_symtab->find_scoped_symbol(original_name, x.n_scope_names, x.m_scope_names); } else if( ASR::is_a(*m_sym) ) { @@ -410,13 +412,13 @@ void fix_external_symbols(ASR::TranslationUnit_t &unit, } ASR::asr_t* deserialize_asr(Allocator &al, const std::string &s, - bool load_symtab_id, SymbolTable & /*external_symtab*/) { - return deserialize_asr(al, s, load_symtab_id); + bool load_symtab_id, SymbolTable & /*external_symtab*/, uint32_t offset) { + return deserialize_asr(al, s, load_symtab_id, offset); } ASR::asr_t* deserialize_asr(Allocator &al, const std::string &s, - bool load_symtab_id) { - ASRDeserializationVisitor v(al, s, load_symtab_id); + bool load_symtab_id, uint32_t offset) { + ASRDeserializationVisitor v(al, s, load_symtab_id, offset); ASR::asr_t *node = v.deserialize_node(); ASR::TranslationUnit_t *tu = ASR::down_cast2(node); diff --git a/src/libasr/serialization.h b/src/libasr/serialization.h index 70f895c681..38dd077219 100644 --- a/src/libasr/serialization.h +++ b/src/libasr/serialization.h @@ -8,9 +8,9 @@ namespace LCompilers { std::string serialize(const ASR::asr_t &asr); std::string serialize(const ASR::TranslationUnit_t &unit); ASR::asr_t* deserialize_asr(Allocator &al, const std::string &s, - bool load_symtab_id, SymbolTable &symtab); + bool load_symtab_id, SymbolTable &symtab, uint32_t offset); ASR::asr_t* deserialize_asr(Allocator &al, const std::string &s, - bool load_symtab_id); + bool load_symtab_id, uint32_t offset); void fix_external_symbols(ASR::TranslationUnit_t &unit, SymbolTable &external_symtab); diff --git a/src/libasr/stacktrace.cpp b/src/libasr/stacktrace.cpp index 4e3b4bbee9..eda8ca2d3e 100644 --- a/src/libasr/stacktrace.cpp +++ b/src/libasr/stacktrace.cpp @@ -9,6 +9,14 @@ #include #include +#ifdef HAVE_LFORTRAN_LLVM_STACKTRACE +#include +#include +#include +#include +#include +#endif + // free() and abort() functions #include @@ -324,7 +332,7 @@ void get_symbol_info_bfd(std::string binary_filename, uintptr_t addr, abfd = bfd_openr(binary_filename.c_str(), NULL); if (abfd == NULL) { std::cout << "Cannot open the binary file '" + binary_filename + "'\n"; - abort(); + exit(1); } if (bfd_check_format(abfd, bfd_archive)) { #ifdef __APPLE__ @@ -336,19 +344,19 @@ void get_symbol_info_bfd(std::string binary_filename, uintptr_t addr, #else // On Linux this should work for any file, so we generate an error std::cout << "Cannot get addresses from the archive '" + binary_filename + "'\n"; - abort(); + exit(1); #endif } char **matching; if (!bfd_check_format_matches(abfd, bfd_object, &matching)) { std::cout << "Unknown format of the binary file '" + binary_filename + "'\n"; - abort(); + exit(1); } data.symbol_table = NULL; // This allocates the symbol_table: if (load_symbol_table(abfd, &data) == 1) { std::cout << "Failed to load the symbol table from '" + binary_filename + "'\n"; - abort(); + exit(1); } // Loops over all sections and try to find the line bfd_map_over_sections(abfd, process_section, &data); @@ -489,6 +497,63 @@ std::string addr2str(const StacktraceItem &i) return s.str(); } +#ifdef HAVE_LFORTRAN_LLVM_STACKTRACE +void get_symbol_info_llvm(StacktraceItem &item, llvm::symbolize::LLVMSymbolizer &symbolizer) { + auto binary_file = llvm::object::ObjectFile::createObjectFile(item.binary_filename); + + if (!binary_file) { +#ifdef __APPLE__ + // This can happen for dynamic libraries in macOS, + // like /usr/lib/system/libsystem_c.dylib + return; +#endif + std::cout << "Cannot open the binary file '" + item.binary_filename + "'\n"; + exit(1); + } + + llvm::object::ObjectFile *obj_file = binary_file.get().getBinary(); + + uint64_t section_index; + bool found = false; + for (const auto& section : obj_file->sections()) { + if (section.getAddress() <= item.local_pc && item.local_pc < section.getAddress() + section.getSize()) { + section_index = section.getIndex(); + found = true; + break; + } + } + + if (!found) { + std::cout << "Cannot find the section for the address " << item.local_pc << " in the binary file '" + item.binary_filename + "'\n"; + exit(1); + } + + llvm::object::SectionedAddress sa = {item.local_pc, section_index}; + auto result = symbolizer.symbolizeCode(item.binary_filename, sa); + + if (result) { + // If there is no filename, at least we can show the binary file + item.source_filename = (result->FileName == "") ? "" : result->FileName; + item.function_name = result->FunctionName; + item.line_number = result->Line; + } else { + std::cout << "Cannot open the symbol table of '" + item.binary_filename + "'\n"; + exit(1); + } +} + +void get_llvm_info(std::vector &d) +{ + llvm::symbolize::LLVMSymbolizer::Options opts; + opts.Demangle = true; + llvm::symbolize::LLVMSymbolizer symbolizer(opts); + + for (auto &item : d) { + get_symbol_info_llvm(item, symbolizer); + } +} + +#endif /* Returns a std::string with the stacktrace corresponding to the @@ -563,6 +628,11 @@ void address_to_line_number(const std::vector &filenames, uintptr_t address, std::string &filename, int &line_number) { + if (addresses.size() == 0) { + line_number = -1; + filename = ""; + return; + } uintptr_t actual_address = address-16; int n = addresses.size() / 3; // Bisection-Search @@ -623,21 +693,26 @@ void get_local_info_dwarfdump(std::vector &d) } } + void get_local_info(std::vector &d) { +#ifdef HAVE_LFORTRAN_LLVM_STACKTRACE + get_llvm_info(d); +#else #ifdef HAVE_LFORTRAN_DWARFDUMP get_local_info_dwarfdump(d); #else -# ifdef HAVE_LFORTRAN_BFD +#ifdef HAVE_LFORTRAN_BFD bfd_init(); -# endif for (size_t i=0; i < d.size(); i++) { -# ifdef HAVE_LFORTRAN_BFD get_symbol_info_bfd(d[i].binary_filename, d[i].local_pc, d[i].source_filename, d[i].function_name, d[i].line_number); -# endif } -#endif +#else + (void)d; +#endif // HAVE_LFORTRAN_BFD +#endif // HAVE_LFOTRAN_DWARFDUMP +#endif // HAVE_LFORTRAN_LLVM_STACKTRACE } std::string error_stacktrace(const std::vector &stacktrace) diff --git a/src/libasr/stacktrace.h b/src/libasr/stacktrace.h index 5a3e653943..8b4043fb69 100644 --- a/src/libasr/stacktrace.h +++ b/src/libasr/stacktrace.h @@ -51,6 +51,8 @@ void get_local_addresses(std::vector &d); // `source_filename` and `line_number` if available void get_local_info(std::vector &d); +void get_llvm_info(std::vector &d); + // Converts the information stored in `d` into a string std::string stacktrace2str(const std::vector &d, int skip); diff --git a/src/libasr/string_utils.cpp b/src/libasr/string_utils.cpp index 04d68033a8..4b838a9570 100644 --- a/src/libasr/string_utils.cpp +++ b/src/libasr/string_utils.cpp @@ -38,17 +38,41 @@ char *s2c(Allocator &al, const std::string &s) { } // Splits the string `s` using the separator `split_string` -std::vector string_split(const std::string &s, const std::string &split_string) +std::vector string_split(const std::string &s, + const std::string &split_string, bool strs_to_lower) { std::vector result; size_t old_pos = 0; size_t new_pos; + std::string substr; while ((new_pos = s.find(split_string, old_pos)) != std::string::npos) { - std::string substr = s.substr(old_pos, new_pos-old_pos); - if (substr.size() > 0) result.push_back(substr); + substr = s.substr(old_pos, new_pos-old_pos); + if (substr.size() > 0) + result.push_back(strs_to_lower ? to_lower(substr) : substr); old_pos = new_pos+split_string.size(); } - result.push_back(s.substr(old_pos)); + substr = s.substr(old_pos); + result.push_back(strs_to_lower ? to_lower(substr) : substr); + return result; +} + +std::vector string_split_avoid_parentheses(const std::string &str, bool strs_to_lower) { + std::vector result; + std::string word; + bool in_brackets = false; + for (char ch : str) { + if (ch == ' ' && !in_brackets) { + if (!word.empty()) { + result.push_back(strs_to_lower ? LCompilers::to_lower(word) : word); + word.clear(); + } + } else { + if (ch == '(') in_brackets = true; + if (ch == ')') in_brackets = false; + word += ch; + } + } + if (!word.empty()) result.push_back(strs_to_lower ? LCompilers::to_lower(word) : word); return result; } @@ -116,7 +140,7 @@ std::string read_file(const std::string &filename) std::vector bytes(filesize); ifs.read(&bytes[0], filesize); - return replace(std::string(&bytes[0], filesize), "\r\n", "\n"); + return std::string(&bytes[0], filesize); } std::string parent_path(const std::string &path) { @@ -241,4 +265,22 @@ char* str_unescape_fortran(Allocator &al, LCompilers::Str &s, char ch) { return LCompilers::s2c(al, x); } +bool str_compare(const unsigned char *pos, std::string s) { + for (size_t i = 0; i < s.size(); i++) { + if (pos[i] == '\0') { + return false; + } + + if (pos[i] != s[i]) { + return false; + } + } + return true; +} + +// trim trailing whitespace from a string in-place +void rtrim(std::string& str) { + str.erase(std::find_if_not(str.rbegin(), str.rend(), ::isspace).base(), str.end()); +} + } // namespace LCompilers diff --git a/src/libasr/string_utils.h b/src/libasr/string_utils.h index d41e3eb82b..9ef70de30b 100644 --- a/src/libasr/string_utils.h +++ b/src/libasr/string_utils.h @@ -14,7 +14,10 @@ namespace LCompilers { bool startswith(const std::string &s, const std::string &e); bool endswith(const std::string &s, const std::string &e); std::string to_lower(const std::string &s); -std::vector string_split(const std::string &s, const std::string &split_string); +std::vector string_split(const std::string &s, + const std::string &split_string, bool strs_to_lower=true); +std::vector string_split_avoid_parentheses(const std::string &s, + bool strs_to_lower=true); std::vector split(const std::string &s); std::string join(const std::string j, const std::vector &v); std::vector slice(const std::vector &v, @@ -45,6 +48,9 @@ char* str_unescape_c(Allocator &al, LCompilers::Str &s); std::string str_escape_fortran_double_quote(const std::string &s); char* str_unescape_fortran(Allocator &al, LCompilers::Str &s, char ch); +bool str_compare(const unsigned char *pos, std::string s); +void rtrim(std::string& str); + } // namespace LCompilers #endif // LFORTRAN_STRING_UTILS_H diff --git a/src/libasr/utils.h b/src/libasr/utils.h index 97417b2bf4..8b05458a63 100644 --- a/src/libasr/utils.h +++ b/src/libasr/utils.h @@ -61,6 +61,8 @@ struct PassOptions { bool c_mangling = false; bool enable_cpython = false; bool c_skip_bindpy_pass = false; + bool openmp = false; + bool enable_gpu_offloading = false; }; struct CompilerOptions { @@ -84,8 +86,17 @@ struct CompilerOptions { bool visualize = false; bool fast = false; bool openmp = false; + std::string openmp_lib_dir = ""; + bool lookup_name = false; + bool rename_symbol = false; + std::string line = ""; + std::string column = ""; + bool continue_compilation = false; + bool semantics_only = false; bool generate_object_code = false; bool no_warnings = false; + bool disable_style = false; + bool logical_casting = false; bool no_error_banner = false; bool enable_bounds_checking = false; std::string error_format = "human"; @@ -100,12 +111,15 @@ struct CompilerOptions { std::string arg_o = ""; bool emit_debug_info = false; bool emit_debug_line_column = false; + bool enable_cpython = false; bool enable_symengine = false; bool link_numpy = false; bool run = false; bool legacy_array_sections = false; bool ignore_pragma = false; bool stack_arrays = false; + bool wasm_html = false; + std::string emcc_embed; std::vector import_paths; Platform platform; diff --git a/src/libasr/utils2.cpp b/src/libasr/utils2.cpp index 075bdb9923..d0f9ec0e14 100644 --- a/src/libasr/utils2.cpp +++ b/src/libasr/utils2.cpp @@ -30,8 +30,10 @@ std::string get_unique_ID() { bool read_file(const std::string &filename, std::string &text) { + if (filename.empty()) return false; std::ifstream ifs(filename.c_str(), std::ios::in | std::ios::binary | std::ios::ate); + if (!ifs.is_open()) return false; std::ifstream::pos_type filesize = ifs.tellg(); if (filesize < 0) return false; @@ -39,6 +41,7 @@ bool read_file(const std::string &filename, std::string &text) ifs.seekg(0, std::ios::beg); std::vector bytes(filesize); + if (filesize == 0) bytes.reserve(1); ifs.read(&bytes[0], filesize); text = std::string(&bytes[0], filesize); diff --git a/src/libasr/wasm_instructions_visitor.py b/src/libasr/wasm_instructions_visitor.py index 614042ac48..849650d3ba 100644 --- a/src/libasr/wasm_instructions_visitor.py +++ b/src/libasr/wasm_instructions_visitor.py @@ -36,10 +36,10 @@ def __init__(self, stream, data): self.data = data def visit_BaseWASMVisitor(self, mod, *args): - self.emit("template ", 0) + self.emit("template ", 0) self.emit("class BaseWASMVisitor {", 0) self.emit("private:", 0) - self.emit( "Struct& self() { return static_cast(*this); }", 1) + self.emit( "StructType& self() { return static_cast(*this); }", 1) self.emit("public:", 0) self.emit( "Vec &code;", 1) self.emit( "uint32_t offset;\n", 1) @@ -105,12 +105,12 @@ def visit_BaseWASMVisitor(self, mod, *args): self.emit("};\n", 0) def visit_WASMInstsAssembler(self, mod): - self.emit("template ", 0) + self.emit("template ", 0) self.emit("class WASMInstsAssembler {", 0) self.emit("private:", 0) self.emit( "Allocator &m_al;", 1) self.emit( "Vec &m_code;\n", 1) - self.emit( "Struct &self() { return static_cast(*this); }", 1) + self.emit( "StructType &self() { return static_cast(*this); }", 1) self.emit("public:", 0) self.emit( "WASMInstsAssembler(Allocator &al, Vec &code): m_al(al), m_code(code) {}\n", 1) @@ -171,7 +171,7 @@ def process_raw_instructions(instructions_raw): return instructions def get_func_name(func, emit = False): - splitted_name = re.split("[\._]", func) + splitted_name = re.split("[._]", func) if emit: return "_".join(splitted_name) return "".join(map(lambda name_sub_part: name_sub_part.capitalize(), splitted_name)) diff --git a/src/lpython/python_evaluator.cpp b/src/lpython/python_evaluator.cpp index f4fa810f39..654cbd1c44 100644 --- a/src/lpython/python_evaluator.cpp +++ b/src/lpython/python_evaluator.cpp @@ -162,7 +162,7 @@ Result PythonCompiler::evaluate( ASR::symbol_t *fn = ASR::down_cast(symbol_table->resolve_symbol(module_name)) ->m_symtab->get_symbol(run_fn); LCOMPILERS_ASSERT(fn) - if (ASRUtils::get_FunctionType(fn)->m_return_var_type->type == ASR::ttypeType::Character) { + if (ASRUtils::get_FunctionType(fn)->m_return_var_type->type == ASR::ttypeType::String) { char *r = e->execfn(run_fn); result.type = EvalResult::string; result.str = r; @@ -655,7 +655,7 @@ void print_type(ASR::ttype_t *t, void *data, std::string &result) { } break; } - case ASR::ttypeType::Character: + case ASR::ttypeType::String: result += '"'; result += std::string(*(char**)data); // TODO: replace \n with \\n result += '"'; diff --git a/src/lpython/python_serialization.cpp b/src/lpython/python_serialization.cpp index 7afe96faa8..4ebf483f94 100644 --- a/src/lpython/python_serialization.cpp +++ b/src/lpython/python_serialization.cpp @@ -23,7 +23,7 @@ class ASTDeserializationVisitor : #else TextReader(s), #endif - DeserializationBaseVisitor(al, true) {} + DeserializationBaseVisitor(al, true, 0) {} bool read_bool() { uint8_t b = read_int8(); diff --git a/src/lpython/semantics/python_ast_to_asr.cpp b/src/lpython/semantics/python_ast_to_asr.cpp index 63c87dbe4a..9a9b499304 100644 --- a/src/lpython/semantics/python_ast_to_asr.cpp +++ b/src/lpython/semantics/python_ast_to_asr.cpp @@ -40,10 +40,10 @@ namespace LCompilers::LPython { int save_pyc_files(const ASR::TranslationUnit_t &u, - std::string infile) { + std::string infile, LocationManager& lm) { diag::Diagnostics diagnostics; LCOMPILERS_ASSERT(asr_verify(u, true, diagnostics)); - std::string modfile_binary = save_pycfile(u); + std::string modfile_binary = save_pycfile(u, lm); while( infile.back() != '.' ) { infile.pop_back(); @@ -217,7 +217,7 @@ ASR::Module_t* load_module(Allocator &al, SymbolTable *symtab, found = set_module_path(infile0, rl_path, infile, path_used, input, lpython, enum_py); } else { - mod1 = load_pycfile(al, input, false); + mod1 = load_pycfile(al, input, false, lm); fix_external_symbols(*mod1, *ASRUtils::get_tu_symtab(symtab)); diag::Diagnostics diagnostics; LCOMPILERS_ASSERT(asr_verify(*mod1, true, diagnostics)); @@ -308,8 +308,8 @@ void get_calls_to_global_stmts(Allocator &al, const Location &loc, SymbolTable* } } -template -class CommonVisitor : public AST::BaseVisitor { +template +class CommonVisitor : public AST::BaseVisitor { public: diag::Diagnostics &diag; @@ -345,7 +345,7 @@ class CommonVisitor : public AST::BaseVisitor { std::vector import_paths; /* current_body exists only for Functions, For, If (& its Else part), While. - current_body does not exist for Modules, ClassDef/Structs. + current_body does not exist for Modules, ClassDef/StructTypes. */ Vec *current_body; ASR::expr_t* assign_asr_target; @@ -538,15 +538,17 @@ class CommonVisitor : public AST::BaseVisitor { fill_new_dims(t, func_calls, new_dims); return ASRUtils::make_Array_t_util(al, loc, t_m_type, new_dims.p, new_dims.size()); } - case ASR::ttypeType::Character: { - ASR::Character_t *t = ASR::down_cast(return_type); + case ASR::ttypeType::String: { + ASR::String_t *t = ASR::down_cast(return_type); func_calls.push_back(t->m_len_expr); fix_exprs_ttype_t(func_calls, args, f); int64_t a_len = t->m_len; if( func_calls[0] ) { - a_len = ASRUtils::extract_len(func_calls[0], loc); + diag::Diagnostics diags; + a_len = ASRUtils::extract_len(func_calls[0], loc, diags); } - return ASRUtils::TYPE(ASR::make_Character_t(al, loc, t->m_kind, a_len, func_calls[0])); + return ASRUtils::TYPE(ASR::make_String_t(al, loc, t->m_kind, a_len, + func_calls[0], ASR::string_physical_typeType::PointerString)); } case ASR::ttypeType::StructType: { ASR::StructType_t* struct_t_type = ASR::down_cast(return_type); @@ -796,10 +798,10 @@ class CommonVisitor : public AST::BaseVisitor { ASRUtils::symbol_get_past_external( r_type->m_derived_type)); if ( ASRUtils::is_derived_type_similar(l2_type, r2_type) ) { - cast_helper(m_args[i], c_arg.m_value, true, true); + cast_helper(m_args[i], c_arg.m_value, true, true); check_type_equality = false; } else { - cast_helper(m_args[i], c_arg.m_value, true); + cast_helper(m_args[i], c_arg.m_value, true); } } else { cast_helper(m_args[i], c_arg.m_value, true); @@ -841,11 +843,11 @@ class CommonVisitor : public AST::BaseVisitor { if ( ASR::is_a(*der_sym) ) { type = ASRUtils::TYPE(ASRUtils::make_StructType_t_util(al, loc, s)); type = ASRUtils::make_Array_t_util(al, loc, type, dims.p, dims.size(), abi, is_argument); - } else if( ASR::is_a(*der_sym) ) { - type = ASRUtils::TYPE(ASR::make_Enum_t(al, loc, s)); + } else if( ASR::is_a(*der_sym) ) { + type = ASRUtils::TYPE(ASR::make_EnumType_t(al, loc, s)); type = ASRUtils::make_Array_t_util(al, loc, type, dims.p, dims.size(), abi, is_argument); - } else if( ASR::is_a(*der_sym) ) { - type = ASRUtils::TYPE(ASR::make_Union_t(al, loc, s)); + } else if( ASR::is_a(*der_sym) ) { + type = ASRUtils::TYPE(ASR::make_UnionType_t(al, loc, s)); type = ASRUtils::make_Array_t_util(al, loc, type, dims.p, dims.size(), abi, is_argument); } } @@ -887,7 +889,7 @@ class CommonVisitor : public AST::BaseVisitor { type = ASRUtils::TYPE(ASR::make_Complex_t(al, loc, 8)); type = ASRUtils::make_Array_t_util(al, loc, type, dims.p, dims.size(), abi, is_argument); } else if (var_annotation == "str") { - type = ASRUtils::TYPE(ASR::make_Character_t(al, loc, 1, -2, nullptr)); + type = ASRUtils::TYPE(ASR::make_String_t(al, loc, 1, -2, nullptr, ASR::string_physical_typeType::PointerString)); type = ASRUtils::make_Array_t_util(al, loc, type, dims.p, dims.size(), abi, is_argument); } else if (var_annotation == "bool" || var_annotation == "i1") { type = ASRUtils::TYPE(ASR::make_Logical_t(al, loc, 4)); @@ -963,7 +965,7 @@ class CommonVisitor : public AST::BaseVisitor { return ASR::down_cast(fn); } else if (ASR::is_a(*t)) { ASR::Struct_t *st = ASR::down_cast(t); - // `st` is the Struct in a module. Now we construct + // `st` is the StructType in a module. Now we construct // an ExternalSymbol that points to it. Str name; name.from_str(al, new_sym_name); @@ -978,8 +980,8 @@ class CommonVisitor : public AST::BaseVisitor { ); current_module_dependencies.push_back(al, m->m_name); return ASR::down_cast(est); - } else if (ASR::is_a(*t)) { - ASR::EnumType_t *et = ASR::down_cast(t); + } else if (ASR::is_a(*t)) { + ASR::Enum_t *et = ASR::down_cast(t); Str name; name.from_str(al, new_sym_name); char *cname = name.c_str(al); @@ -993,8 +995,8 @@ class CommonVisitor : public AST::BaseVisitor { ); current_module_dependencies.push_back(al, m->m_name); return ASR::down_cast(est); - } else if (ASR::is_a(*t)) { - ASR::UnionType_t *ut = ASR::down_cast(t); + } else if (ASR::is_a(*t)) { + ASR::Union_t *ut = ASR::down_cast(t); Str name; name.from_str(al, new_sym_name); char *cname = name.c_str(al); @@ -1057,7 +1059,7 @@ class CommonVisitor : public AST::BaseVisitor { return import_from_module(al, mt, current_scope, std::string(mt->m_name), cur_sym_name, new_sym_name, loc); } else { - throw SemanticError("Only Subroutines, Functions, Struct, Variables and " + throw SemanticError("Only Subroutines, Functions, StructType, Variables and " "ExternalSymbol are currently supported in 'import'", loc); } LCOMPILERS_ASSERT(false); @@ -1077,7 +1079,7 @@ class CommonVisitor : public AST::BaseVisitor { variable_dependencies_vec.size(), ASR::intentType::Local, nullptr, nullptr, ASR::storage_typeType::Default, type, nullptr, ASR::abiType::Source, ASR::accessType::Public, - ASR::presenceType::Required, false); + ASR::presenceType::Required, false, false); ASR::symbol_t* variable_sym = ASR::down_cast(variable_asr); current_scope->add_symbol(dummy_ret_name, variable_sym); ASR::expr_t* variable_var = ASRUtils::EXPR(ASR::make_Var_t(al, expr->base.loc, variable_sym)); @@ -1309,7 +1311,7 @@ class CommonVisitor : public AST::BaseVisitor { } if ( args.size() > 0 && args.size() > st->n_members ) { - throw SemanticError("StructConstructor has more arguments than the number of struct members", + throw SemanticError("StructTypeConstructor has more arguments than the number of struct members", loc); } @@ -1340,11 +1342,11 @@ class CommonVisitor : public AST::BaseVisitor { } ASR::ttype_t* der_type = ASRUtils::TYPE(ASRUtils::make_StructType_t_util(al, loc, stemp)); return ASR::make_StructConstructor_t(al, loc, stemp, args.p, args.size(), der_type, nullptr); - } else if( ASR::is_a(*s) ) { + } else if( ASR::is_a(*s) ) { Vec args_new; args_new.reserve(al, args.size()); ASRUtils::visit_expr_list(al, args, args_new); - ASR::EnumType_t* enumtype = ASR::down_cast(s); + ASR::Enum_t* enumtype = ASR::down_cast(s); for( size_t i = 0; i < std::min(args.size(), enumtype->n_members); i++ ) { std::string member_name = enumtype->m_members[i]; ASR::Variable_t* member_var = ASR::down_cast( @@ -1353,15 +1355,15 @@ class CommonVisitor : public AST::BaseVisitor { cast_helper(member_var->m_type, arg_new_i, arg_new_i->base.loc); args_new.p[i] = arg_new_i; } - ASR::ttype_t* der_type = ASRUtils::TYPE(ASR::make_Enum_t(al, loc, s)); - return ASR::make_EnumTypeConstructor_t(al, loc, stemp, args_new.p, args_new.size(), der_type, nullptr); - } else if( ASR::is_a(*s) ) { + ASR::ttype_t* der_type = ASRUtils::TYPE(ASR::make_EnumType_t(al, loc, s)); + return ASR::make_EnumConstructor_t(al, loc, stemp, args_new.p, args_new.size(), der_type, nullptr); + } else if( ASR::is_a(*s) ) { if( args.size() != 0 ) { throw SemanticError("Union constructors do not accept any argument as of now.", loc); } - ASR::ttype_t* union_ = ASRUtils::TYPE(ASR::make_Union_t(al, loc, stemp)); - return ASR::make_UnionTypeConstructor_t(al, loc, stemp, nullptr, 0, union_, nullptr); + ASR::ttype_t* union_ = ASRUtils::TYPE(ASR::make_UnionType_t(al, loc, stemp)); + return ASR::make_UnionConstructor_t(al, loc, stemp, nullptr, 0, union_, nullptr); } else { throw SemanticError("Unsupported call type for " + call_name, loc); } @@ -1685,7 +1687,7 @@ class CommonVisitor : public AST::BaseVisitor { } else if ( AST::is_a(*annotation) ) { //self case in methods intent = ASRUtils::intent_inout; - return annotation; + return annotation; } return annotation; } @@ -1780,9 +1782,9 @@ class CommonVisitor : public AST::BaseVisitor { is_allocatable, is_const, raise_error, abi, is_argument); if (!is_hashable(type)) { diag.add(diag::Diagnostic( - "Unhashable type: '" + ASRUtils::type_to_str(type) + "'", + "Unhashable type: '" + ASRUtils::type_to_str_python(type) + "'", diag::Level::Error, diag::Stage::Semantic, { - diag::Label("Mutable type '" + ASRUtils::type_to_str(type) + diag::Label("Mutable type '" + ASRUtils::type_to_str_python(type) + "' cannot be stored in a set.", {s->m_slice->base.loc}) }) @@ -1826,9 +1828,9 @@ class CommonVisitor : public AST::BaseVisitor { is_allocatable, is_const, raise_error, abi, is_argument); if (!is_hashable(key_type)) { diag.add(diag::Diagnostic( - "Unhashable type: '" + ASRUtils::type_to_str(key_type) + "'", + "Unhashable type: '" + ASRUtils::type_to_str_python(key_type) + "'", diag::Level::Error, diag::Stage::Semantic, { - diag::Label("Mutable type '" + ASRUtils::type_to_str(key_type) + diag::Label("Mutable type '" + ASRUtils::type_to_str_python(key_type) + "' cannot become a key in dict. Hint: Use an immutable type for key.", {t->m_elts[0]->base.loc}) }) @@ -1942,16 +1944,16 @@ class CommonVisitor : public AST::BaseVisitor { s2c(al, struct_member_name), ASR::accessType::Public)); current_scope->add_symbol(import_name, import_struct_member); } - return ASRUtils::TYPE(ASR::make_Union_t(al, attr_annotation->base.base.loc, import_struct_member)); + return ASRUtils::TYPE(ASR::make_UnionType_t(al, attr_annotation->base.base.loc, import_struct_member)); } else if ( AST::is_a(annotation) ) { AST::ConstantStr_t *n = AST::down_cast(&annotation); ASR::symbol_t *sym = current_scope->resolve_symbol(n->m_value); if ( sym == nullptr || !ASR::is_a(*sym) ) { - throw SemanticError("Only Struct implemented for constant" - " str annotation", loc); + throw SemanticError("Only StructType implemented for constant" + " str annotation", loc); } - //TODO: Change the returned type from Class to Struct - return ASRUtils::TYPE(ASR::make_Class_t(al,loc,sym)); + //TODO: Change the returned type from Class to StructType + return ASRUtils::TYPE(ASR::make_ClassType_t(al,loc,sym)); } throw SemanticError("Only Name, Subscript, and Call supported for now in annotation of annotated assignment.", loc); @@ -2157,7 +2159,7 @@ class CommonVisitor : public AST::BaseVisitor { // string repeat int64_t left_int = 0, right_int = 0, dest_len = 0; if (right_is_int && ASRUtils::expr_value(right) != nullptr) { - ASR::Character_t *left_type2 = ASR::down_cast( + ASR::String_t *left_type2 = ASR::down_cast( ASRUtils::type_get_past_array(left_type)); LCOMPILERS_ASSERT(ASRUtils::extract_n_dims_from_ttype(left_type) == 0); right_int = ASR::down_cast( @@ -2165,10 +2167,10 @@ class CommonVisitor : public AST::BaseVisitor { dest_len = left_type2->m_len * right_int; if (dest_len < 0) dest_len = 0; dest_type = ASR::down_cast( - ASR::make_Character_t(al, loc, left_type2->m_kind, - dest_len, nullptr)); + ASR::make_String_t(al, loc, left_type2->m_kind, + dest_len, nullptr, ASR::string_physical_typeType::PointerString)); } else if (left_is_int && ASRUtils::expr_value(left) != nullptr) { - ASR::Character_t *right_type2 = ASR::down_cast( + ASR::String_t *right_type2 = ASR::down_cast( ASRUtils::type_get_past_array(right_type)); LCOMPILERS_ASSERT(ASRUtils::extract_n_dims_from_ttype(right_type) == 0); left_int = ASR::down_cast( @@ -2176,11 +2178,11 @@ class CommonVisitor : public AST::BaseVisitor { dest_len = right_type2->m_len * left_int; if (dest_len < 0) dest_len = 0; dest_type = ASR::down_cast( - ASR::make_Character_t(al, loc, right_type2->m_kind, - dest_len, nullptr)); + ASR::make_String_t(al, loc, right_type2->m_kind, + dest_len, nullptr, ASR::string_physical_typeType::PointerString)); } else { - dest_type = ASRUtils::TYPE(ASR::make_Character_t(al, - loc, 1, -1, nullptr)); + dest_type = ASRUtils::TYPE(ASR::make_String_t(al, + loc, 1, -1, nullptr, ASR::string_physical_typeType::PointerString)); } if (ASRUtils::expr_value(left) != nullptr && ASRUtils::expr_value(right) != nullptr) { @@ -2208,15 +2210,16 @@ class CommonVisitor : public AST::BaseVisitor { } else if (ASRUtils::is_character(*left_type) && ASRUtils::is_character(*right_type) && op == ASR::binopType::Add) { // string concat - ASR::Character_t *left_type2 = ASR::down_cast( + ASR::String_t *left_type2 = ASR::down_cast( ASRUtils::type_get_past_array(left_type)); - ASR::Character_t *right_type2 = ASR::down_cast( + ASR::String_t *right_type2 = ASR::down_cast( ASRUtils::type_get_past_array(right_type)); LCOMPILERS_ASSERT(ASRUtils::extract_n_dims_from_ttype(left_type) == 0); LCOMPILERS_ASSERT(ASRUtils::extract_n_dims_from_ttype(right_type) == 0); dest_type = ASR::down_cast( - ASR::make_Character_t(al, loc, left_type2->m_kind, - left_type2->m_len + right_type2->m_len, nullptr)); + ASR::make_String_t(al, loc, left_type2->m_kind, + left_type2->m_len + right_type2->m_len, nullptr, + ASR::string_physical_typeType::PointerString)); if (ASRUtils::expr_value(left) != nullptr && ASRUtils::expr_value(right) != nullptr) { char* left_value = ASR::down_cast( ASRUtils::expr_value(left))->m_s; @@ -2225,7 +2228,7 @@ class CommonVisitor : public AST::BaseVisitor { char* result; std::string result_s = std::string(left_value) + std::string(right_value); result = s2c(al, result_s); - LCOMPILERS_ASSERT((int64_t)strlen(result) == ASR::down_cast(dest_type)->m_len) + LCOMPILERS_ASSERT((int64_t)strlen(result) == ASR::down_cast(dest_type)->m_len) value = ASR::down_cast(ASR::make_StringConstant_t( al, loc, result, dest_type)); } @@ -2685,7 +2688,7 @@ class CommonVisitor : public AST::BaseVisitor { s_intent, nullptr, nullptr, storage_type, type, nullptr, current_procedure_abi_type, s_access, s_presence, - value_attr); + value_attr, false); ASR::symbol_t* v_sym = ASR::down_cast(v); current_scope->add_or_overwrite_symbol(var_name, v_sym); } @@ -2740,7 +2743,7 @@ class CommonVisitor : public AST::BaseVisitor { ASR::ttype_t* type = ASRUtils::make_Array_t_util(al, loc, ASRUtils::expr_type(lbs[0]), dims.p, dims.size(), ASR::abiType::Source, false, ASR::array_physical_typeType::PointerToDataArray, true); - return ASRUtils::EXPR(ASR::make_ArrayConstant_t(al, + return ASRUtils::EXPR(ASRUtils::make_ArrayConstructor_t_util(al, loc, lbs.p, lbs.size(), type, ASR::arraystorageType::RowMajor)); } @@ -2842,7 +2845,7 @@ class CommonVisitor : public AST::BaseVisitor { variable_dependencies_vec.size(), ASRUtils::intent_unspecified, nullptr, nullptr, ASR::storage_typeType::Default, fn_type->m_arg_types[i], nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, - false)); + false, false)); current_scope->add_symbol(arg_name, v); LCOMPILERS_ASSERT(v != nullptr) args.push_back(al, ASRUtils::EXPR(ASR::make_Var_t(al, x.m_args.m_args[i].loc, v))); @@ -3005,7 +3008,7 @@ class CommonVisitor : public AST::BaseVisitor { ASR::storage_typeType storage_type = ASR::storage_typeType::Default; create_add_variable_to_scope(var_name, type, - ann_assign.base.base.loc, abi, storage_type); + ann_assign.base.base.loc, abi, storage_type); ASR::symbol_t* var_sym = current_scope->resolve_symbol(var_name); ASR::call_arg_t c_arg; c_arg.loc = var_sym->base.loc; @@ -3016,12 +3019,12 @@ class CommonVisitor : public AST::BaseVisitor { if( ASR::is_a(*var_type) ) { aggregate_type_name = ASRUtils::symbol_name( ASR::down_cast(var_type)->m_derived_type); - } else if( ASR::is_a(*var_type) ) { + } else if( ASR::is_a(*var_type) ) { aggregate_type_name = ASRUtils::symbol_name( - ASR::down_cast(var_type)->m_enum_type); - } else if( ASR::is_a(*var_type) ) { + ASR::down_cast(var_type)->m_enum_type); + } else if( ASR::is_a(*var_type) ) { aggregate_type_name = ASRUtils::symbol_name( - ASR::down_cast(var_type)->m_union_type); + ASR::down_cast(var_type)->m_union_type); } if( aggregate_type_name && !current_scope->get_symbol(std::string(aggregate_type_name)) ) { @@ -3051,7 +3054,7 @@ class CommonVisitor : public AST::BaseVisitor { continue; } else if ( AST::is_a(*x.m_body[i]) ) { if ( !is_class_scope ) { - throw SemanticError("Struct member functions are not supported", x.m_body[i]->base.loc); + throw SemanticError("StructType member functions are not supported", x.m_body[i]->base.loc); } else { AST::FunctionDef_t *f = AST::down_cast(x.m_body[i]); @@ -3121,12 +3124,12 @@ class CommonVisitor : public AST::BaseVisitor { if( ASR::is_a(*var_type) ) { aggregate_type_name = ASRUtils::symbol_name( ASR::down_cast(var_type)->m_derived_type); - } else if( ASR::is_a(*var_type) ) { + } else if( ASR::is_a(*var_type) ) { aggregate_type_name = ASRUtils::symbol_name( - ASR::down_cast(var_type)->m_enum_type); - } else if( ASR::is_a(*var_type) ) { + ASR::down_cast(var_type)->m_enum_type); + } else if( ASR::is_a(*var_type) ) { aggregate_type_name = ASRUtils::symbol_name( - ASR::down_cast(var_type)->m_union_type); + ASR::down_cast(var_type)->m_union_type); } if( aggregate_type_name && !current_scope->get_symbol(std::string(aggregate_type_name)) ) { @@ -3236,7 +3239,7 @@ class CommonVisitor : public AST::BaseVisitor { "values cannot interoperate with C code.", x.base.base.loc); } - ASR::symbol_t* enum_type = ASR::down_cast(ASR::make_EnumType_t(al, + ASR::symbol_t* enum_type = ASR::down_cast(ASR::make_Enum_t(al, x.base.base.loc, current_scope, x.m_name, struct_dependencies.p, struct_dependencies.size(), member_names.p, member_names.size(), @@ -3258,7 +3261,7 @@ class CommonVisitor : public AST::BaseVisitor { struct_dependencies.reserve(al, 1); visit_ClassMembers(x, member_names, member_fn_names, struct_dependencies, member_init); LCOMPILERS_ASSERT(member_init.size() == member_names.size()); - ASR::symbol_t* union_type = ASR::down_cast(ASR::make_UnionType_t(al, + ASR::symbol_t* union_type = ASR::down_cast(ASR::make_Union_t(al, x.base.base.loc, current_scope, x.m_name, struct_dependencies.p, struct_dependencies.size(), member_names.p, member_names.size(), @@ -3267,7 +3270,7 @@ class CommonVisitor : public AST::BaseVisitor { current_scope = parent_scope; if (current_scope->resolve_symbol(x_m_name)) { ASR::symbol_t* sym = current_scope->resolve_symbol(x_m_name); - ASR::UnionType_t *ut = ASR::down_cast(sym); + ASR::Union_t *ut = ASR::down_cast(sym); ut->m_initializers = member_init.p; ut->n_initializers = member_init.size(); } else { @@ -3390,7 +3393,7 @@ class CommonVisitor : public AST::BaseVisitor { } } - void init_self_type (const AST::FunctionDef_t &x, + void init_self_type (const AST::FunctionDef_t &x, ASR::symbol_t* class_sym, Location loc) { SymbolTable* parent_scope = current_scope; ASR::symbol_t *t = current_scope->get_symbol(x.m_name); @@ -3420,8 +3423,8 @@ class CommonVisitor : public AST::BaseVisitor { std::string var_name = "__name__"; std::string var_value = module_name; size_t s_size = var_value.size(); - ASR::ttype_t *type = ASRUtils::TYPE(ASR::make_Character_t(al, loc, - 1, s_size, nullptr)); + ASR::ttype_t *type = ASRUtils::TYPE(ASR::make_String_t(al, loc, + 1, s_size, nullptr, ASR::string_physical_typeType::PointerString)); ASR::expr_t *value = ASRUtils::EXPR(ASR::make_StringConstant_t(al, loc, s2c(al, var_value), type)); ASR::expr_t *init_expr = value; @@ -3440,7 +3443,7 @@ class CommonVisitor : public AST::BaseVisitor { s2c(al, var_name), variable_dependencies_vec.p, variable_dependencies_vec.size(), s_intent, init_expr, value, storage_type, type, nullptr, current_procedure_abi_type, - s_access, s_presence, value_attr); + s_access, s_presence, value_attr, false); current_scope->add_symbol(var_name, ASR::down_cast(v)); } @@ -3448,8 +3451,8 @@ class CommonVisitor : public AST::BaseVisitor { std::string var_name = "__LPYTHON_VERSION__"; std::string var_value = LFORTRAN_VERSION; size_t s_size = var_value.size(); - ASR::ttype_t *type = ASRUtils::TYPE(ASR::make_Character_t(al, loc, - 1, s_size, nullptr)); + ASR::ttype_t *type = ASRUtils::TYPE(ASR::make_String_t(al, loc, + 1, s_size, nullptr, ASR::string_physical_typeType::PointerString)); ASR::expr_t *value = ASRUtils::EXPR(ASR::make_StringConstant_t(al, loc, s2c(al, var_value), type)); ASR::expr_t *init_expr = value; @@ -3469,7 +3472,7 @@ class CommonVisitor : public AST::BaseVisitor { variable_dependencies_vec.size(), s_intent, init_expr, value, storage_type, type, nullptr, current_procedure_abi_type, s_access, s_presence, - value_attr); + value_attr, false); current_scope->add_symbol(var_name, ASR::down_cast(v)); } @@ -3563,8 +3566,8 @@ class CommonVisitor : public AST::BaseVisitor { void visit_ConstantStr(const AST::ConstantStr_t &x) { char *s = x.m_value; size_t s_size = std::string(s).size(); - ASR::ttype_t *type = ASRUtils::TYPE(ASR::make_Character_t(al, x.base.base.loc, - 1, s_size, nullptr)); + ASR::ttype_t *type = ASRUtils::TYPE(ASR::make_String_t(al, x.base.base.loc, + 1, s_size, nullptr, ASR::string_physical_typeType::PointerString)); tmp = ASR::make_StringConstant_t(al, x.base.base.loc, s, type); } @@ -3672,7 +3675,7 @@ class CommonVisitor : public AST::BaseVisitor { al, x.base.base.loc, result, dest_type)); break; } - case ASR::ttypeType::Character: { + case ASR::ttypeType::String: { char* left_value = ASR::down_cast( ASRUtils::expr_value(lhs))->m_s; char* right_value = ASR::down_cast( @@ -4074,7 +4077,7 @@ class CommonVisitor : public AST::BaseVisitor { if (ASR::is_a(*type)) { tmp = ASR::make_ListSection_t(al, loc, value, ai, type, nullptr); return false; - } else if (ASR::is_a(*type)) { + } else if (ASR::is_a(*type)) { tmp = ASR::make_StringSection_t(al, loc, value, ai.m_left, ai.m_right, ai.m_step, type, nullptr); return false; @@ -4373,7 +4376,7 @@ class SymbolTableVisitor : public CommonVisitor { variable_dependencies_vec.size(), ASRUtils::intent_unspecified, nullptr, nullptr, ASR::storage_typeType::Default, func->m_arg_types[i], nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, - false)); + false, false)); current_scope->add_symbol(arg_name, v); LCOMPILERS_ASSERT(v != nullptr) args.push_back(al, ASRUtils::EXPR(ASR::make_Var_t(al, loc, @@ -4392,7 +4395,7 @@ class SymbolTableVisitor : public CommonVisitor { variable_dependencies_vec.size(), ASRUtils::intent_return_var, nullptr, nullptr, ASR::storage_typeType::Default, func->m_return_var_type, nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, - false); + false, false); current_scope->add_symbol(return_var_name, ASR::down_cast(return_var)); to_return = ASRUtils::EXPR(ASR::make_Var_t(al, loc, ASR::down_cast(return_var))); @@ -4610,7 +4613,7 @@ class SymbolTableVisitor : public CommonVisitor { variable_dependencies_vec.size(), s_intent, init_expr, value, storage_type, arg_type, nullptr, current_procedure_abi_type, s_access, s_presence, - value_attr); + value_attr, false); v = ASR::down_cast(_tmp); } @@ -4654,7 +4657,7 @@ class SymbolTableVisitor : public CommonVisitor { current_scope, s2c(al, return_var_name), variable_dependencies_vec.p, variable_dependencies_vec.size(), ASRUtils::intent_return_var, nullptr, nullptr, storage_type, type, nullptr, current_procedure_abi_type, ASR::Public, - ASR::presenceType::Required, false); + ASR::presenceType::Required, false, false); LCOMPILERS_ASSERT(current_scope->get_scope().find(return_var_name) == current_scope->get_scope().end()) current_scope->add_symbol(return_var_name, ASR::down_cast(return_var)); @@ -4982,7 +4985,7 @@ class SymbolTableVisitor : public CommonVisitor { ASR::asr_t *v = ASR::make_Variable_t(al, x.base.base.loc, current_scope, s2c(al, tvar_name), variable_dependencies_vec.p, variable_dependencies_vec.size(), s_intent, init_expr, value, storage_type, type, nullptr, current_procedure_abi_type, - s_access, s_presence, value_attr); + s_access, s_presence, value_attr, false); current_scope->add_symbol(tvar_name, ASR::down_cast(v)); tmp = nullptr; @@ -5207,28 +5210,28 @@ class BodyVisitor : public CommonVisitor { AST::stmt_t* assgn = AST::down_cast(assgn_ast); body.push_back(al, assgn); } - } else if (AST::is_a(*x.m_body[i]) && + } else if (AST::is_a(*x.m_body[i]) && AST::is_a(*(AST::down_cast(x.m_body[i])->m_value))) { AST::Call_t* c = AST::down_cast(AST::down_cast(x.m_body[i])->m_value); - - if ( !AST::is_a(*(c->m_func)) + + if ( !AST::is_a(*(c->m_func)) || !AST::is_a(*(AST::down_cast(c->m_func)->m_value)) ) { - body.push_back(al, x.m_body[i]); + body.push_back(al, x.m_body[i]); continue; } AST::Call_t* super_call = AST::down_cast(AST::down_cast(c->m_func)->m_value); std::string attr = AST::down_cast(c->m_func)->m_attr; - if ( AST::is_a(*(super_call->m_func)) && + if ( AST::is_a(*(super_call->m_func)) && std::string(AST::down_cast(super_call->m_func)->m_id)=="super" && attr == "__init__") { if (parent_sym == nullptr) { throw SemanticError("The class doesn't have a base class",loc); - } + } Vec args; args.reserve(al, 1); parse_args(*super_call,args); ASR::call_arg_t first_arg; - first_arg.loc = loc; + first_arg.loc = loc; ASR::symbol_t* self_sym = current_scope->get_symbol("self"); first_arg.m_value = ASRUtils::EXPR(ASR::make_Var_t(al,loc,self_sym)); ASR::ttype_t* target_type = ASRUtils::TYPE(ASRUtils::make_StructType_t_util(al,loc,parent_sym)); @@ -5241,7 +5244,7 @@ class BodyVisitor : public CommonVisitor { std::string call_name = "__init__"; ASR::symbol_t* call_sym = get_struct_member(parent_sym,call_name,loc); super_call_stmt = ASRUtils::STMT( - ASR::make_SubroutineCall_t(al, loc, call_sym, call_sym, args_w_first.p, + ASR::make_SubroutineCall_t(al, loc, call_sym, call_sym, args_w_first.p, args_w_first.size(), nullptr)); } } else { @@ -5377,7 +5380,7 @@ class BodyVisitor : public CommonVisitor { ASR::symbol_t* sym = current_scope->get_symbol(var_name); if ( sym && ASR::is_a(*sym) ) { ASR::Variable_t* var = ASR::down_cast(sym); - if ( ASR::is_a(*(var->m_type)) && + if ( ASR::is_a(*(var->m_type)) && !ASR::down_cast((var->m_type))->m_is_cstruct ) { if ( !ASR::is_a(*init_expr) ) { throw SemanticError("Only Class constructor is allowed in the object assignment for now", x.base.base.loc); @@ -5658,7 +5661,7 @@ class BodyVisitor : public CommonVisitor { std::string var_name = std::string(v->m_name); throw SemanticError("Assignment to loop variable `" + std::string(to_lower(var_name)) +"` is not allowed", target->base.loc); } - if ( ASR::is_a(*(v->m_type)) && + if ( ASR::is_a(*(v->m_type)) && !ASR::down_cast((v->m_type))->m_is_cstruct && !(tmp_value->type == ASR::exprType::StructConstructor) ) { ASR::Variable_t *v = ASR::down_cast(sym); @@ -5741,7 +5744,7 @@ class BodyVisitor : public CommonVisitor { variable_dependencies_vec.p, variable_dependencies_vec.size(), ASR::intentType::Local, nullptr, nullptr, storage_type, int_type, nullptr, ASR::abiType::Source, ASR::accessType::Public, - ASR::presenceType::Required, false + ASR::presenceType::Required, false, false ); current_scope->add_symbol(explicit_iter_name, ASR::down_cast(explicit_iter_variable)); @@ -5749,7 +5752,7 @@ class BodyVisitor : public CommonVisitor { // we are iterating the for in loop LCOMPILERS_ASSERT(loop_src_var_symbol != nullptr); auto loop_src_var = ASR::make_Var_t(al, loc, loop_src_var_symbol); - if (ASR::is_a(*loop_src_var_ttype)) { + if (ASR::is_a(*loop_src_var_ttype)) { return ASRUtils::EXPR(ASR::make_StringLen_t(al, loc, ASRUtils::EXPR(loop_src_var), int_type, nullptr)); @@ -5764,7 +5767,7 @@ class BodyVisitor : public CommonVisitor { } else { throw SemanticError("Only Strings, Lists, Sets and Tuples" "can be used with for in loop, not " + - ASRUtils::type_to_str(loop_src_var_ttype), loc); + ASRUtils::type_to_str_python(loop_src_var_ttype), loc); } return nullptr; } @@ -5947,7 +5950,8 @@ class BodyVisitor : public CommonVisitor { ASR::asr_t* tmp_assign_variable = ASR::make_Variable_t(al, sbt->base.base.loc, current_scope, s2c(al, tmp_assign_name), variable_dependencies_vec.p, variable_dependencies_vec.size(), ASR::intentType::Local, nullptr, nullptr, ASR::storage_typeType::Default, - loop_src_var_ttype, nullptr, ASR::abiType::Source, ASR::accessType::Public, ASR::presenceType::Required, false + loop_src_var_ttype, nullptr, ASR::abiType::Source, ASR::accessType::Public, + ASR::presenceType::Required, false, false ); ASR::symbol_t *tmp_assign_variable_sym = ASR::down_cast(tmp_assign_variable); current_scope->add_symbol(tmp_assign_name, tmp_assign_variable_sym); @@ -5984,7 +5988,8 @@ class BodyVisitor : public CommonVisitor { ASR::asr_t* tmp_assign_variable = ASR::make_Variable_t(al, target->base.loc, current_scope, s2c(al, tmp_assign_name), variable_dependencies_vec.p, variable_dependencies_vec.size(), ASR::intentType::Local, nullptr, nullptr, ASR::storage_typeType::Default, - loop_src_var_ttype, nullptr, ASR::abiType::Source, ASR::accessType::Public, ASR::presenceType::Required, false + loop_src_var_ttype, nullptr, ASR::abiType::Source, ASR::accessType::Public, + ASR::presenceType::Required, false, false ); ASR::symbol_t *tmp_assign_variable_sym = ASR::down_cast(tmp_assign_variable); current_scope->add_symbol(tmp_assign_name, tmp_assign_variable_sym); @@ -6091,8 +6096,11 @@ class BodyVisitor : public CommonVisitor { } } if (parallel) { - tmp = ASR::make_DoConcurrentLoop_t(al, x.base.base.loc, head, - body.p, body.size()); + Vec heads; + heads.reserve(al, 1); + tmp = ASR::make_DoConcurrentLoop_t( + al, x.base.base.loc, heads.p, heads.size(), + nullptr, 0, nullptr, 0, nullptr, 0, body.p, body.size()); } else { if (orelse.size() > 0) tmp = ASR::make_DoLoop_t(al, x.base.base.loc, nullptr, head, @@ -6225,19 +6233,20 @@ class BodyVisitor : public CommonVisitor { } tmp = ASR::make_StructInstanceMember_t(al, loc, e, member_sym, member_var_type, nullptr); - } else if(ASR::is_a(*type)) { + } else if(ASR::is_a(*type)) { if( std::string(attr_char) == "value" ) { - ASR::Enum_t* enum_ = ASR::down_cast(type); - ASR::EnumType_t* enum_type = ASR::down_cast(enum_->m_enum_type); + ASR::EnumType_t* enum_ = ASR::down_cast(type); + ASR::Enum_t* enum_type = ASR::down_cast(enum_->m_enum_type); tmp = ASR::make_EnumValue_t(al, loc, e, type, enum_type->m_type, nullptr); } else if( std::string(attr_char) == "name" ) { - ASR::ttype_t* char_type = ASRUtils::TYPE(ASR::make_Character_t(al, loc, 1, -2, nullptr)); + ASR::ttype_t* char_type = ASRUtils::TYPE(ASR::make_String_t( + al, loc, 1, -2, nullptr, ASR::string_physical_typeType::PointerString)); tmp = ASR::make_EnumName_t(al, loc, e, type, char_type, nullptr); } - } else if(ASR::is_a(*type)) { - ASR::Union_t* u = ASR::down_cast(type); + } else if(ASR::is_a(*type)) { + ASR::UnionType_t* u = ASR::down_cast(type); ASR::symbol_t* u_sym = ASRUtils::symbol_get_past_external(u->m_union_type); - ASR::UnionType_t* u_type = ASR::down_cast(u_sym); + ASR::Union_t* u_type = ASR::down_cast(u_sym); bool member_found = false; std::string member_name = attr_char; for( size_t i = 0; i < u_type->n_members && !member_found; i++ ) { @@ -6306,7 +6315,7 @@ class BodyVisitor : public CommonVisitor { throw SemanticError("'" + attr + "' is not implemented for Complex type", loc); } - } else if( ASR::is_a(*type)) { + } else if( ASR::is_a(*type)) { ASR::StructType_t* der = ASR::down_cast(type); ASR::symbol_t* der_sym = ASRUtils::symbol_get_past_external(der->m_derived_type); ASR::Struct_t* der_type = ASR::down_cast(der_sym); @@ -6363,8 +6372,8 @@ class BodyVisitor : public CommonVisitor { } tmp = ASR::make_StructInstanceMember_t(al, loc, val, member_sym, member_var_type, nullptr); - } else if( ASR::is_a(*type) ) { //TODO: Remove Class_t from here - ASR::Class_t* der = ASR::down_cast(type); + } else if( ASR::is_a(*type) ) { //TODO: Remove ClassType_t from here + ASR::ClassType_t* der = ASR::down_cast(type); ASR::symbol_t* der_sym = ASRUtils::symbol_get_past_external(der->m_class_type); ASR::Struct_t* der_type = ASR::down_cast(der_sym); bool member_found = false; @@ -6416,9 +6425,9 @@ class BodyVisitor : public CommonVisitor { } tmp = ASR::make_StructInstanceMember_t(al, loc, val, member_sym, member_var_type, nullptr); - } else if (ASR::is_a(*type)) { - ASR::Enum_t* enum_ = ASR::down_cast(type); - ASR::EnumType_t* enum_type = ASR::down_cast(enum_->m_enum_type); + } else if (ASR::is_a(*type)) { + ASR::EnumType_t* enum_ = ASR::down_cast(type); + ASR::Enum_t* enum_type = ASR::down_cast(enum_->m_enum_type); std::string attr_name = attr_char; if( attr_name != "value" && attr_name != "name" ) { throw SemanticError(attr_name + " property not yet supported with Enums. " @@ -6436,13 +6445,14 @@ class BodyVisitor : public CommonVisitor { if( attr_name == "value" ) { tmp = ASR::make_EnumValue_t(al, loc, t_mem, type, enum_type->m_type, nullptr); } else if( attr_name == "name" ) { - ASR::ttype_t* char_type = ASRUtils::TYPE(ASR::make_Character_t(al, loc, 1, -2, nullptr)); + ASR::ttype_t* char_type = ASRUtils::TYPE(ASR::make_String_t( + al, loc, 1, -2, nullptr, ASR::string_physical_typeType::PointerString)); tmp = ASR::make_EnumName_t(al, loc, t_mem, type, char_type, nullptr); } - } else if (ASR::is_a(*type)) { - ASR::Union_t* union_asr = ASR::down_cast(type); + } else if (ASR::is_a(*type)) { + ASR::UnionType_t* union_asr = ASR::down_cast(type); ASR::symbol_t* union_sym = ASRUtils::symbol_get_past_external(union_asr->m_union_type); - ASR::UnionType_t* union_type = ASR::down_cast(union_sym); + ASR::Union_t* union_type = ASR::down_cast(union_sym); bool member_found = false; std::string member_name = attr_char; for( size_t i = 0; i < union_type->n_members && !member_found; i++ ) { @@ -6495,8 +6505,8 @@ class BodyVisitor : public CommonVisitor { if (ASR::is_a(*t)) { ASR::Variable_t *var = ASR::down_cast(t); visit_AttributeUtil(var->m_type, x.m_attr, t, x.base.base.loc); - } else if (ASR::is_a(*t)) { - ASR::EnumType_t* enum_type = ASR::down_cast(t); + } else if (ASR::is_a(*t)) { + ASR::Enum_t* enum_type = ASR::down_cast(t); ASR::symbol_t* enum_member = enum_type->m_symtab->resolve_symbol(std::string(x.m_attr)); if( !enum_member ) { throw SemanticError(std::string(x.m_attr) + " not present in " + @@ -6508,7 +6518,7 @@ class BodyVisitor : public CommonVisitor { ASR::expr_t* enum_member_var = ASRUtils::EXPR(ASR::make_EnumStaticMember_t(al, x.base.base.loc, enum_type_var, enum_member, enum_type->m_type, ASRUtils::expr_value(enum_member_variable->m_symbolic_value))); - ASR::ttype_t* enum_t = ASRUtils::TYPE(ASR::make_Enum_t(al, x.base.base.loc, t)); + ASR::ttype_t* enum_t = ASRUtils::TYPE(ASR::make_EnumType_t(al, x.base.base.loc, t)); tmp = ASR::make_EnumValue_t(al, x.base.base.loc, enum_member_var, enum_t, enum_member_variable->m_type, ASRUtils::expr_value(enum_member_variable->m_symbolic_value)); @@ -6526,9 +6536,9 @@ class BodyVisitor : public CommonVisitor { tmp = ASR::make_StructStaticMember_t(al, x.base.base.loc, struct_type_var, struct_member, struct_member_variable->m_type, nullptr); - } else if( ASR::is_a(*struct_member) ) { + } else if( ASR::is_a(*struct_member) ) { ASR::expr_t* struct_type_var = ASRUtils::EXPR(ASR::make_Var_t(al, x.base.base.loc, org_sym)); - ASR::ttype_t* union_type = ASRUtils::TYPE(ASR::make_Union_t(al, x.base.base.loc, struct_member)); + ASR::ttype_t* union_type = ASRUtils::TYPE(ASR::make_UnionType_t(al, x.base.base.loc, struct_member)); tmp = ASR::make_StructStaticMember_t(al, x.base.base.loc, struct_type_var, struct_member, union_type, nullptr); } } else if (ASR::is_a(*t)) { @@ -6573,7 +6583,9 @@ class BodyVisitor : public CommonVisitor { ASR::Variable_t* enum_m_var = ASR::down_cast(enum_Var->m_m); char *s = enum_m_var->m_name; size_t s_size = std::string(s).size(); - enum_ref_type = ASRUtils::TYPE(ASR::make_Character_t(al, x.base.base.loc, 1, s_size, nullptr)); + enum_ref_type = ASRUtils::TYPE(ASR::make_String_t( + al, x.base.base.loc, 1, s_size, nullptr, + ASR::string_physical_typeType::PointerString)); enum_ref_value = ASRUtils::EXPR(ASR::make_StringConstant_t(al, x.base.base.loc, s, enum_ref_type)); } @@ -6629,9 +6641,9 @@ class BodyVisitor : public CommonVisitor { key_type = ASRUtils::expr_type(key); if (!is_hashable(key_type)) { diag.add(diag::Diagnostic( - "Unhashable type: '" + ASRUtils::type_to_str(key_type) + "'", + "Unhashable type: '" + ASRUtils::type_to_str_python(key_type) + "'", diag::Level::Error, diag::Stage::Semantic, { - diag::Label("Mutable type '" + ASRUtils::type_to_str(key_type) + diag::Label("Mutable type '" + ASRUtils::type_to_str_python(key_type) + "' cannot become a key in dict. Hint: Use an immutable type for key.", {key->base.loc}) }) @@ -6773,7 +6785,7 @@ class BodyVisitor : public CommonVisitor { ASR::make_Logical_t(al, x.base.base.loc, 4)); ASR::expr_t *value = nullptr; - if( ASR::is_a(*dest_type) ) { + if( ASR::is_a(*dest_type) ) { dest_type = ASRUtils::get_contained_type(dest_type); } @@ -7221,9 +7233,9 @@ class BodyVisitor : public CommonVisitor { type = ASRUtils::expr_type(value); if (!is_hashable(type)) { diag.add(diag::Diagnostic( - "Unhashable type: '" + ASRUtils::type_to_str(type) + "'", + "Unhashable type: '" + ASRUtils::type_to_str_python(type) + "'", diag::Level::Error, diag::Stage::Semantic, { - diag::Label("Mutable type '" + ASRUtils::type_to_str(type) + diag::Label("Mutable type '" + ASRUtils::type_to_str_python(type) + "' cannot be stored in a set.", {value->base.loc}) }) @@ -7682,8 +7694,8 @@ class BodyVisitor : public CommonVisitor { args.reserve(al, 1); ASR::call_arg_t str_arg; str_arg.loc = loc; - ASR::ttype_t *str_type = ASRUtils::TYPE(ASR::make_Character_t(al, loc, - 1, s_var.size(), nullptr)); + ASR::ttype_t *str_type = ASRUtils::TYPE(ASR::make_String_t(al, loc, + 1, s_var.size(), nullptr, ASR::string_physical_typeType::PointerString)); str_arg.m_value = ASRUtils::EXPR( ASR::make_StringConstant_t(al, loc, s2c(al, s_var), str_type)); ASR::call_arg_t sub_arg; @@ -7717,8 +7729,8 @@ class BodyVisitor : public CommonVisitor { args.reserve(al, 1); ASR::call_arg_t str_arg; str_arg.loc = loc; - ASR::ttype_t *str_type = ASRUtils::TYPE(ASR::make_Character_t(al, loc, - 1, s_var.size(), nullptr)); + ASR::ttype_t *str_type = ASRUtils::TYPE(ASR::make_String_t(al, loc, + 1, s_var.size(), nullptr, ASR::string_physical_typeType::PointerString)); str_arg.m_value = ASRUtils::EXPR( ASR::make_StringConstant_t(al, loc, s2c(al, s_var), str_type)); ASR::call_arg_t sub_arg; @@ -7804,8 +7816,8 @@ class BodyVisitor : public CommonVisitor { args.reserve(al, 1); ASR::call_arg_t str_arg; str_arg.loc = loc; - ASR::ttype_t *str_type = ASRUtils::TYPE(ASR::make_Character_t(al, loc, - 1, s_var.size(), nullptr)); + ASR::ttype_t *str_type = ASRUtils::TYPE(ASR::make_String_t(al, loc, + 1, s_var.size(), nullptr, ASR::string_physical_typeType::PointerString)); str_arg.m_value = ASRUtils::EXPR( ASR::make_StringConstant_t(al, loc, s2c(al, s_var), str_type)); ASR::call_arg_t sub_arg; @@ -7860,8 +7872,8 @@ class BodyVisitor : public CommonVisitor { args.reserve(al, 1); ASR::call_arg_t str_arg; str_arg.loc = loc; - ASR::ttype_t *str_type = ASRUtils::TYPE(ASR::make_Character_t(al, loc, - 1, s_var.size(), nullptr)); + ASR::ttype_t *str_type = ASRUtils::TYPE(ASR::make_String_t(al, loc, + 1, s_var.size(), nullptr, ASR::string_physical_typeType::PointerString)); str_arg.m_value = ASRUtils::EXPR( ASR::make_StringConstant_t(al, loc, s2c(al, s_var), str_type)); ASR::call_arg_t sub_arg; @@ -7887,8 +7899,8 @@ class BodyVisitor : public CommonVisitor { throw SemanticError("String to undergo partition cannot be empty", loc); } - ASR::ttype_t *char_type = ASRUtils::TYPE(ASR::make_Character_t(al, - loc, 1, s_var.size(), nullptr)); + ASR::ttype_t *char_type = ASRUtils::TYPE(ASR::make_String_t(al, + loc, 1, s_var.size(), nullptr, ASR::string_physical_typeType::PointerString)); ASR::expr_t *str = ASRUtils::EXPR(ASR::make_StringConstant_t(al, loc, s2c(al, s_var), char_type)); tmp = ASRUtils::Partition::create_partition(al, loc, args_, str, diag); @@ -8091,8 +8103,8 @@ we will have to use something else. throw SemanticError("'str' object has no attribute '" + attr_name + "'", loc); } - ASR::ttype_t *str_type = ASRUtils::TYPE(ASR::make_Character_t(al, loc, - 1, s_var.size(), nullptr)); + ASR::ttype_t *str_type = ASRUtils::TYPE(ASR::make_String_t(al, loc, + 1, s_var.size(), nullptr, ASR::string_physical_typeType::PointerString)); tmp = ASR::make_StringConstant_t(al, loc, s2c(al, s_var), str_type); } @@ -8139,8 +8151,8 @@ we will have to use something else. st = get_struct_member(st, call_name, loc); } else if ( ASR::is_a(*st)) { ASR::Variable_t* var = ASR::down_cast(st); - if (ASR::is_a(*var->m_type) || - ASR::is_a(*var->m_type) ) { + if (ASR::is_a(*var->m_type) || + ASR::is_a(*var->m_type) ) { //TODO: Correct Class and ClassType // call to struct member function // modifying args to pass the object as self @@ -8166,7 +8178,7 @@ we will have to use something else. } } else { throw SemanticError("Method not found in the class "+std::string(der->m_name)+ - " or it's parents",loc); + " or it's parents",loc); } tmp = make_call_helper(al, st, current_scope, new_args, call_name, loc); return; @@ -8180,7 +8192,7 @@ we will have to use something else. } ASR::expr_t *se = ASR::down_cast( ASR::make_Var_t(al, loc, st)); - if (ASR::is_a(*(ASRUtils::expr_type(se)))) { + if (ASR::is_a(*(ASRUtils::expr_type(se)))) { handle_string_attributes(se, args, at->m_attr, loc); return; } @@ -8452,7 +8464,14 @@ we will have to use something else. throw SemanticError("Function '" + call_name + "' does not accept vector values", x.base.base.loc); } + if( intrinsic_name == "int" ) { + args_.push_back(al, + make_ConstantWithKind(make_IntegerConstant_t, make_Integer_t, 8, 4, x.base.base.loc)); + } tmp = create_func(al, x.base.base.loc, args_, diag); + if( tmp == nullptr ) { + throw SemanticAbort(); + } return ; } else if (intrinsic_procedures.is_intrinsic(call_name)) { s = resolve_intrinsic_function(x.base.base.loc, call_name); @@ -8487,7 +8506,7 @@ we will have to use something else. separator = ASRUtils::EXPR(tmp); ASR::ttype_t *type = ASRUtils::expr_type(separator); if (!ASRUtils::is_character(*type)) { - std::string found = ASRUtils::type_to_str(type); + std::string found = ASRUtils::type_to_str_python(type); diag.add(diag::Diagnostic( "Separator is expected to be of string type", diag::Level::Error, diag::Stage::Semantic, { @@ -8503,7 +8522,7 @@ we will have to use something else. end = ASRUtils::EXPR(tmp); ASR::ttype_t *type = ASRUtils::expr_type(end); if (!ASRUtils::is_character(*type)) { - std::string found = ASRUtils::type_to_str(type); + std::string found = ASRUtils::type_to_str_python(type); diag.add(diag::Diagnostic( "End is expected to be of string type", diag::Level::Error, diag::Stage::Semantic, { @@ -8516,8 +8535,13 @@ we will have to use something else. } } } - tmp = ASR::make_Print_t(al, x.base.base.loc, - args_expr.p, args_expr.size(), separator, end); + ASR::ttype_t *type = ASRUtils::TYPE(ASR::make_String_t( + al, x.base.base.loc, -1, 0, nullptr, ASR::string_physical_typeType::PointerString)); + ASR::expr_t* string_format = ASRUtils::EXPR(ASRUtils::make_StringFormat_t_util(al, x.base.base.loc, + nullptr, args_expr.p, args_expr.size(), ASR::string_format_kindType::FormatPythonFormat, + type, nullptr)); + + tmp = ASR::make_Print_t(al, x.base.base.loc, string_format); return; } else if (call_name == "quit") { parse_args(x, args); @@ -8608,10 +8632,33 @@ we will have to use something else. alloc_args_vec.p, alloc_args_vec.size(), nullptr, nullptr, nullptr); } else { - Vec arr_args; - arr_args.reserve(al, 0); - tmp = ASRUtils::make_ArrayConstructor_t_util(al, x.base.base.loc, - arr_args.p, arr_args.size(), type, ASR::arraystorageType::RowMajor); + const Location& loc = x.base.base.loc; + ASR::ttype_t* el_type = ASRUtils::type_get_past_array( + ASRUtils::type_get_past_allocatable_pointer(type)); + if( !ASRUtils::is_struct(*el_type) ) { + ASR::expr_t* zero = ASRUtils::get_constant_zero_with_given_type(al, el_type); + LCOMPILERS_ASSERT(assign_asr_target) + ASRUtils::make_ArrayBroadcast_t_util(al, x.base.base.loc, assign_asr_target, zero, false); + tmp = &(zero->base); + } else { + ASR::expr_t* zero = ASRUtils::get_constant_zero_with_given_type(al, int32); + LCOMPILERS_ASSERT(assign_asr_target) + size_t rank = ASRUtils::extract_n_dims_from_ttype(type); + Vec array_index; array_index.reserve(al, rank); + for( size_t i = 0; i < rank; i++ ) { + ASR::array_index_t idx; + idx.loc = loc; + idx.m_left = nullptr; + idx.m_right = zero; + idx.m_step = nullptr; + array_index.push_back(al, idx); + } + ASR::expr_t* arrayitem = ASRUtils::EXPR(ASR::make_ArrayItem_t( + al, loc, assign_asr_target, array_index.p, array_index.size(), + el_type, ASR::arraystorageType::RowMajor, nullptr)); + ASRUtils::make_ArrayBroadcast_t_util(al, x.base.base.loc, assign_asr_target, arrayitem, false); + tmp = &(arrayitem->base); + } } return; } else if (call_name == "c_p_pointer") { @@ -8775,7 +8822,7 @@ we will have to use something else. tmp = ASRUtils::make_ArrayConstructor_t_util(al, x.base.base.loc, m_args, n_args, type, ASR::arraystorageType::RowMajor); } else { throw SemanticError("array accepts only list for now, got " + - ASRUtils::type_to_str(type) + " type.", x.base.base.loc); + ASRUtils::type_to_str_python(type) + " type.", x.base.base.loc); } return; } else if( call_name == "set" ) { @@ -8821,7 +8868,7 @@ we will have to use something else. ASR::Var_t* arg_Var = ASR::down_cast(arg); ASR::symbol_t* arg_Var_m_v = ASRUtils::symbol_get_past_external(arg_Var->m_v); if( ASR::is_a(*arg_Var_m_v) ) { - // TODO: Import the underlying struct if arg_type is of StructType type + // TODO: Import the underlying struct if arg_type is of Struct type // Ideally if a variable of struct type is being imported then its underlying type // should also be imported automatically. However, the naming of the // underlying struct type might lead to collisions, so importing the type diff --git a/src/lpython/semantics/python_ast_to_asr.h b/src/lpython/semantics/python_ast_to_asr.h index b53a2137b2..2afdfaaa2b 100644 --- a/src/lpython/semantics/python_ast_to_asr.h +++ b/src/lpython/semantics/python_ast_to_asr.h @@ -11,7 +11,7 @@ namespace LCompilers::LPython { bool main_module, std::string module_name, std::string file_path, bool allow_implicit_casting=false, size_t eval_count=0); int save_pyc_files(const ASR::TranslationUnit_t &u, - std::string infile); + std::string infile, LocationManager& lm); } // namespace LCompilers::LPython diff --git a/src/lpython/semantics/python_comptime_eval.h b/src/lpython/semantics/python_comptime_eval.h index 5f2d379275..fd1c3760a6 100644 --- a/src/lpython/semantics/python_comptime_eval.h +++ b/src/lpython/semantics/python_comptime_eval.h @@ -162,7 +162,7 @@ struct PythonIntrinsicProcedures { static ASR::expr_t *eval_str(Allocator &al, const Location &loc, Vec &args) { LCOMPILERS_ASSERT(ASRUtils::all_args_evaluated(args)); if (args.size() == 0) { // create an empty string - ASR::ttype_t* str_type = ASRUtils::TYPE(ASR::make_Character_t(al, loc, 1, 0, nullptr)); + ASR::ttype_t* str_type = ASRUtils::TYPE(ASR::make_String_t(al, loc, 1, 0, nullptr, ASR::string_physical_typeType::PointerString)); return ASR::down_cast(ASR::make_StringConstant_t(al, loc, s2c(al, ""), str_type)); } std::string s = ""; @@ -184,7 +184,7 @@ struct PythonIntrinsicProcedures { throw SemanticError("str() argument must be real, integer, logical, or a string, not '" + ASRUtils::type_to_str_python(arg_type) + "'", loc); } - ASR::ttype_t* str_type = ASRUtils::TYPE(ASR::make_Character_t(al, loc, 1, s.size(), nullptr)); + ASR::ttype_t* str_type = ASRUtils::TYPE(ASR::make_String_t(al, loc, 1, s.size(), nullptr, ASR::string_physical_typeType::PointerString)); return ASR::down_cast(ASR::make_StringConstant_t(al, loc, s2c(al, s), str_type)); } @@ -324,7 +324,7 @@ struct PythonIntrinsicProcedures { str += std::bitset<64>(std::abs(n)).to_string(); str.erase(0, str.find_first_not_of('0')); str.insert(0, prefix); - ASR::ttype_t* str_type = ASRUtils::TYPE(ASR::make_Character_t(al, loc, 1, str.size(), nullptr)); + ASR::ttype_t* str_type = ASRUtils::TYPE(ASR::make_String_t(al, loc, 1, str.size(), nullptr, ASR::string_physical_typeType::PointerString)); return ASR::down_cast(make_StringConstant_t(al, loc, s2c(al, str), str_type)); } else { throw SemanticError("bin() argument must be an integer, not '" + @@ -348,7 +348,7 @@ struct PythonIntrinsicProcedures { ss << std::hex << std::abs(n); str += ss.str(); str.insert(0, prefix); - ASR::ttype_t* str_type = ASRUtils::TYPE(ASR::make_Character_t(al, loc, 1, str.size(), nullptr)); + ASR::ttype_t* str_type = ASRUtils::TYPE(ASR::make_String_t(al, loc, 1, str.size(), nullptr, ASR::string_physical_typeType::PointerString)); return ASR::down_cast(make_StringConstant_t(al, loc, s2c(al, str), str_type)); } else { throw SemanticError("hex() argument must be an integer, not '" + @@ -372,7 +372,7 @@ struct PythonIntrinsicProcedures { ss << std::oct << std::abs(n); str += ss.str(); str.insert(0, prefix); - ASR::ttype_t* str_type = ASRUtils::TYPE(ASR::make_Character_t(al, loc, 1, str.size(), nullptr)); + ASR::ttype_t* str_type = ASRUtils::TYPE(ASR::make_String_t(al, loc, 1, str.size(), nullptr, ASR::string_physical_typeType::PointerString)); return ASR::down_cast(make_StringConstant_t(al, loc, s2c(al, str), str_type)); } else { throw SemanticError("oct() argument must be an integer, not '" + @@ -389,7 +389,7 @@ struct PythonIntrinsicProcedures { LCOMPILERS_ASSERT(args.size()==1); ASR::expr_t *arg = args[0]; ASR::ttype_t *type = ASRUtils::expr_type(arg); - ASR::ttype_t* str_type = ASRUtils::TYPE(ASR::make_Character_t(al, loc, 1, 1, nullptr)); + ASR::ttype_t* str_type = ASRUtils::TYPE(ASR::make_String_t(al, loc, 1, 1, nullptr, ASR::string_physical_typeType::PointerString)); if (ASRUtils::is_integer(*type) || ASRUtils::is_real(*type) || ASRUtils::is_complex(*type) || ASRUtils::is_logical(*type)) { throw SemanticError("Integer, Real, Complex and Boolean are not iterable " diff --git a/src/lpython/semantics/python_intrinsic_eval.h b/src/lpython/semantics/python_intrinsic_eval.h index 130652a4ac..220f27639d 100644 --- a/src/lpython/semantics/python_intrinsic_eval.h +++ b/src/lpython/semantics/python_intrinsic_eval.h @@ -72,7 +72,7 @@ struct IntrinsicNodeHandler { } else { throw SemanticError("'" + ASRUtils::type_to_str_python(type) + "' object cannot be interpreted as an integer", arg->base.loc); - } + } } arg = args[0].m_value; type = ASRUtils::expr_type(arg); @@ -102,14 +102,14 @@ struct IntrinsicNodeHandler { } } else { base = 10; - } + } } else { if (*ch == '0' && ((base == 16 && (ch[1] == 'x'|| ch[1] == 'X')) || (base == 8 && (ch[1] == 'o' || ch[1] == 'O')) || (base == 2 && (ch[1] == 'b' || ch[1] == 'B')))) { ch += 2; - } + } } while (*ch) { if (*ch == '.') { @@ -125,8 +125,8 @@ struct IntrinsicNodeHandler { loc, ival, to_type)); } return (ASR::asr_t *)ASR::down_cast(ASR::make_Cast_t( - al, loc, arg, ASR::cast_kindType::CharacterToInteger, - to_type, value)); + al, loc, arg, ASR::cast_kindType::StringToInteger, + to_type, value)); } else { if (args.size() == 2) { throw SemanticError("int() can't convert non-string with explicit base", loc); @@ -280,7 +280,7 @@ struct IntrinsicNodeHandler { loc, std::string(c) != "", to_type)); } return (ASR::asr_t *)ASR::down_cast(ASR::make_Cast_t( - al, loc, arg, ASR::cast_kindType::CharacterToLogical, to_type, value)); + al, loc, arg, ASR::cast_kindType::StringToLogical, to_type, value)); } else if (ASRUtils::is_complex(*type)) { if (ASRUtils::expr_value(arg) != nullptr) { @@ -323,9 +323,9 @@ struct IntrinsicNodeHandler { arg = args[0].m_value; arg_type = ASRUtils::expr_type(arg); } - ASR::ttype_t *str_type = ASRUtils::TYPE(ASR::make_Character_t(al, loc, 1, -2, nullptr)); + ASR::ttype_t *str_type = ASRUtils::TYPE(ASR::make_String_t(al, loc, 1, -2, nullptr, ASR::string_physical_typeType::PointerString)); if (!arg) { - ASR::ttype_t *res_type = ASRUtils::TYPE(ASR::make_Character_t(al, loc, 1, 0, nullptr)); + ASR::ttype_t *res_type = ASRUtils::TYPE(ASR::make_String_t(al, loc, 1, 0, nullptr, ASR::string_physical_typeType::PointerString)); return ASR::make_StringConstant_t(al, loc, s2c(al, ""), res_type); } if (ASRUtils::is_real(*arg_type)) { @@ -337,36 +337,36 @@ struct IntrinsicNodeHandler { sm << ival; std::string value_str = sm.str(); sm.clear(); - ASR::ttype_t *res_type = ASRUtils::TYPE(ASR::make_Character_t(al, loc, - 1, value_str.size(), nullptr)); + ASR::ttype_t *res_type = ASRUtils::TYPE(ASR::make_String_t(al, loc, + 1, value_str.size(), nullptr, ASR::string_physical_typeType::PointerString)); res_value = ASR::down_cast(ASR::make_StringConstant_t(al, loc, s2c(al, value_str), res_type)); } - return ASR::make_Cast_t(al, loc, arg, ASR::cast_kindType::RealToCharacter, + return ASR::make_Cast_t(al, loc, arg, ASR::cast_kindType::RealToString, str_type, res_value); } else if (ASRUtils::is_integer(*arg_type)) { if (ASRUtils::expr_value(arg) != nullptr) { int64_t number = ASR::down_cast( ASRUtils::expr_value(arg))->m_n; std::string value_str = std::to_string(number); - ASR::ttype_t *res_type = ASRUtils::TYPE(ASR::make_Character_t(al, loc, - 1, value_str.size(), nullptr)); + ASR::ttype_t *res_type = ASRUtils::TYPE(ASR::make_String_t(al, loc, + 1, value_str.size(), nullptr, ASR::string_physical_typeType::PointerString)); res_value = ASR::down_cast(ASR::make_StringConstant_t(al, loc, s2c(al, value_str), res_type)); } - return ASR::make_Cast_t(al, loc, arg, ASR::cast_kindType::IntegerToCharacter, + return ASR::make_Cast_t(al, loc, arg, ASR::cast_kindType::IntegerToString, str_type, res_value); } else if (ASRUtils::is_logical(*arg_type)) { if(ASRUtils::expr_value(arg) != nullptr) { bool bool_number = ASR::down_cast( ASRUtils::expr_value(arg))->m_value; std::string value_str = (bool_number)? "True" : "False"; - ASR::ttype_t *res_type = ASRUtils::TYPE(ASR::make_Character_t(al, loc, - 1, value_str.size(), nullptr)); + ASR::ttype_t *res_type = ASRUtils::TYPE(ASR::make_String_t(al, loc, + 1, value_str.size(), nullptr, ASR::string_physical_typeType::PointerString)); res_value = ASR::down_cast(ASR::make_StringConstant_t(al, loc, s2c(al, value_str), res_type)); } - return ASR::make_Cast_t(al, loc, arg, ASR::cast_kindType::LogicalToCharacter, + return ASR::make_Cast_t(al, loc, arg, ASR::cast_kindType::LogicalToString, str_type, res_value); } else if (ASRUtils::is_character(*arg_type)) { @@ -497,8 +497,8 @@ struct IntrinsicNodeHandler { } ASR::expr_t *arg = args[0].m_value; ASR::ttype_t *type = ASRUtils::expr_type(arg); - ASR::ttype_t* str_type = ASRUtils::TYPE(ASR::make_Character_t(al, - loc, 1, 1, nullptr)); + ASR::ttype_t* str_type = ASRUtils::TYPE(ASR::make_String_t(al, + loc, 1, 1, nullptr, ASR::string_physical_typeType::PointerString)); ASR::expr_t *value = nullptr; if (ASRUtils::is_integer(*type)) { if (ASRUtils::expr_value(arg) != nullptr) { diff --git a/src/runtime/lpython_builtin.py b/src/runtime/lpython_builtin.py index 6bb7920d5f..c46889df74 100644 --- a/src/runtime/lpython_builtin.py +++ b/src/runtime/lpython_builtin.py @@ -636,7 +636,7 @@ def _lpython_str_count(s: str, sub: str) -> i32: sub_len = len(sub) if sub_len == 0: - return s_len + 1 + return s_len + 1 count = 0 @@ -777,7 +777,7 @@ def _lpython_str_istitle(s: str) -> bool: word_start: bool = True # Flag to track the start of a word ch: str - only_whitespace: bool = True + only_whitespace: bool = True for ch in s: if ch.isalpha() and (ord('A') <= ord(ch) and ord(ch) <= ord('Z')): only_whitespace = False @@ -873,7 +873,7 @@ def _lpython_str_split(x: str) -> list[str]: start:i32 = 0 ind: i32 x_strip: str = _lpython_str_strip(x) - if (x_strip == ""): + if (x_strip == ""): return res while True: while (start < len(x_strip) and x_strip[start] == ' '): @@ -886,7 +886,7 @@ def _lpython_str_split(x: str) -> list[str]: res.append(x_strip[start:start + ind]) start += ind + len(sep) return res - + @overload def _lpython_str_split(x: str, sep:str) -> list[str]: if len(sep) == 0: @@ -907,7 +907,7 @@ def _lpython_str_split(x: str, sep:str) -> list[str]: @overload def _lpython_str_replace(x: str, old:str, new:str) -> str: return _lpython_str_replace(x, old, new, len(x)) - + @overload def _lpython_str_replace(x: str, old:str, new:str, count: i32) -> str: @@ -1045,7 +1045,7 @@ def _lpython_str_isspace(s: str) -> bool: # type 'WS', 'B' or 'S'; or the category 'Zs'. if len(s) == 0: return False - + ch: str for ch in s: if not (ch == " " or # SPACE @@ -1077,12 +1077,13 @@ def _lpython_str_isspace(s: str) -> bool: return True @overload -def _lpython_str_center(s: str, width: i32, fillchar: str) -> str: +def _lpython_str_center(s: str, width_: i32, fillchar: str) -> str: """ - Return centered in a string of length width. - Padding is done using the specified fillchar (default is an ASCII space). + Return centered in a string of length width. + Padding is done using the specified fillchar (default is an ASCII space). The original string is returned if width is less than or equal to len(s). """ + width: i32 = width_ if(len(fillchar) != 1): raise TypeError("The fill character must be exactly one character long") str_len: i32 = len(s) @@ -1091,7 +1092,7 @@ def _lpython_str_center(s: str, width: i32, fillchar: str) -> str: width -= str_len result: str = "" left_padding: i32 = i32(width/2) + _mod(width,2) - i: i32 + i: i32 for i in range(left_padding): result += fillchar right_padding: i32 = width - left_padding @@ -1107,7 +1108,7 @@ def _lpython_str_center(s: str, width: i32) -> str: @overload def _lpython_str_expandtabs(s: str, tabsize: i32) -> str: """ - Return a copy of the string where all tab characters are replaced + Return a copy of the string where all tab characters are replaced by one or more spaces, depending on the current column and the given tab size. """ if len(s) == 0: