Skip to content

Reallocate LHS for allocatable strings #192

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion grammar/ASR.asdl
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ abi -- External ABI
stmt
= Allocate(alloc_arg* args, expr? stat)
| Assign(int label, identifier variable)
| Assignment(expr target, expr value, stmt? overloaded)
| Assignment(expr target, expr value, stmt? overloaded, bool realloc_lhs)
| Associate(expr target, expr value)
| Cycle()
-- deallocates if allocated otherwise throws a runtime error
Expand Down
36 changes: 33 additions & 3 deletions src/libasr/codegen/asr_to_llvm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2440,12 +2440,13 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
target = builder->CreateLoad(llvm_utils->create_gep(ptr, idx));
}
if( arr_descr->is_array(target) ) {
if( asr_target->m_type->type ==
ASR::ttypeType::Character ) {
if( asr_target->m_type->type == ASR::ttypeType::Character ) {
target = arr_descr->get_pointer_to_data(target);
}
}
}

// Evaluate the RHS and save into `value`
this->visit_expr_wrapper(x.m_value, true);
value = tmp;
if ( is_a<ASR::Character_t>(*expr_type(x.m_value)) ) {
Expand All @@ -2456,7 +2457,36 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
}
}
}
builder->CreateStore(value, target);

bool allocatable_string = false;
if( x.m_target->type == ASR::exprType::ArrayRef ||
x.m_target->type == ASR::exprType::DerivedRef ) {
// pass
} else {
ASR::Variable_t *asr_target = EXPR2VAR(x.m_target);
if (!arr_descr->is_array(target)) {
if (ASR::is_a<ASR::Character_t>(*asr_target->m_type)) {
if (x.m_realloc_lhs) {
// This is an allocatable string
LFORTRAN_ASSERT(ASR::down_cast<ASR::Character_t>(asr_target->m_type)->m_len == -2)
allocatable_string = true;
}
}
}
}
if (allocatable_string) {
// RHS is an allocatable string

// TODO: We need to free the previously allocated memory (if not null)

// If the RHS contains a temporarily created string, we simply
// copy the pointer to it (now LHS owns it):
builder->CreateStore(value, target);
// TODO: otherwise we allocate the LHS to the right size
// and copy the string
} else {
builder->CreateStore(value, target);
}
auto finder = std::find(nested_globals.begin(),
nested_globals.end(), h);
if (finder != nested_globals.end()) {
Expand Down
8 changes: 4 additions & 4 deletions src/libasr/pass/arr_slice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -241,19 +241,19 @@ class ArrSliceVisitor : public PassUtils::PassVisitor<ArrSliceVisitor>
if( doloop == nullptr ) {
ASR::expr_t* target_ref = PassUtils::create_array_ref(slice_sym, idx_vars_target, al, x.base.base.loc, x.m_type);
ASR::expr_t* value_ref = PassUtils::create_array_ref(x.m_v, idx_vars_value, al, x.base.base.loc, x.m_type);
ASR::stmt_t* assign_stmt = LFortran::ASRUtils::STMT(ASR::make_Assignment_t(al, x.base.base.loc, target_ref, value_ref, nullptr));
ASR::stmt_t* assign_stmt = LFortran::ASRUtils::STMT(ASR::make_Assignment_t(al, x.base.base.loc, target_ref, value_ref, nullptr, false));
doloop_body.push_back(al, assign_stmt);
} else {
ASR::stmt_t* set_to_one = LFortran::ASRUtils::STMT(ASR::make_Assignment_t(al, x.base.base.loc, idx_vars_target[i+1], const_1, nullptr));
ASR::stmt_t* set_to_one = LFortran::ASRUtils::STMT(ASR::make_Assignment_t(al, x.base.base.loc, idx_vars_target[i+1], const_1, nullptr, false));
doloop_body.push_back(al, set_to_one);
doloop_body.push_back(al, doloop);
}
ASR::expr_t* inc_expr = LFortran::ASRUtils::EXPR(ASR::make_BinOp_t(al, x.base.base.loc, idx_vars_target[i], ASR::binopType::Add, const_1, int32_type, nullptr, nullptr));
ASR::stmt_t* assign_stmt = LFortran::ASRUtils::STMT(ASR::make_Assignment_t(al, x.base.base.loc, idx_vars_target[i], inc_expr, nullptr));
ASR::stmt_t* assign_stmt = LFortran::ASRUtils::STMT(ASR::make_Assignment_t(al, x.base.base.loc, idx_vars_target[i], inc_expr, nullptr, false));
doloop_body.push_back(al, assign_stmt);
doloop = LFortran::ASRUtils::STMT(ASR::make_DoLoop_t(al, x.base.base.loc, head, doloop_body.p, doloop_body.size()));
}
ASR::stmt_t* set_to_one = LFortran::ASRUtils::STMT(ASR::make_Assignment_t(al, x.base.base.loc, idx_vars_target[0], const_1, nullptr));
ASR::stmt_t* set_to_one = LFortran::ASRUtils::STMT(ASR::make_Assignment_t(al, x.base.base.loc, idx_vars_target[0], const_1, nullptr, false));
arr_slice_result.push_back(al, set_to_one);
arr_slice_result.push_back(al, doloop);
}
Expand Down
22 changes: 11 additions & 11 deletions src/libasr/pass/array_op.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ class ArrayOpVisitor : public PassUtils::PassVisitor<ArrayOpVisitor>
ASR::expr_t* ref = PassUtils::create_array_ref(tmp_val, idx_vars, al);
ASR::expr_t* res = PassUtils::create_array_ref(result_var, idx_vars, al);
ASR::expr_t* impl_cast_el_wise = LFortran::ASRUtils::EXPR(ASR::make_ImplicitCast_t(al, x.base.base.loc, ref, x.m_kind, x.m_type, nullptr));
ASR::stmt_t* assign = LFortran::ASRUtils::STMT(ASR::make_Assignment_t(al, x.base.base.loc, res, impl_cast_el_wise, nullptr));
ASR::stmt_t* assign = LFortran::ASRUtils::STMT(ASR::make_Assignment_t(al, x.base.base.loc, res, impl_cast_el_wise, nullptr, false));
doloop_body.push_back(al, assign);
} else {
doloop_body.push_back(al, doloop);
Expand Down Expand Up @@ -375,7 +375,7 @@ class ArrayOpVisitor : public PassUtils::PassVisitor<ArrayOpVisitor>
ref = tmp_val;
}
ASR::expr_t* res = PassUtils::create_array_ref(result_var, idx_vars, al);
ASR::stmt_t* assign = LFortran::ASRUtils::STMT(ASR::make_Assignment_t(al, x.base.base.loc, res, ref, nullptr));
ASR::stmt_t* assign = LFortran::ASRUtils::STMT(ASR::make_Assignment_t(al, x.base.base.loc, res, ref, nullptr, false));
doloop_body.push_back(al, assign);
} else {
doloop_body.push_back(al, doloop);
Expand Down Expand Up @@ -427,7 +427,7 @@ class ArrayOpVisitor : public PassUtils::PassVisitor<ArrayOpVisitor>
ASR::expr_t* op_el_wise = LFortran::ASRUtils::EXPR(ASR::make_UnaryOp_t(
al, x.base.base.loc,
x.m_op, ref, x.m_type, nullptr));
ASR::stmt_t* assign = LFortran::ASRUtils::STMT(ASR::make_Assignment_t(al, x.base.base.loc, res, op_el_wise, nullptr));
ASR::stmt_t* assign = LFortran::ASRUtils::STMT(ASR::make_Assignment_t(al, x.base.base.loc, res, op_el_wise, nullptr, false));
doloop_body.push_back(al, assign);
} else {
doloop_body.push_back(al, doloop);
Expand Down Expand Up @@ -516,21 +516,21 @@ class ArrayOpVisitor : public PassUtils::PassVisitor<ArrayOpVisitor>
default:
throw LFortranException("The desired operation is not supported yet for arrays.");
}
ASR::stmt_t* assign = LFortran::ASRUtils::STMT(ASR::make_Assignment_t(al, x.base.base.loc, res, op_el_wise, nullptr));
ASR::stmt_t* assign = LFortran::ASRUtils::STMT(ASR::make_Assignment_t(al, x.base.base.loc, res, op_el_wise, nullptr, false));
doloop_body.push_back(al, assign);
} else {
ASR::stmt_t* set_to_one = LFortran::ASRUtils::STMT(ASR::make_Assignment_t(al, x.base.base.loc, idx_vars_value[i+1], const_1, nullptr));
ASR::stmt_t* set_to_one = LFortran::ASRUtils::STMT(ASR::make_Assignment_t(al, x.base.base.loc, idx_vars_value[i+1], const_1, nullptr, false));
doloop_body.push_back(al, set_to_one);
doloop_body.push_back(al, doloop);
}
ASR::expr_t* inc_expr = LFortran::ASRUtils::EXPR(ASR::make_BinOp_t(al, x.base.base.loc, idx_vars_value[i],
ASR::binopType::Add, const_1, int32_type,
nullptr, nullptr));
ASR::stmt_t* assign_stmt = LFortran::ASRUtils::STMT(ASR::make_Assignment_t(al, x.base.base.loc, idx_vars_value[i], inc_expr, nullptr));
ASR::stmt_t* assign_stmt = LFortran::ASRUtils::STMT(ASR::make_Assignment_t(al, x.base.base.loc, idx_vars_value[i], inc_expr, nullptr, false));
doloop_body.push_back(al, assign_stmt);
doloop = LFortran::ASRUtils::STMT(ASR::make_DoLoop_t(al, x.base.base.loc, head, doloop_body.p, doloop_body.size()));
}
ASR::stmt_t* set_to_one = LFortran::ASRUtils::STMT(ASR::make_Assignment_t(al, x.base.base.loc, idx_vars_value[0], const_1, nullptr));
ASR::stmt_t* set_to_one = LFortran::ASRUtils::STMT(ASR::make_Assignment_t(al, x.base.base.loc, idx_vars_value[0], const_1, nullptr, false));
array_op_result.push_back(al, set_to_one);
array_op_result.push_back(al, doloop);
} else if( (rank_left == 0 && rank_right > 0) ||
Expand Down Expand Up @@ -599,19 +599,19 @@ class ArrayOpVisitor : public PassUtils::PassVisitor<ArrayOpVisitor>
default:
throw LFortranException("The desired operation is not supported yet for arrays.");
}
ASR::stmt_t* assign = LFortran::ASRUtils::STMT(ASR::make_Assignment_t(al, x.base.base.loc, res, op_el_wise, nullptr));
ASR::stmt_t* assign = LFortran::ASRUtils::STMT(ASR::make_Assignment_t(al, x.base.base.loc, res, op_el_wise, nullptr, false));
doloop_body.push_back(al, assign);
} else {
ASR::stmt_t* set_to_one = LFortran::ASRUtils::STMT(ASR::make_Assignment_t(al, x.base.base.loc, idx_vars_value[i+1], const_1, nullptr));
ASR::stmt_t* set_to_one = LFortran::ASRUtils::STMT(ASR::make_Assignment_t(al, x.base.base.loc, idx_vars_value[i+1], const_1, nullptr, false));
doloop_body.push_back(al, set_to_one);
doloop_body.push_back(al, doloop);
}
ASR::expr_t* inc_expr = LFortran::ASRUtils::EXPR(ASR::make_BinOp_t(al, x.base.base.loc, idx_vars_value[i], ASR::binopType::Add, const_1, int32_type, nullptr, nullptr));
ASR::stmt_t* assign_stmt = LFortran::ASRUtils::STMT(ASR::make_Assignment_t(al, x.base.base.loc, idx_vars_value[i], inc_expr, nullptr));
ASR::stmt_t* assign_stmt = LFortran::ASRUtils::STMT(ASR::make_Assignment_t(al, x.base.base.loc, idx_vars_value[i], inc_expr, nullptr, false));
doloop_body.push_back(al, assign_stmt);
doloop = LFortran::ASRUtils::STMT(ASR::make_DoLoop_t(al, x.base.base.loc, head, doloop_body.p, doloop_body.size()));
}
ASR::stmt_t* set_to_one = LFortran::ASRUtils::STMT(ASR::make_Assignment_t(al, x.base.base.loc, idx_vars_value[0], const_1, nullptr));
ASR::stmt_t* set_to_one = LFortran::ASRUtils::STMT(ASR::make_Assignment_t(al, x.base.base.loc, idx_vars_value[0], const_1, nullptr, false));
array_op_result.push_back(al, set_to_one);
array_op_result.push_back(al, doloop);
}
Expand Down
2 changes: 1 addition & 1 deletion src/libasr/pass/class_constructor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ class ClassConstructorVisitor : public PassUtils::PassVisitor<ClassConstructorVi
for( size_t i = 0; i < dt_dertype->n_members; i++ ) {
ASR::symbol_t* member = dt_dertype->m_symtab->resolve_symbol(std::string(dt_dertype->m_members[i], strlen(dt_dertype->m_members[i])));
ASR::expr_t* derived_ref = LFortran::ASRUtils::EXPR(ASRUtils::getDerivedRef_t(al, x.base.base.loc, (ASR::asr_t*)result_var, member, current_scope));
ASR::stmt_t* assign = LFortran::ASRUtils::STMT(ASR::make_Assignment_t(al, x.base.base.loc, derived_ref, x.m_args[i], nullptr));
ASR::stmt_t* assign = LFortran::ASRUtils::STMT(ASR::make_Assignment_t(al, x.base.base.loc, derived_ref, x.m_args[i], nullptr, false));
class_constructor_result.push_back(al, assign);
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/libasr/pass/do_loops.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ Vec<ASR::stmt_t*> replace_doloop(Allocator &al, const ASR::DoLoop_t &loop) {
ASR::ttype_t *type = LFortran::ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4, nullptr, 0));
ASR::stmt_t *stmt1 = LFortran::ASRUtils::STMT(ASR::make_Assignment_t(al, loc, target,
LFortran::ASRUtils::EXPR(ASR::make_BinOp_t(al, loc, a, ASR::binopType::Sub, c, type, nullptr, nullptr)),
nullptr));
nullptr, false));

ASR::expr_t *cond = LFortran::ASRUtils::EXPR(ASR::make_Compare_t(al, loc,
LFortran::ASRUtils::EXPR(ASR::make_BinOp_t(al, loc, target, ASR::binopType::Add, c, type, nullptr, nullptr)),
Expand All @@ -74,7 +74,7 @@ Vec<ASR::stmt_t*> replace_doloop(Allocator &al, const ASR::DoLoop_t &loop) {
body.reserve(al, loop.n_body+1);
body.push_back(al, LFortran::ASRUtils::STMT(ASR::make_Assignment_t(al, loc, target,
LFortran::ASRUtils::EXPR(ASR::make_BinOp_t(al, loc, target, ASR::binopType::Add, c, type, nullptr, nullptr)),
nullptr)));
nullptr, false)));
for (size_t i=0; i<loop.n_body; i++) {
body.push_back(al, loop.m_body[i]);
}
Expand Down
2 changes: 1 addition & 1 deletion src/libasr/pass/global_stmts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ void pass_wrap_global_stmts_into_function(Allocator &al,
} else {
throw LFortranException("Return type not supported in interactive mode");
}
ASR::stmt_t* asr_stmt = LFortran::ASRUtils::STMT(ASR::make_Assignment_t(al, loc, target, value, nullptr));
ASR::stmt_t* asr_stmt = LFortran::ASRUtils::STMT(ASR::make_Assignment_t(al, loc, target, value, nullptr, false));
body.push_back(al, asr_stmt);
} else if (unit.m_items[i]->type == ASR::asrType::stmt) {
ASR::stmt_t* asr_stmt = LFortran::ASRUtils::STMT(unit.m_items[i]);
Expand Down
12 changes: 6 additions & 6 deletions src/libasr/pass/implied_do_loops.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,11 +159,11 @@ class ImpliedDoLoopVisitor : public PassUtils::PassVisitor<ImpliedDoLoopVisitor>
if( idoloop->m_values[i]->type == ASR::exprType::ImpliedDoLoop ) {
throw LFortranException("Pass for nested ImpliedDoLoop nodes isn't implemented yet."); // idoloop->m_values[i]->base.loc
}
ASR::stmt_t* doloop_stmt = LFortran::ASRUtils::STMT(ASR::make_Assignment_t(al, arr_var->base.base.loc, array_ref, idoloop->m_values[i], nullptr));
ASR::stmt_t* doloop_stmt = LFortran::ASRUtils::STMT(ASR::make_Assignment_t(al, arr_var->base.base.loc, array_ref, idoloop->m_values[i], nullptr, false));
doloop_body.push_back(al, doloop_stmt);
if( arr_idx != nullptr ) {
ASR::expr_t* increment = LFortran::ASRUtils::EXPR(ASR::make_BinOp_t(al, arr_var->base.base.loc, arr_idx, ASR::binopType::Add, const_1, LFortran::ASRUtils::expr_type(arr_idx), nullptr, nullptr));
ASR::stmt_t* assign_stmt = LFortran::ASRUtils::STMT(ASR::make_Assignment_t(al, arr_var->base.base.loc, arr_idx, increment, nullptr));
ASR::stmt_t* assign_stmt = LFortran::ASRUtils::STMT(ASR::make_Assignment_t(al, arr_var->base.base.loc, arr_idx, increment, nullptr, false));
doloop_body.push_back(al, assign_stmt);
}
}
Expand Down Expand Up @@ -196,7 +196,7 @@ class ImpliedDoLoopVisitor : public PassUtils::PassVisitor<ImpliedDoLoopVisitor>
} else {
ASR::symbol_t* idx_sym = unit.m_global_scope->scope[std::string(idx_var_name)];
idx_var = LFortran::ASRUtils::EXPR(ASR::make_Var_t(al, x.base.base.loc, idx_sym));
ASR::stmt_t* assign_stmt = LFortran::ASRUtils::STMT(ASR::make_Assignment_t(al, arr_var->base.base.loc, idx_var, const_1, nullptr));
ASR::stmt_t* assign_stmt = LFortran::ASRUtils::STMT(ASR::make_Assignment_t(al, arr_var->base.base.loc, idx_var, const_1, nullptr, false));
implied_do_loop_result.push_back(al, assign_stmt);
}
for( size_t k = 0; k < arr_init->n_args; k++ ) {
Expand All @@ -216,10 +216,10 @@ class ImpliedDoLoopVisitor : public PassUtils::PassVisitor<ImpliedDoLoopVisitor>
ASR::expr_t* array_ref = LFortran::ASRUtils::EXPR(ASR::make_ArrayRef_t(al, arr_var->base.base.loc, arr_var->m_v,
args.p, args.size(),
LFortran::ASRUtils::expr_type(LFortran::ASRUtils::EXPR((ASR::asr_t*)arr_var)), nullptr));
ASR::stmt_t* assign_stmt = LFortran::ASRUtils::STMT(ASR::make_Assignment_t(al, arr_var->base.base.loc, array_ref, arr_init->m_args[k], nullptr));
ASR::stmt_t* assign_stmt = LFortran::ASRUtils::STMT(ASR::make_Assignment_t(al, arr_var->base.base.loc, array_ref, arr_init->m_args[k], nullptr, false));
implied_do_loop_result.push_back(al, assign_stmt);
ASR::expr_t* increment = LFortran::ASRUtils::EXPR(ASR::make_BinOp_t(al, arr_var->base.base.loc, idx_var, ASR::binopType::Add, const_1, LFortran::ASRUtils::expr_type(idx_var), nullptr, nullptr));
assign_stmt = LFortran::ASRUtils::STMT(ASR::make_Assignment_t(al, arr_var->base.base.loc, idx_var, increment, nullptr));
assign_stmt = LFortran::ASRUtils::STMT(ASR::make_Assignment_t(al, arr_var->base.base.loc, idx_var, increment, nullptr, false));
implied_do_loop_result.push_back(al, assign_stmt);
}
}
Expand Down Expand Up @@ -248,7 +248,7 @@ class ImpliedDoLoopVisitor : public PassUtils::PassVisitor<ImpliedDoLoopVisitor>
doloop_body.reserve(al, 1);
if( doloop == nullptr ) {
ASR::expr_t* ref = PassUtils::create_array_ref(x.m_target, idx_vars, al);
ASR::stmt_t* assign = LFortran::ASRUtils::STMT(ASR::make_Assignment_t(al, x.base.base.loc, ref, x.m_value, nullptr));
ASR::stmt_t* assign = LFortran::ASRUtils::STMT(ASR::make_Assignment_t(al, x.base.base.loc, ref, x.m_value, nullptr, false));
doloop_body.push_back(al, assign);
} else {
doloop_body.push_back(al, doloop);
Expand Down
2 changes: 1 addition & 1 deletion src/lpython/semantics/ast_body_visitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -794,7 +794,7 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
throw SemanticAbort();
}
tmp = ASR::make_Assignment_t(al, x.base.base.loc, target, value,
overloaded_stmt);
overloaded_stmt, false);
}

void visit_SubroutineCall(const AST::SubroutineCall_t &x) {
Expand Down
Loading