From 155ec90610f0b68b874ce3e29ab7d5da8a0e80be Mon Sep 17 00:00:00 2001 From: Gagandeep Singh Date: Wed, 27 Mar 2024 01:48:47 +0530 Subject: [PATCH] done --- src/libasr/ASR.asdl | 6 +-- src/libasr/asdl_cpp.py | 4 ++ src/libasr/asr_verify.cpp | 23 ++++++++- src/libasr/casting_utils.cpp | 15 ++++-- src/libasr/casting_utils.h | 2 +- src/libasr/codegen/llvm_array_utils.cpp | 2 +- src/libasr/compiler_tester/tester.py | 7 +-- src/libasr/pass/select_case.cpp | 69 ++++++++++++++++++++++++- src/libasr/utils.h | 2 + 9 files changed, 116 insertions(+), 14 deletions(-) diff --git a/src/libasr/ASR.asdl b/src/libasr/ASR.asdl index 5757c03d542..d31b2d95ddf 100644 --- a/src/libasr/ASR.asdl +++ b/src/libasr/ASR.asdl @@ -53,7 +53,7 @@ stmt | 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) | 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) + | 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) @@ -207,7 +207,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 +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 storage_type = Default | Save | Parameter access = Public | Private intent = Local | In | Out | InOut | ReturnVar | Unspecified @@ -222,7 +222,7 @@ call_arg = (expr? value) 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) -case_stmt = CaseStmt(expr* test, stmt* body) | CaseStmt_Range(expr? start, expr? end, stmt* body) +case_stmt = CaseStmt(expr* test, stmt* body, bool fall_through) | CaseStmt_Range(expr? start, expr? end, stmt* body) 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) diff --git a/src/libasr/asdl_cpp.py b/src/libasr/asdl_cpp.py index 135eca514f9..9463cb9d1fb 100644 --- a/src/libasr/asdl_cpp.py +++ b/src/libasr/asdl_cpp.py @@ -2738,6 +2738,10 @@ def main(argv): elif subs["MOD"] == "AST": subs["MOD"] = "LFortran::AST" subs["lcompiler"] = "lfortran" + elif subs["MOD"] == "LC": + subs["MOD"] = "LC::AST" + subs["mod"] = "ast" + subs["lcompiler"] = "lc" else: subs["lcompiler"] = "lfortran" is_asr = (mod.name.upper() == "ASR") diff --git a/src/libasr/asr_verify.cpp b/src/libasr/asr_verify.cpp index ab384700274..670d0a1f9eb 100644 --- a/src/libasr/asr_verify.cpp +++ b/src/libasr/asr_verify.cpp @@ -124,6 +124,20 @@ class VerifyVisitor : public BaseWalkVisitor current_symtab = nullptr; } + void visit_Select(const Select_t& x) { + bool fall_through = false; + for( size_t i = 0; i < x.n_body; i++ ) { + if( ASR::is_a(*x.m_body[i]) ) { + ASR::CaseStmt_t* case_stmt_t = ASR::down_cast(x.m_body[i]); + fall_through = fall_through || case_stmt_t->m_fall_through; + } + } + require(fall_through == x.m_enable_fall_through, + "Select_t::m_enable_fall_through should be " + + std::to_string(x.m_enable_fall_through)); + BaseWalkVisitor::visit_Select(x); + } + // -------------------------------------------------------- // symbol instances: @@ -698,6 +712,7 @@ class VerifyVisitor : public BaseWalkVisitor ASR::Module_t *m = ASRUtils::get_sym_module(x.m_external); ASR::StructType_t* sm = nullptr; ASR::EnumType_t* em = nullptr; + ASR::UnionType_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)); @@ -706,13 +721,17 @@ class VerifyVisitor : public BaseWalkVisitor 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)); 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); asr_owner_name = em->m_name; + } 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); asr_owner_name = fm->m_name; @@ -741,6 +760,8 @@ class VerifyVisitor : public BaseWalkVisitor s = em->m_symtab->resolve_symbol(std::string(x.m_original_name)); } else if( fm ) { s = fm->m_symtab->resolve_symbol(std::string(x.m_original_name)); + } else if( um ) { + s = um->m_symtab->resolve_symbol(std::string(x.m_original_name)); } require(s != nullptr, "ExternalSymbol::m_original_name ('" diff --git a/src/libasr/casting_utils.cpp b/src/libasr/casting_utils.cpp index 6b5d127fcaa..33537971e98 100644 --- a/src/libasr/casting_utils.cpp +++ b/src/libasr/casting_utils.cpp @@ -55,7 +55,7 @@ namespace LCompilers::CastingUtil { int get_src_dest(ASR::expr_t* left_expr, ASR::expr_t* right_expr, ASR::expr_t*& src_expr, ASR::expr_t*& dest_expr, ASR::ttype_t*& src_type, ASR::ttype_t*& dest_type, - bool is_assign) { + bool is_assign, bool allow_int_to_float) { ASR::ttype_t* left_type = ASRUtils::expr_type(left_expr); ASR::ttype_t* right_type = ASRUtils::expr_type(right_expr); if( ASR::is_a(*left_type) ) { @@ -71,7 +71,8 @@ namespace LCompilers::CastingUtil { return 2; } if( is_assign ) { - if( ASRUtils::is_real(*left_type) && ASRUtils::is_integer(*right_type)) { + if( ASRUtils::is_real(*left_type) && ASRUtils::is_integer(*right_type) && + !allow_int_to_float) { throw LCompilersException("Assigning integer to float is not supported"); } if ( ASRUtils::is_complex(*left_type) && !ASRUtils::is_complex(*right_type)) { @@ -139,7 +140,13 @@ namespace LCompilers::CastingUtil { return expr; } // TODO: Fix loc - return ASRUtils::EXPR(ASRUtils::make_Cast_t_value(al, loc, expr, - cast_kind, dest)); + if( ASRUtils::is_array(src) ) { + ASR::dimension_t* m_dims = nullptr; + size_t n_dims = ASRUtils::extract_dimensions_from_ttype(src, m_dims); + dest = ASRUtils::make_Array_t_util(al, loc, ASRUtils::extract_type(dest), m_dims, n_dims); + } else { + dest = ASRUtils::extract_type(dest); + } + return ASRUtils::EXPR(ASRUtils::make_Cast_t_value(al, loc, expr, cast_kind, dest)); } } diff --git a/src/libasr/casting_utils.h b/src/libasr/casting_utils.h index bdc80db6284..695e2951fb8 100644 --- a/src/libasr/casting_utils.h +++ b/src/libasr/casting_utils.h @@ -13,7 +13,7 @@ namespace LCompilers::CastingUtil { int get_src_dest(ASR::expr_t* left_expr, ASR::expr_t* right_expr, ASR::expr_t*& src_expr, ASR::expr_t*& dest_expr, ASR::ttype_t*& src_type, ASR::ttype_t*& dest_type, - bool is_assign); + bool is_assign, bool allow_int_to_float=false); ASR::expr_t* perform_casting(ASR::expr_t* expr, ASR::ttype_t* dest, Allocator& al, const Location& loc); diff --git a/src/libasr/codegen/llvm_array_utils.cpp b/src/libasr/codegen/llvm_array_utils.cpp index 8c54cdde718..a38415e125d 100644 --- a/src/libasr/codegen/llvm_array_utils.cpp +++ b/src/libasr/codegen/llvm_array_utils.cpp @@ -874,7 +874,7 @@ 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(dest, llvm::MaybeAlign(), src, llvm::MaybeAlign(), num_elements); + builder->CreateMemCpy(src, llvm::MaybeAlign(), dest, llvm::MaybeAlign(), num_elements); } } // LLVMArrUtils diff --git a/src/libasr/compiler_tester/tester.py b/src/libasr/compiler_tester/tester.py index 433633a662f..bd6d7e62e5a 100644 --- a/src/libasr/compiler_tester/tester.py +++ b/src/libasr/compiler_tester/tester.py @@ -362,7 +362,7 @@ def run_test(testname, basename, cmd, infile, update_reference=False, log.debug(s + " " + check()) -def tester_main(compiler, single_test): +def tester_main(compiler, single_test, is_lcompilers_executable_installed=False): parser = argparse.ArgumentParser(description=f"{compiler} Test Suite") parser.add_argument("-u", "--update", action="store_true", help="update all reference results") @@ -416,8 +416,9 @@ def tester_main(compiler, single_test): no_color = args.no_color # So that the tests find the `lcompiler` executable - os.environ["PATH"] = os.path.join(SRC_DIR, "bin") \ - + os.pathsep + os.environ["PATH"] + if not is_lcompilers_executable_installed: + 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"))) filtered_tests = test_data["test"] if specific_tests: diff --git a/src/libasr/pass/select_case.cpp b/src/libasr/pass/select_case.cpp index d5cd5e0b06b..effcd06f06d 100644 --- a/src/libasr/pass/select_case.cpp +++ b/src/libasr/pass/select_case.cpp @@ -150,6 +150,69 @@ Vec replace_selectcase(Allocator &al, const ASR::Select_t &select_ return body; } +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( + 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, + ASR::accessType::Public, ASR::presenceType::Required, false)); + scope->add_symbol(scope->get_unique_name("case_found"), case_found_sym); + ASR::expr_t* true_asr = ASRUtils::EXPR(ASR::make_LogicalConstant_t(al, loc, true, + ASRUtils::TYPE(ASR::make_Logical_t(al, loc, 4)))); + ASR::expr_t* false_asr = ASRUtils::EXPR(ASR::make_LogicalConstant_t(al, loc, false, + ASRUtils::TYPE(ASR::make_Logical_t(al, loc, 4)))); + ASR::expr_t* case_found = ASRUtils::EXPR(ASR::make_Var_t(al, loc, case_found_sym)); + body.push_back(al, ASRUtils::STMT(ASR::make_Assignment_t(al, loc, case_found, false_asr, nullptr))); + int label_id = ASRUtils::LabelGenerator::get_instance()->get_unique_label(); + for( int idx = 0; idx < x.n_body; idx++ ) { + ASR::case_stmt_t* case_body = x.m_body[idx]; + switch(case_body->type) { + case ASR::case_stmtType::CaseStmt: { + ASR::CaseStmt_t* Case_Stmt = ASR::down_cast(case_body); + ASR::expr_t* test_expr = gen_test_expr_CaseStmt(al, loc, Case_Stmt, a_test); + test_expr = ASRUtils::EXPR(ASR::make_LogicalBinOp_t(al, loc, test_expr, + ASR::logicalbinopType::Or, case_found, ASRUtils::expr_type(case_found), nullptr)); + Vec case_body; case_body.reserve(al, Case_Stmt->n_body); + case_body.from_pointer_n(Case_Stmt->m_body, Case_Stmt->n_body); + case_body.push_back(al, ASRUtils::STMT(ASR::make_Assignment_t( + al, loc, case_found, true_asr, nullptr))); + if( !Case_Stmt->m_fall_through ) { + case_body.push_back(al, ASRUtils::STMT(ASR::make_GoTo_t(al, loc, + label_id, s2c(al, scope->get_unique_name("switch_case_label"))))); + } + body.push_back(al, ASRUtils::STMT(ASR::make_If_t(al, loc, + test_expr, case_body.p, case_body.size(), nullptr, 0))); + break; + } + case ASR::case_stmtType::CaseStmt_Range: { + LCOMPILERS_ASSERT(false); + break; + } + } + } + for( int id = 0; id < x.n_default; id++ ) { + body.push_back(al, x.m_default[id]); + } + SymbolTable* block_symbol_table = al.make_new(scope); + ASR::symbol_t* empty_block = ASR::down_cast(ASR::make_Block_t( + al, loc, block_symbol_table, s2c(al, scope->get_unique_name("switch_case_label")), + nullptr, 0)); + scope->add_symbol(scope->get_unique_name("switch_case_label"), empty_block); + body.push_back(al, ASRUtils::STMT(ASR::make_BlockCall_t(al, loc, label_id, empty_block))); +} + +Vec replace_selectcase_with_fall_through( + Allocator &al, const ASR::Select_t &select_case, + SymbolTable* scope) { + ASR::expr_t *a = select_case.m_test; + Vec body; + case_to_if_with_fall_through(al, select_case, a, body, scope); + return body; +} + class SelectCaseVisitor : public PassUtils::PassVisitor { @@ -165,7 +228,11 @@ class SelectCaseVisitor : public PassUtils::PassVisitor } void visit_Select(const ASR::Select_t &x) { - pass_result = replace_selectcase(al, x); + if( x.m_enable_fall_through ) { + pass_result = replace_selectcase_with_fall_through(al, x, current_scope); + } else { + pass_result = replace_selectcase(al, x); + } } }; diff --git a/src/libasr/utils.h b/src/libasr/utils.h index 8fd22b4ad01..4a511279879 100644 --- a/src/libasr/utils.h +++ b/src/libasr/utils.h @@ -61,6 +61,8 @@ struct PassOptions { }; struct CompilerOptions { + std::vector runtime_linker_paths; + // TODO: Convert to std::filesystem::path (also change find_and_load_module()) PassOptions po;