Skip to content
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

Fix double initialisation of variables in ASR #1629

Merged
merged 2 commits into from
Mar 27, 2023
Merged
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
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