Skip to content

Commit

Permalink
Merge pull request #1629 from czgdp1807/var_init
Browse files Browse the repository at this point in the history
Fix double initialisation of variables in ASR
  • Loading branch information
czgdp1807 committed Mar 27, 2023
2 parents 57699a9 + 095494a commit 6ebd4b8
Show file tree
Hide file tree
Showing 75 changed files with 333 additions and 130 deletions.
1 change: 1 addition & 0 deletions integration_tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ RUN(NAME array_02_decl LABELS cpython llvm c)
RUN(NAME array_03_decl LABELS cpython llvm c)
RUN(NAME variable_decl_01 LABELS cpython llvm c)
RUN(NAME variable_decl_02 LABELS cpython llvm c)
RUN(NAME variable_decl_03 LABELS cpython llvm c)
RUN(NAME array_expr_01 LABELS cpython llvm c)
RUN(NAME array_expr_02 LABELS cpython llvm c)
RUN(NAME array_01 LABELS cpython llvm wasm c)
Expand Down
2 changes: 1 addition & 1 deletion integration_tests/nrp/nr.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from ltypes import i32, f64
from lpython import i32, f64


def func(x: f64, c: f64) -> f64:
Expand Down
4 changes: 2 additions & 2 deletions integration_tests/test_global_decl.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from lpython import i32
from lpython import i32, Const
from numpy import empty, int32

# issue-1368

SIZE: i32 = i32(3)
SIZE: Const[i32] = i32(3)

def main() -> None:
xs: i32[SIZE] = empty(SIZE, dtype=int32)
Expand Down
2 changes: 1 addition & 1 deletion integration_tests/test_package_01.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from nrp import newton_raphson
from ltypes import f64, i32
from lpython import f64, i32


def check():
Expand Down
4 changes: 2 additions & 2 deletions integration_tests/variable_decl_01.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from lpython import i32, i64
from lpython import i32, i64, Const
from numpy import empty, int64

def f(n: i32, m: i32):
l: i32 = 2
l: Const[i32] = 2
a: i64[n, m, l] = empty((n, m, l), dtype=int64)
i: i32; j: i32; k: i32;
for i in range(n):
Expand Down
11 changes: 11 additions & 0 deletions integration_tests/variable_decl_03.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from lpython import f64

def f() -> f64:
return 5.5

def main():
t1: f64 = f() * 1e6
print(t1)
assert abs(t1 - 5.5 * 1e6) <= 1e-6

main()
4 changes: 4 additions & 0 deletions src/libasr/asdl_cpp.py
Original file line number Diff line number Diff line change
Expand Up @@ -2419,6 +2419,10 @@ def make_visitor(self, name, fields):
LCOMPILERS_ASSERT(!ASR::is_a<ASR::ExternalSymbol_t>(*e->m_external));
s = e->m_external;
}
if( ASR::down_cast<ASR::Variable_t>(s)->m_storage !=
ASR::storage_typeType::Parameter ) {
return nullptr;
}
return ASR::down_cast<ASR::Variable_t>(s)->m_value;
}""" \
% (name, name), 2, new_line=False)
Expand Down
4 changes: 2 additions & 2 deletions src/libasr/asr_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -963,8 +963,8 @@ ASR::asr_t* make_Cast_t_value(Allocator &al, const Location &a_loc,
double_value, 0, a_type));
} else if (a_kind == ASR::cast_kindType::IntegerToReal) {
// TODO: Clashes with the pow functions
// int64_t value = ASR::down_cast<ASR::ConstantInteger_t>(ASRUtils::expr_value(a_arg))->m_n;
// value = ASR::down_cast<ASR::expr_t>(ASR::make_ConstantReal_t(al, a_loc, (double)v, a_type));
int64_t int_value = ASR::down_cast<ASR::IntegerConstant_t>(ASRUtils::expr_value(a_arg))->m_n;
value = ASR::down_cast<ASR::expr_t>(ASR::make_RealConstant_t(al, a_loc, (double)int_value, a_type));
} else if (a_kind == ASR::cast_kindType::IntegerToComplex) {
int64_t int_value = ASR::down_cast<ASR::IntegerConstant_t>(
ASRUtils::expr_value(a_arg))->m_n;
Expand Down
29 changes: 29 additions & 0 deletions src/libasr/asr_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,35 @@ static inline bool is_value_constant(ASR::expr_t *a_value) {
// OK
} else if (ASR::is_a<ASR::StringConstant_t>(*a_value)) {
// OK
} else if(ASR::is_a<ASR::ArrayConstant_t>(*a_value)) {
// OK
// TODO: Check for each value of array constant
// and make sure each one is a constant.
} else if(ASR::is_a<ASR::ImpliedDoLoop_t>(*a_value)) {
// OK
} else if(ASR::is_a<ASR::Cast_t>(*a_value)) {
ASR::Cast_t* cast_t = ASR::down_cast<ASR::Cast_t>(a_value);
return is_value_constant(cast_t->m_arg);
} else if(ASR::is_a<ASR::PointerNullConstant_t>(*a_value)) {
// OK
} else if(ASR::is_a<ASR::ArrayReshape_t>(*a_value)) {
ASR::ArrayReshape_t* array_reshape = ASR::down_cast<ASR::ArrayReshape_t>(a_value);
return is_value_constant(array_reshape->m_array) && is_value_constant(array_reshape->m_shape);
} else if( ASR::is_a<ASR::StructTypeConstructor_t>(*a_value) ) {
ASR::StructTypeConstructor_t* struct_type_constructor =
ASR::down_cast<ASR::StructTypeConstructor_t>(a_value);
bool is_constant = true;
for( size_t i = 0; i < struct_type_constructor->n_args; i++ ) {
if( struct_type_constructor->m_args[i].m_value ) {
is_constant = is_constant &&
(is_value_constant(
struct_type_constructor->m_args[i].m_value) ||
is_value_constant(
ASRUtils::expr_value(
struct_type_constructor->m_args[i].m_value)));
}
}
return is_constant;
} else {
return false;
}
Expand Down
18 changes: 18 additions & 0 deletions src/libasr/asr_verify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,24 @@ class VerifyVisitor : public BaseWalkVisitor<VerifyVisitor>
"Variable::m_parent_symtab must be present in the ASR ("
+ std::string(x.m_name) + ")");

ASR::asr_t* asr_owner = symtab->asr_owner;
bool is_module = false;
if( ASR::is_a<ASR::symbol_t>(*asr_owner) &&
ASR::is_a<ASR::Module_t>(
*ASR::down_cast<ASR::symbol_t>(asr_owner)) ) {
is_module = true;
}
if( symtab->parent != nullptr &&
!is_module) {
// 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)),
"Initialisation of " + std::string(x.m_name) +
" must reduce to a compile time constant.");
}

if (x.m_symbolic_value)
visit_expr(*x.m_symbolic_value);
visit_ttype(*x.m_type);
Expand Down
5 changes: 3 additions & 2 deletions src/libasr/codegen/asr_to_llvm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2154,7 +2154,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
}

void visit_Variable(const ASR::Variable_t &x) {
if (x.m_value) {
if (x.m_value && x.m_storage == ASR::storage_typeType::Parameter) {
this->visit_expr_wrapper(x.m_value, true);
return;
}
Expand Down Expand Up @@ -5534,7 +5534,8 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
}

inline void fetch_var(ASR::Variable_t* x) {
if (x->m_value) {
// Only do for constant variables
if (x->m_value && x->m_storage == ASR::storage_typeType::Parameter) {
this->visit_expr_wrapper(x->m_value, true);
return;
}
Expand Down
18 changes: 11 additions & 7 deletions src/libasr/pass/inline_function_calls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -294,18 +294,22 @@ class InlineFunctionCallVisitor : public PassUtils::PassVisitor<InlineFunctionCa
break;
}
ASR::ttype_t* local_var_type = func_var->m_type;
if( ASR::is_a<ASR::Const_t>(*local_var_type) ) {
local_var_type = ASR::down_cast<ASR::Const_t>(local_var_type)->m_type;
}
LCOMPILERS_ASSERT(!ASR::is_a<ASR::Const_t>(*local_var_type));
ASR::symbol_t* local_var = (ASR::symbol_t*) ASR::make_Variable_t(
al, func_var->base.base.loc, current_scope,
s2c(al, local_var_name), nullptr, 0, ASR::intentType::Local,
nullptr, nullptr, ASR::storage_typeType::Default,
local_var_type, ASR::abiType::Source, ASR::accessType::Public,
ASR::presenceType::Required, false);
al, func_var->base.base.loc, current_scope,
s2c(al, local_var_name), nullptr, 0, ASR::intentType::Local,
nullptr, nullptr, ASR::storage_typeType::Default,
local_var_type, ASR::abiType::Source, ASR::accessType::Public,
ASR::presenceType::Required, false);
current_scope->add_symbol(local_var_name, local_var);
arg2value[func_var_name] = local_var;
if( m_symbolic_value && !ASR::is_a<ASR::Const_t>(*local_var_type) ) {
if( m_symbolic_value ) {
exprs_to_be_visited.push_back(std::make_pair(m_symbolic_value, local_var));
}
if( m_value && !ASR::is_a<ASR::Const_t>(*local_var_type) ) {
if( m_value ) {
exprs_to_be_visited.push_back(std::make_pair(m_value, local_var));
}
}
Expand Down
Loading

0 comments on commit 6ebd4b8

Please sign in to comment.