Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 670b12f

Browse files
authored
Merge pull request #2372 from Shaikh-Ubaid/intrinsic_floor_div
Support floor division as intrinsic function
2 parents e97aa69 + 235117b commit 670b12f

File tree

82 files changed

+2377
-2236
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

82 files changed

+2377
-2236
lines changed

integration_tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -799,6 +799,7 @@ RUN(NAME callback_04 IMPORT_PATH .. LABELS cpython)
799799

800800
# Intrinsic Functions
801801
RUN(NAME intrinsics_01 LABELS cpython llvm NOFAST) # any
802+
RUN(NAME intrinsics_02 LABELS cpython llvm c) # floordiv
802803

803804
# lpython decorator
804805
RUN(NAME lpython_decorator_01 LABELS cpython)

integration_tests/intrinsics_02.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
from lpython import Const, i32, f32, f64
2+
3+
foo: Const[i32] = 4
4+
bar: Const[i32] = foo // 2
5+
6+
print(bar)
7+
assert bar == 2
8+
9+
def floordiv1():
10+
a: f64
11+
b: f64
12+
c: f64
13+
a = 5.0
14+
b = 2.0
15+
c = a // b
16+
17+
print(c)
18+
assert c == 2.0
19+
20+
def floordiv2():
21+
a: Const[f32] = f32(5.0)
22+
b: Const[f32] = f32(2.0)
23+
c: f32
24+
c = a // b
25+
26+
print(c)
27+
assert c == f32(2.0)
28+
29+
def floordiv3():
30+
a: f64
31+
b: f64
32+
c: f64
33+
a = 5.0
34+
b = -2.0
35+
c = a // b
36+
37+
print(c)
38+
assert c == -3.0
39+
40+
floordiv1()
41+
floordiv2()
42+
floordiv3()

src/libasr/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ set(SRC
6565

6666
asr_verify.cpp
6767
asr_utils.cpp
68+
casting_utils.cpp
6869
diagnostics.cpp
6970
stacktrace.cpp
7071
string_utils.cpp

src/libasr/casting_utils.cpp

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
#include <libasr/casting_utils.h>
2+
#include <libasr/asr_utils.h>
3+
4+
#include <map>
5+
6+
7+
namespace LCompilers::CastingUtil {
8+
9+
// Data structure which contains priorities for
10+
// intrinsic types defined in ASR
11+
const std::map<ASR::ttypeType, int>& type2weight = {
12+
{ASR::ttypeType::Complex, 4},
13+
{ASR::ttypeType::Real, 3},
14+
{ASR::ttypeType::Integer, 2},
15+
{ASR::ttypeType::Logical, 1}
16+
};
17+
18+
// Data structure which contains casting rules for non-equal
19+
// intrinsic types defined in ASR
20+
const std::map<std::pair<ASR::ttypeType, ASR::ttypeType>, ASR::cast_kindType>& type_rules = {
21+
{std::make_pair(ASR::ttypeType::Complex, ASR::ttypeType::Real), ASR::cast_kindType::ComplexToReal},
22+
{std::make_pair(ASR::ttypeType::Complex, ASR::ttypeType::Logical), ASR::cast_kindType::ComplexToLogical},
23+
{std::make_pair(ASR::ttypeType::Real, ASR::ttypeType::Complex), ASR::cast_kindType::RealToComplex},
24+
{std::make_pair(ASR::ttypeType::Real, ASR::ttypeType::Integer), ASR::cast_kindType::RealToInteger},
25+
{std::make_pair(ASR::ttypeType::Real, ASR::ttypeType::Logical), ASR::cast_kindType::RealToLogical},
26+
{std::make_pair(ASR::ttypeType::Real, ASR::ttypeType::UnsignedInteger), ASR::cast_kindType::RealToUnsignedInteger},
27+
{std::make_pair(ASR::ttypeType::Integer, ASR::ttypeType::Complex), ASR::cast_kindType::IntegerToComplex},
28+
{std::make_pair(ASR::ttypeType::Integer, ASR::ttypeType::Real), ASR::cast_kindType::IntegerToReal},
29+
{std::make_pair(ASR::ttypeType::Integer, ASR::ttypeType::Logical), ASR::cast_kindType::IntegerToLogical},
30+
{std::make_pair(ASR::ttypeType::Integer, ASR::ttypeType::UnsignedInteger), ASR::cast_kindType::IntegerToUnsignedInteger},
31+
{std::make_pair(ASR::ttypeType::Logical, ASR::ttypeType::Real), ASR::cast_kindType::LogicalToReal},
32+
{std::make_pair(ASR::ttypeType::Logical, ASR::ttypeType::Integer), ASR::cast_kindType::LogicalToInteger},
33+
{std::make_pair(ASR::ttypeType::UnsignedInteger, ASR::ttypeType::Integer), ASR::cast_kindType::UnsignedIntegerToInteger},
34+
{std::make_pair(ASR::ttypeType::UnsignedInteger, ASR::ttypeType::Real), ASR::cast_kindType::UnsignedIntegerToReal},
35+
{std::make_pair(ASR::ttypeType::Integer, ASR::ttypeType::SymbolicExpression), ASR::cast_kindType::IntegerToSymbolicExpression}
36+
};
37+
38+
// Data structure which contains casting rules for equal intrinsic
39+
// types but with different kinds.
40+
const std::map<ASR::ttypeType, ASR::cast_kindType>& kind_rules = {
41+
{ASR::ttypeType::Complex, ASR::cast_kindType::ComplexToComplex},
42+
{ASR::ttypeType::Real, ASR::cast_kindType::RealToReal},
43+
{ASR::ttypeType::Integer, ASR::cast_kindType::IntegerToInteger},
44+
{ASR::ttypeType::UnsignedInteger, ASR::cast_kindType::UnsignedIntegerToUnsignedInteger}
45+
};
46+
47+
int get_type_priority(ASR::ttypeType type) {
48+
if( type2weight.find(type) == type2weight.end() ) {
49+
return -1;
50+
}
51+
52+
return type2weight.at(type);
53+
}
54+
55+
int get_src_dest(ASR::expr_t* left_expr, ASR::expr_t* right_expr,
56+
ASR::expr_t*& src_expr, ASR::expr_t*& dest_expr,
57+
ASR::ttype_t*& src_type, ASR::ttype_t*& dest_type,
58+
bool is_assign) {
59+
ASR::ttype_t* left_type = ASRUtils::expr_type(left_expr);
60+
ASR::ttype_t* right_type = ASRUtils::expr_type(right_expr);
61+
if( ASR::is_a<ASR::Const_t>(*left_type) ) {
62+
left_type = ASRUtils::get_contained_type(left_type);
63+
}
64+
if( ASR::is_a<ASR::Const_t>(*right_type) ) {
65+
right_type = ASRUtils::get_contained_type(right_type);
66+
}
67+
left_type = ASRUtils::type_get_past_pointer(left_type);
68+
right_type = ASRUtils::type_get_past_pointer(right_type);
69+
if( ASRUtils::check_equal_type(left_type, right_type) ||
70+
ASRUtils::is_character(*left_type) || ASRUtils::is_character(*right_type) ) {
71+
return 2;
72+
}
73+
if( is_assign ) {
74+
if( ASRUtils::is_real(*left_type) && ASRUtils::is_integer(*right_type)) {
75+
throw SemanticError("Assigning integer to float is not supported",
76+
right_expr->base.loc);
77+
}
78+
if ( ASRUtils::is_complex(*left_type) && !ASRUtils::is_complex(*right_type)) {
79+
throw SemanticError("Assigning non-complex to complex is not supported",
80+
right_expr->base.loc);
81+
}
82+
dest_expr = left_expr, dest_type = left_type;
83+
src_expr = right_expr, src_type = right_type;
84+
return 1;
85+
}
86+
87+
int casted_expr_signal = 2;
88+
ASR::ttypeType left_Type = left_type->type, right_Type = right_type->type;
89+
int left_kind = ASRUtils::extract_kind_from_ttype_t(left_type);
90+
int right_kind = ASRUtils::extract_kind_from_ttype_t(right_type);
91+
int left_priority = get_type_priority(left_Type);
92+
int right_priority = get_type_priority(right_Type);
93+
if( left_priority > right_priority ) {
94+
src_expr = right_expr, src_type = right_type;
95+
dest_expr = left_expr, dest_type = left_type;
96+
casted_expr_signal = 1;
97+
} else if( left_priority < right_priority ) {
98+
src_expr = left_expr, src_type = left_type;
99+
dest_expr = right_expr, dest_type = right_type;
100+
casted_expr_signal = 0;
101+
} else {
102+
if( left_kind > right_kind ) {
103+
src_expr = right_expr, src_type = right_type;
104+
dest_expr = left_expr, dest_type = left_type;
105+
casted_expr_signal = 1;
106+
} else if( left_kind < right_kind ) {
107+
src_expr = left_expr, src_type = left_type;
108+
dest_expr = right_expr, dest_type = right_type;
109+
casted_expr_signal = 0;
110+
} else {
111+
return 2;
112+
}
113+
}
114+
115+
return casted_expr_signal;
116+
}
117+
118+
ASR::expr_t* perform_casting(ASR::expr_t* expr, ASR::ttype_t* src,
119+
ASR::ttype_t* dest, Allocator& al,
120+
const Location& loc) {
121+
ASR::ttypeType src_type = src->type;
122+
ASR::ttypeType dest_type = dest->type;
123+
ASR::cast_kindType cast_kind;
124+
if( src_type == dest_type ) {
125+
if( kind_rules.find(src_type) == kind_rules.end() ) {
126+
return expr;
127+
}
128+
cast_kind = kind_rules.at(src_type);
129+
} else {
130+
std::pair<ASR::ttypeType, ASR::ttypeType> cast_key = std::make_pair(src_type, dest_type);
131+
if( type_rules.find(cast_key) == type_rules.end() ) {
132+
return expr;
133+
}
134+
cast_kind = type_rules.at(cast_key);
135+
}
136+
if( ASRUtils::check_equal_type(src, dest, true) ) {
137+
return expr;
138+
}
139+
// TODO: Fix loc
140+
return ASRUtils::EXPR(ASRUtils::make_Cast_t_value(al, loc, expr,
141+
cast_kind, dest));
142+
}
143+
}

src/libasr/casting_utils.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#ifndef LFORTRAN_CASTING_UTILS_H
2+
#define LFORTRAN_CASTING_UTILS_H
3+
4+
5+
#include <libasr/asr.h>
6+
7+
namespace LCompilers::CastingUtil {
8+
9+
int get_type_priority(ASR::ttypeType type);
10+
11+
int get_src_dest(ASR::expr_t* left_expr, ASR::expr_t* right_expr,
12+
ASR::expr_t*& src_expr, ASR::expr_t*& dest_expr,
13+
ASR::ttype_t*& src_type, ASR::ttype_t*& dest_type,
14+
bool is_assign);
15+
16+
ASR::expr_t* perform_casting(ASR::expr_t* expr, ASR::ttype_t* src,
17+
ASR::ttype_t* dest, Allocator& al,
18+
const Location& loc);
19+
}
20+
21+
#endif // LFORTRAN_CASTING_UTILS_H

src/libasr/codegen/asr_to_c_cpp.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2800,6 +2800,7 @@ PyMODINIT_FUNC PyInit_lpython_module_)" + fn_name + R"((void) {
28002800
SET_INTRINSIC_NAME(Expm1, "expm1");
28012801
SET_INTRINSIC_NAME(Trunc, "trunc");
28022802
SET_INTRINSIC_NAME(Fix, "fix");
2803+
SET_INTRINSIC_NAME(FloorDiv, "floordiv");
28032804
default : {
28042805
throw LCompilersException("IntrinsicScalarFunction: `"
28052806
+ ASRUtils::get_intrinsic_name(x.m_intrinsic_id)

src/libasr/codegen/asr_to_wasm.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2299,7 +2299,7 @@ class ASRToWASMVisitor : public ASR::BaseVisitor<ASRToWASMVisitor> {
22992299

23002300
void visit_RealConstant(const ASR::RealConstant_t &x) {
23012301
double val = x.m_r;
2302-
int a_kind = ((ASR::Real_t *)(&(x.m_type->base)))->m_kind;
2302+
int a_kind = ASRUtils::extract_kind_from_ttype_t(x.m_type);
23032303
switch (a_kind) {
23042304
case 4: {
23052305
m_wa.emit_f32_const(val);
@@ -2318,7 +2318,7 @@ class ASRToWASMVisitor : public ASR::BaseVisitor<ASRToWASMVisitor> {
23182318

23192319
void visit_LogicalConstant(const ASR::LogicalConstant_t &x) {
23202320
bool val = x.m_value;
2321-
int a_kind = ((ASR::Logical_t *)(&(x.m_type->base)))->m_kind;
2321+
int a_kind = ASRUtils::extract_kind_from_ttype_t(x.m_type);
23222322
switch (a_kind) {
23232323
case 4: {
23242324
m_wa.emit_i32_const(val);
@@ -3222,7 +3222,7 @@ Result<Vec<uint8_t>> asr_to_wasm_bytes_stream(ASR::TranslationUnit_t &asr,
32223222
pass_options.dump_all_passes = co.dump_all_passes;
32233223
std::vector<std::string> passes = {"pass_array_by_data", "array_op",
32243224
"implied_do_loops", "print_arr", "do_loops", "select_case",
3225-
"intrinsic_function", "nested_vars", "unused_functions"};
3225+
"nested_vars", "unused_functions", "intrinsic_function"};
32263226
LCompilers::PassManager pass_manager;
32273227
pass_manager.apply_passes(al, &asr, passes, pass_options, diagnostics);
32283228

0 commit comments

Comments
 (0)