Skip to content

Commit dd2413b

Browse files
Sync from LFortran's IntrinsicFunctions (#1720)
LFortran: lfortran/lfortran#1485
1 parent aa1f195 commit dd2413b

11 files changed

+735
-55
lines changed

integration_tests/CMakeLists.txt

+4-1
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ RUN(NAME test_dict_06 LABELS cpython llvm c)
294294
RUN(NAME test_dict_07 LABELS cpython llvm)
295295
RUN(NAME test_dict_08 LABELS cpython llvm c)
296296
RUN(NAME test_dict_09 LABELS cpython llvm c)
297-
RUN(NAME test_dict_10 LABELS cpython llvm) # TODO: Add support of dict with string in C backend
297+
RUN(NAME test_dict_10 LABELS cpython llvm) # TODO: Add support of dict with string in C backend
298298
RUN(NAME test_for_loop LABELS cpython llvm c)
299299
RUN(NAME modules_01 LABELS cpython llvm c wasm wasm_x86 wasm_x64)
300300
RUN(NAME modules_02 LABELS cpython llvm c wasm wasm_x86 wasm_x64)
@@ -452,3 +452,6 @@ RUN(NAME global_syms_03_c LABELS cpython llvm c)
452452
RUN(NAME global_syms_04 LABELS cpython llvm c wasm wasm_x64)
453453
RUN(NAME global_syms_05 LABELS cpython llvm c)
454454
RUN(NAME global_syms_06 LABELS cpython llvm c)
455+
456+
# Intrinsic Functions
457+
RUN(NAME intrinsics_01 LABELS cpython llvm) # any

integration_tests/intrinsics_01.py

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
from numpy import array
2+
3+
def any_01() -> None:
4+
x: bool[2]
5+
6+
x= array([False, False])
7+
assert not any(x)
8+
9+
x = array([False, True])
10+
assert any(x)
11+
12+
x = array([True, True])
13+
assert any(x)
14+
15+
any_01()

src/libasr/asr_utils.h

+14
Original file line numberDiff line numberDiff line change
@@ -1772,6 +1772,20 @@ static inline ASR::ttype_t* duplicate_type(Allocator& al, const ASR::ttype_t* t,
17721772
}
17731773
}
17741774

1775+
static inline ASR::ttype_t* duplicate_type_with_empty_dims(Allocator& al, ASR::ttype_t* t) {
1776+
size_t n_dims = ASRUtils::extract_n_dims_from_ttype(t);
1777+
Vec<ASR::dimension_t> empty_dims;
1778+
empty_dims.reserve(al, n_dims);
1779+
for( size_t i = 0; i < n_dims; i++ ) {
1780+
ASR::dimension_t empty_dim;
1781+
empty_dim.loc = t->base.loc;
1782+
empty_dim.m_start = nullptr;
1783+
empty_dim.m_length = nullptr;
1784+
empty_dims.push_back(al, empty_dim);
1785+
}
1786+
return duplicate_type(al, t, &empty_dims);
1787+
}
1788+
17751789
static inline ASR::ttype_t* duplicate_type_without_dims(Allocator& al, const ASR::ttype_t* t, const Location& loc) {
17761790
switch (t->type) {
17771791
case ASR::ttypeType::Integer: {

src/libasr/asr_verify.cpp

+7-2
Original file line numberDiff line numberDiff line change
@@ -718,7 +718,7 @@ class VerifyVisitor : public BaseWalkVisitor<VerifyVisitor>
718718
}
719719

720720
if( func ) {
721-
for (size_t i=0; i<x.n_args; i++) {
721+
for (size_t i = 0; i < x.n_args; i++) {
722722
ASR::symbol_t* arg_sym = ASR::down_cast<ASR::Var_t>(func->m_args[i])->m_v;
723723
if (x.m_args[i].m_value == nullptr &&
724724
(ASR::is_a<ASR::Variable_t>(*arg_sym) &&
@@ -857,15 +857,20 @@ class VerifyVisitor : public BaseWalkVisitor<VerifyVisitor>
857857
// Check both `name` and `orig_name` that `orig_name` points
858858
// to GenericProcedure (if applicable), both external and non
859859
// external
860+
const ASR::symbol_t *fn = ASRUtils::symbol_get_past_external(x.m_name);
860861
if (check_external) {
861-
const ASR::symbol_t *fn = ASRUtils::symbol_get_past_external(x.m_name);
862862
require(ASR::is_a<ASR::Function_t>(*fn) ||
863863
(ASR::is_a<ASR::Variable_t>(*fn) &&
864864
ASR::is_a<ASR::FunctionType_t>(*ASRUtils::symbol_type(fn))) ||
865865
ASR::is_a<ASR::ClassProcedure_t>(*fn),
866866
"FunctionCall::m_name must be a Function or Variable with FunctionType");
867867
}
868868

869+
if( fn && ASR::is_a<ASR::Function_t>(*fn) ) {
870+
ASR::Function_t* fn_ = ASR::down_cast<ASR::Function_t>(fn);
871+
require(fn_->m_return_var != nullptr,
872+
"FunctionCall::m_name must be returning a non-void value.");
873+
}
869874
verify_args(x);
870875
visit_ttype(*x.m_type);
871876
}

src/libasr/codegen/asr_to_llvm.cpp

+6-3
Original file line numberDiff line numberDiff line change
@@ -3102,14 +3102,16 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
31023102
ASR::ttype_t* symbol_type = ASRUtils::symbol_type(item.second);
31033103
int idx = name2memidx[struct_type_name][item.first];
31043104
llvm::Value* ptr_member = llvm_utils->create_gep(ptr, idx);
3105+
ASR::Variable_t* v = nullptr;
31053106
if( ASR::is_a<ASR::Variable_t>(*item.second) ) {
3106-
ASR::Variable_t* v = ASR::down_cast<ASR::Variable_t>(item.second);
3107+
v = ASR::down_cast<ASR::Variable_t>(item.second);
31073108
if( v->m_symbolic_value ) {
31083109
visit_expr(*v->m_symbolic_value);
31093110
LLVM::CreateStore(*builder, tmp, ptr_member);
31103111
}
31113112
}
3112-
if( ASRUtils::is_array(symbol_type) ) {
3113+
if( ASRUtils::is_array(symbol_type) &&
3114+
(v && v->m_storage != ASR::storage_typeType::Allocatable) ) {
31133115
// Assume that struct member array is not allocatable
31143116
ASR::dimension_t* m_dims = nullptr;
31153117
size_t n_dims = ASRUtils::extract_dimensions_from_ttype(symbol_type, m_dims);
@@ -6983,7 +6985,8 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
69836985
throw CodeGenError(std::string(arg->m_name) + " isn't defined in any scope.");
69846986
}
69856987
this->visit_expr_wrapper(arg->m_value, true);
6986-
if( x_abi != ASR::abiType::BindC ) {
6988+
if( x_abi != ASR::abiType::BindC &&
6989+
!ASR::is_a<ASR::ArrayConstant_t>(*arg->m_value) ) {
69876990
llvm::BasicBlock &entry_block = builder->GetInsertBlock()->getParent()->getEntryBlock();
69886991
llvm::IRBuilder<> builder0(context);
69896992
builder0.SetInsertPoint(&entry_block, entry_block.getFirstInsertionPt());

src/libasr/pass/array_op.cpp

+42-3
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <libasr/asr_verify.h>
66
#include <libasr/pass/array_op.h>
77
#include <libasr/pass/pass_utils.h>
8+
#include <libasr/pass/intrinsic_function_registry.h>
89

910
#include <vector>
1011
#include <utility>
@@ -207,6 +208,7 @@ class ReplaceArrayOp: public ASR::BaseExprReplacer<ReplaceArrayOp> {
207208
ASR::stmt_t* assign = ASRUtils::STMT(ASR::make_Assignment_t(al, loc, res, ref, nullptr));
208209
doloop_body.push_back(al, assign);
209210
});
211+
*current_expr = nullptr;
210212
result_var = nullptr;
211213
use_custom_loop_params = false;
212214
}
@@ -281,6 +283,7 @@ class ReplaceArrayOp: public ASR::BaseExprReplacer<ReplaceArrayOp> {
281283
});
282284
result_var = nullptr;
283285
use_custom_loop_params = false;
286+
*current_expr = nullptr;
284287
}
285288

286289
void replace_IntegerConstant(ASR::IntegerConstant_t* x) {
@@ -347,6 +350,24 @@ class ReplaceArrayOp: public ASR::BaseExprReplacer<ReplaceArrayOp> {
347350
}
348351
}
349352

353+
ASR::ttype_t* get_result_type(ASR::expr_t* arr_expr, ASR::exprType class_type) {
354+
switch( class_type ) {
355+
case ASR::exprType::RealCompare:
356+
case ASR::exprType::ComplexCompare:
357+
case ASR::exprType::LogicalCompare:
358+
case ASR::exprType::IntegerCompare: {
359+
ASR::ttype_t* arr_expr_type = ASRUtils::expr_type(arr_expr);
360+
ASR::dimension_t* m_dims;
361+
size_t n_dims = ASRUtils::extract_dimensions_from_ttype(arr_expr_type, m_dims);
362+
return ASRUtils::TYPE(ASR::make_Logical_t(al, arr_expr->base.loc,
363+
4, m_dims, n_dims));
364+
}
365+
default: {
366+
return PassUtils::get_matching_type(arr_expr, al);
367+
}
368+
}
369+
}
370+
350371
template <typename T>
351372
void replace_ArrayOpCommon(T* x, std::string res_prefix) {
352373
const Location& loc = x->base.base.loc;
@@ -387,8 +408,9 @@ class ReplaceArrayOp: public ASR::BaseExprReplacer<ReplaceArrayOp> {
387408
}
388409

389410
if( result_var == nullptr ) {
411+
ASR::ttype_t* result_var_type = get_result_type(left, x->class_type);
390412
result_var = PassUtils::create_var(result_counter, res_prefix, loc,
391-
left, al, current_scope);
413+
result_var_type, al, current_scope);
392414
result_counter += 1;
393415
}
394416
*current_expr = result_var;
@@ -422,8 +444,9 @@ class ReplaceArrayOp: public ASR::BaseExprReplacer<ReplaceArrayOp> {
422444
n_dims = rank_right;
423445
}
424446
if( result_var == nullptr ) {
447+
ASR::ttype_t* result_var_type = get_result_type(arr_expr, x->class_type);
425448
result_var = PassUtils::create_var(result_counter, res_prefix, loc,
426-
arr_expr, al, current_scope);
449+
result_var_type, al, current_scope);
427450
result_counter += 1;
428451
}
429452
*current_expr = result_var;
@@ -547,6 +570,7 @@ class ReplaceArrayOp: public ASR::BaseExprReplacer<ReplaceArrayOp> {
547570
});
548571
result_var = nullptr;
549572
use_custom_loop_params = false;
573+
*current_expr = nullptr;
550574
}
551575
}
552576
return ;
@@ -590,6 +614,7 @@ class ReplaceArrayOp: public ASR::BaseExprReplacer<ReplaceArrayOp> {
590614
op_el_wise, nullptr));
591615
doloop_body.push_back(al, assign);
592616
});
617+
result_var = nullptr;
593618
use_custom_loop_params = false;
594619
}
595620
}
@@ -647,6 +672,9 @@ class ReplaceArrayOp: public ASR::BaseExprReplacer<ReplaceArrayOp> {
647672
}
648673

649674
void replace_IntrinsicFunction(ASR::IntrinsicFunction_t* x) {
675+
if( !ASRUtils::IntrinsicFunctionRegistry::is_elemental(x->m_intrinsic_id) ) {
676+
return ;
677+
}
650678
LCOMPILERS_ASSERT(current_scope != nullptr);
651679
const Location& loc = x->base.base.loc;
652680
std::vector<bool> array_mask(x->n_args, false);
@@ -924,6 +952,8 @@ class ArrayOpVisitor : public ASR::CallReplacerOnExpressionsVisitor<ArrayOpVisit
924952
pass_result.n = 0;
925953
pass_result.reserve(al, 1);
926954
remove_original_statement = false;
955+
replacer.result_var = nullptr;
956+
replacer.result_type = nullptr;
927957
Vec<ASR::stmt_t*>* parent_body_copy = parent_body;
928958
parent_body = &body;
929959
visit_stmt(*m_body[i]);
@@ -1147,10 +1177,19 @@ class ArrayOpVisitor : public ASR::CallReplacerOnExpressionsVisitor<ArrayOpVisit
11471177

11481178
inline void visit_AssignmentUtil(const ASR::Assignment_t& x) {
11491179
ASR::expr_t** current_expr_copy_9 = current_expr;
1180+
ASR::expr_t* original_value = x.m_value;
11501181
current_expr = const_cast<ASR::expr_t**>(&(x.m_value));
11511182
this->call_replacer();
11521183
current_expr = current_expr_copy_9;
1153-
this->visit_expr(*x.m_value);
1184+
if( x.m_value == original_value ) {
1185+
ASR::expr_t* result_var_copy = replacer.result_var;
1186+
replacer.result_var = nullptr;
1187+
this->visit_expr(*x.m_value);
1188+
replacer.result_var = result_var_copy;
1189+
remove_original_statement = false;
1190+
} else if( x.m_value ) {
1191+
this->visit_expr(*x.m_value);
1192+
}
11541193
if (x.m_overloaded) {
11551194
this->visit_stmt(*x.m_overloaded);
11561195
}

0 commit comments

Comments
 (0)