diff --git a/integration_tests/CMakeLists.txt b/integration_tests/CMakeLists.txt index d2e7160f23b..b2f4a182319 100644 --- a/integration_tests/CMakeLists.txt +++ b/integration_tests/CMakeLists.txt @@ -374,6 +374,9 @@ RUN(NAME bindc_04 LABELS llvm c NOFAST) RUN(NAME bindc_07 LABELS cpython llvm c NOFAST) RUN(NAME bindc_08 LABELS cpython llvm c) RUN(NAME bindc_09 LABELS cpython llvm c) +RUN(NAME bindc_09b LABELS cpython llvm c) +RUN(NAME bindc_10 LABELS cpython llvm c NOFAST) +RUN(NAME bindc_11 LABELS cpython) # This is CPython test only RUN(NAME exit_01 LABELS cpython llvm c NOFAST) RUN(NAME exit_02 FAIL LABELS cpython llvm c NOFAST) RUN(NAME exit_03 LABELS cpython llvm c wasm wasm_x86 wasm_x64) @@ -418,6 +421,7 @@ RUN(NAME expr_15 LABELS cpython llvm c) RUN(NAME expr_16 LABELS cpython c) RUN(NAME expr_17 LABELS cpython llvm c) RUN(NAME expr_18 FAIL LABELS cpython llvm c) +RUN(NAME expr_19 LABELS cpython llvm c) RUN(NAME expr_01u LABELS cpython llvm c NOFAST) RUN(NAME expr_02u LABELS cpython llvm c NOFAST) @@ -456,6 +460,7 @@ RUN(NAME test_list_repeat LABELS cpython llvm NOFAST) RUN(NAME test_list_reverse LABELS cpython llvm) RUN(NAME test_list_pop LABELS cpython llvm NOFAST) # TODO: Remove NOFAST from here. RUN(NAME test_list_pop2 LABELS cpython llvm NOFAST) # TODO: Remove NOFAST from here. +RUN(NAME test_list_compare LABELS cpython llvm) RUN(NAME test_tuple_01 LABELS cpython llvm c) RUN(NAME test_tuple_02 LABELS cpython llvm c NOFAST) RUN(NAME test_tuple_03 LABELS cpython llvm c) @@ -553,16 +558,19 @@ RUN(NAME test_ConstantEllipsis LABLES cpython llvm c) RUN(NAME test_max_min LABELS cpython llvm c) RUN(NAME test_global LABELS cpython llvm c) RUN(NAME test_global_decl LABELS cpython llvm c) -RUN(NAME test_integer_bitnot LABELS cpython llvm c wasm) -RUN(NAME test_unsign_int_bitnot LABELS cpython llvm c) RUN(NAME test_ifexp_01 LABELS cpython llvm c) RUN(NAME test_ifexp_02 LABELS cpython llvm c) -RUN(NAME test_unary_minus LABELS cpython llvm c) -RUN(NAME test_unary_plus LABELS cpython llvm c) +RUN(NAME test_unary_op_01 LABELS cpython llvm c) # unary minus +RUN(NAME test_unary_op_02 LABELS cpython llvm c) # unary plus +RUN(NAME test_unary_op_03 LABELS cpython llvm c wasm) # unary bitinvert +RUN(NAME test_unary_op_04 LABELS cpython llvm c) # unary bitinvert +RUN(NAME test_unary_op_05 LABELS cpython llvm c) # unsigned unary minus, plus +RUN(NAME test_unary_op_06 LABELS cpython llvm c) # unsigned unary bitnot RUN(NAME test_bool_binop LABELS cpython llvm c) RUN(NAME test_issue_518 LABELS cpython llvm c NOFAST) RUN(NAME structs_01 LABELS cpython llvm c) RUN(NAME structs_02 LABELS cpython llvm c) +RUN(NAME structs_02b LABELS cpython llvm c NOFAST) RUN(NAME structs_03 LABELS llvm c) RUN(NAME structs_04 LABELS cpython llvm c) RUN(NAME structs_05 LABELS cpython llvm c) @@ -598,12 +606,14 @@ RUN(NAME structs_29 LABELS cpython llvm) RUN(NAME structs_30 LABELS cpython llvm c) RUN(NAME structs_31 LABELS cpython llvm c) RUN(NAME structs_32 LABELS cpython llvm c) +RUN(NAME structs_33 LABELS cpython llvm c) RUN(NAME symbolics_01 LABELS cpython_sym c_sym) RUN(NAME symbolics_02 LABELS cpython_sym c_sym) RUN(NAME symbolics_03 LABELS cpython_sym c_sym) RUN(NAME symbolics_04 LABELS cpython_sym c_sym) RUN(NAME symbolics_05 LABELS cpython_sym c_sym) +RUN(NAME symbolics_06 LABELS cpython_sym c_sym) RUN(NAME sizeof_01 LABELS llvm c EXTRAFILES sizeof_01b.c) @@ -631,6 +641,8 @@ RUN(NAME vec_01 LABELS cpython llvm c NOFAST) RUN(NAME test_str_comparison LABELS cpython llvm c) RUN(NAME test_bit_length LABELS cpython llvm c) RUN(NAME str_to_list_cast LABELS cpython llvm c) +RUN(NAME cast_01 LABELS cpython llvm c) +RUN(NAME cast_02 LABELS cpython llvm c) RUN(NAME test_sys_01 LABELS cpython llvm c NOFAST) RUN(NAME intent_01 LABELS cpython llvm) diff --git a/integration_tests/bindc_09.py b/integration_tests/bindc_09.py index 18fdaad29ef..956b56b6588 100644 --- a/integration_tests/bindc_09.py +++ b/integration_tests/bindc_09.py @@ -1,6 +1,7 @@ from enum import Enum -from lpython import CPtr, c_p_pointer, p_c_pointer, dataclass, empty_c_void_p, pointer, Pointer, i32, ccallable +from lpython import (CPtr, c_p_pointer, p_c_pointer, dataclass, empty_c_void_p, + pointer, Pointer, i32, ccallable, InOut) class Value(Enum): TEN: i32 = 10 @@ -17,8 +18,7 @@ class Foo: class FooC: value: Value -def bar(foo_ptr: CPtr) -> None: - foo: Pointer[Foo] = c_p_pointer(foo_ptr, Foo) +def bar(foo: InOut[Foo]) -> None: foo.value = Value.FIVE def barc(foo_ptr: CPtr) -> None: @@ -30,8 +30,7 @@ def main() -> None: fooc: FooC = FooC(Value.TWO) foo_ptr: CPtr = empty_c_void_p() - p_c_pointer(pointer(foo), foo_ptr) - bar(foo_ptr) + bar(foo) print(foo.value, foo.value.name) assert foo.value == Value.FIVE diff --git a/integration_tests/bindc_09b.py b/integration_tests/bindc_09b.py new file mode 100644 index 00000000000..58be1e768b0 --- /dev/null +++ b/integration_tests/bindc_09b.py @@ -0,0 +1,44 @@ +from enum import Enum + +from lpython import CPtr, c_p_pointer, p_c_pointer, dataclass, empty_c_void_p, pointer, Pointer, i32, ccallable + +class Value(Enum): + TEN: i32 = 10 + TWO: i32 = 2 + ONE: i32 = 1 + FIVE: i32 = 5 + +@ccallable +@dataclass +class Foo: + value: Value + +@ccallable +@dataclass +class FooC: + value: Value + +def bar(foo_ptr: CPtr) -> None: + foo: Pointer[Foo] = c_p_pointer(foo_ptr, Foo) + foo.value = Value.FIVE + +def barc(foo_ptr: CPtr) -> None: + foo: Pointer[FooC] = c_p_pointer(foo_ptr, FooC) + foo.value = Value.ONE + +def main() -> None: + foo: Foo = Foo(Value.TEN) + fooc: FooC = FooC(Value.TWO) + foo_ptr: CPtr = empty_c_void_p() + + p_c_pointer(pointer(foo), foo_ptr) + bar(foo_ptr) + print(foo.value) + assert foo.value == Value.FIVE.value + + p_c_pointer(pointer(fooc), foo_ptr) + barc(foo_ptr) + print(fooc.value) + assert fooc.value == Value.ONE.value + +main() diff --git a/integration_tests/bindc_10.py b/integration_tests/bindc_10.py new file mode 100644 index 00000000000..934eacfd43b --- /dev/null +++ b/integration_tests/bindc_10.py @@ -0,0 +1,32 @@ +from lpython import (i64, i16, CPtr, c_p_pointer, Pointer, sizeof, packed, + dataclass, ccallable, ccall, i32) + +@ccall +def _lfortran_malloc(size: i32) -> CPtr: + pass + + +def alloc(buf_size:i64) -> CPtr: + return _lfortran_malloc(i32(buf_size)) + + +@ccallable +@packed +@dataclass +class S: + a: i16 + b: i64 + + +def main(): + p1: CPtr = alloc(sizeof(S)) + print(p1) + p2: Pointer[S] = c_p_pointer(p1, S) + p2.a = i16(5) + p2.b = i64(4) + print(p2.a, p2.b) + assert p2.a == i16(5) + assert p2.b == i64(4) + + +main() diff --git a/integration_tests/bindc_11.py b/integration_tests/bindc_11.py new file mode 100644 index 00000000000..c2e81c9a0a5 --- /dev/null +++ b/integration_tests/bindc_11.py @@ -0,0 +1,34 @@ +import numpy, ctypes +from lpython import (i64, i16, CPtr, c_p_pointer, Pointer, sizeof, packed, + dataclass, ccallable, ccall, i32) + +global_arrays = [] + + +def alloc(buf_size:i64) -> CPtr: + xs = numpy.empty(buf_size, dtype=numpy.uint8) + global_arrays.append(xs) + p = ctypes.c_void_p(xs.ctypes.data) + return ctypes.cast(p.value, ctypes.c_void_p) + + +@ccallable +@packed +@dataclass +class S: + a: i16 + b: i64 + + +def main(): + p1: CPtr = alloc(sizeof(S)) + print(p1) + p2: Pointer[S] = c_p_pointer(p1, S) + p2.a = i16(5) + p2.b = i64(4) + print(p2.a, p2.b) + assert p2.a == i16(5) + assert p2.b == i64(4) + + +main() diff --git a/integration_tests/cast_01.py b/integration_tests/cast_01.py new file mode 100644 index 00000000000..41c8a124f54 --- /dev/null +++ b/integration_tests/cast_01.py @@ -0,0 +1,18 @@ +from lpython import i32, u8, u32, dataclass +from numpy import empty, uint8 + +@dataclass +class LPBHV_small: + dim : i32 = 4 + a : u8[4] = empty(4, dtype=uint8) + +def main0(): + lphv_small : LPBHV_small = LPBHV_small() + i: i32 + for i in range(4): + lphv_small.a[i] = u8(10 + i) + elt: u32 = u32(lphv_small.a[i]) + print(elt) + assert elt == u32(10 + i) + +main0() diff --git a/integration_tests/cast_02.py b/integration_tests/cast_02.py new file mode 100644 index 00000000000..2eecb5b384e --- /dev/null +++ b/integration_tests/cast_02.py @@ -0,0 +1,79 @@ +from lpython import u8, u16, u32, u64 + +def test_01(): + x : u32 = u32(10) + print(x) + assert x == u32(10) + + y: u16 = u16(x) + print(y) + assert y == u16(10) + + z: u64 = u64(y) + print(z) + assert z == u64(10) + + w: u8 = u8(z) + print(w) + assert w == u8(10) + +def test_02(): + x : u64 = u64(11) + print(x) + assert x == u64(11) + + y: u8 = u8(x) + print(y) + assert y == u8(11) + + z: u16 = u16(y) + print(z) + assert z == u16(11) + + w: u32 = u32(z) + print(w) + assert w == u32(11) + +def test_03(): + x : u32 = u32(-10) + print(x) + assert x == u32(4294967286) + + y: u16 = u16(x) + print(y) + assert y == u16(65526) + + z: u64 = u64(y) + print(z) + assert z == u64(65526) + + w: u8 = u8(z) + print(w) + assert w == u8(246) + +def test_04(): + x : u64 = u64(-11) + print(x) + # TODO: We are unable to store the following u64 in AST/R + # assert x == u64(18446744073709551605) + + y: u8 = u8(x) + print(y) + assert y == u8(245) + + z: u16 = u16(y) + print(z) + assert z == u16(245) + + w: u32 = u32(z) + print(w) + assert w == u32(245) + + +def main0(): + test_01() + test_02() + test_03() + test_04() + +main0() diff --git a/integration_tests/expr_19.py b/integration_tests/expr_19.py new file mode 100644 index 00000000000..6fe7a95998d --- /dev/null +++ b/integration_tests/expr_19.py @@ -0,0 +1,7 @@ +from lpython import (f64,) + +result : f64 = f64(14) +divisor : f64 = f64(4) +result /= divisor + +assert abs(result - f64(3.5)) < 1e-12 diff --git a/integration_tests/structs_02.py b/integration_tests/structs_02.py index f3325d6a9af..0e99458c34e 100644 --- a/integration_tests/structs_02.py +++ b/integration_tests/structs_02.py @@ -17,8 +17,6 @@ def f(a: CPtr) -> None: y = a2.y assert x == 3 assert f64(y) == 3.25 - a2 = c_p_pointer(a, A) - print(a, a2, pointer(a1)) def g(): b: CPtr = empty_c_void_p() diff --git a/integration_tests/structs_02b.py b/integration_tests/structs_02b.py new file mode 100644 index 00000000000..ed061ff6ce9 --- /dev/null +++ b/integration_tests/structs_02b.py @@ -0,0 +1,43 @@ +from lpython import (i32, f32, dataclass, CPtr, Pointer, c_p_pointer, pointer, + ccallable, empty_c_void_p, f64, ccall, sizeof, i64) + +@ccall +def _lfortran_malloc(size: i32) -> CPtr: + pass + +def alloc(buf_size:i64) -> CPtr: + return _lfortran_malloc(i32(buf_size)) + +@ccallable +@dataclass +class A: + x: i32 + y: f32 + +@ccallable +def f(a: CPtr) -> None: + x: i32 + y: f32 + a1: A = A(3, f32(3.25)) + a2: Pointer[A] + a2 = pointer(a1) + print(a2, pointer(a1)) + # TODO: does not work: + #x = a2.x + #y = a2.y + #assert x == 3 + #assert f64(y) == 3.25 + a2 = c_p_pointer(a, A) + print(a, a2, pointer(a1)) + print(a2.x, a2.y) + assert a2.x == 5 + assert a2.y == f32(6.0) + +def g(): + b: CPtr = alloc(sizeof(A)) + b2: Pointer[A] = c_p_pointer(b, A) + b2.x = 5 + b2.y = f32(6) + f(b) + +g() diff --git a/integration_tests/structs_13.py b/integration_tests/structs_13.py index 651518fc05c..9806fa1ac97 100644 --- a/integration_tests/structs_13.py +++ b/integration_tests/structs_13.py @@ -1,6 +1,8 @@ -from lpython import i32, i16, i64, CPtr, dataclass, ccall, Pointer, c_p_pointer, sizeof +from lpython import (i32, i16, i64, CPtr, dataclass, ccall, Pointer, + c_p_pointer, sizeof, ccallable) from numpy import array +@ccallable @dataclass class A: x: i32 diff --git a/integration_tests/structs_33.py b/integration_tests/structs_33.py new file mode 100644 index 00000000000..c8f02cb8e62 --- /dev/null +++ b/integration_tests/structs_33.py @@ -0,0 +1,24 @@ +from lpython import packed, dataclass, i32, ccallback, CPtr, ccall + +# test issue 2125 + +@packed +@dataclass +class inner_struct: + inner_field: i32 = 0 + + +@packed +@dataclass +class outer_struct: + inner_s : inner_struct = inner_struct() + + +def check() -> None: + outer_struct_instance : outer_struct = outer_struct(inner_struct(5)) + outer_struct_instance2 : outer_struct = outer_struct_instance + inner_struct_instance : inner_struct = outer_struct_instance2.inner_s + assert inner_struct_instance.inner_field == 5 + + +check() diff --git a/integration_tests/symbolics_06.py b/integration_tests/symbolics_06.py new file mode 100644 index 00000000000..f56aa52c766 --- /dev/null +++ b/integration_tests/symbolics_06.py @@ -0,0 +1,37 @@ +from sympy import Symbol, sin, cos, exp, log, Abs, pi, diff +from lpython import S + +def test_elementary_functions(): + + # test sin, cos + x: S = Symbol('x') + assert(sin(pi) == S(0)) + assert(sin(pi/S(2)) == S(1)) + assert(sin(S(2)*pi) == S(0)) + assert(cos(pi) == S(-1)) + assert(cos(pi/S(2)) == S(0)) + assert(cos(S(2)*pi) == S(1)) + assert(diff(sin(x), x) == cos(x)) + assert(diff(cos(x), x) == S(-1)*sin(x)) + + # test exp, log + assert(exp(S(0)) == S(1)) + assert(log(S(1)) == S(0)) + assert(diff(exp(x), x) == exp(x)) + assert(diff(log(x), x) == S(1)/x) + + # test Abs + assert(Abs(S(-10)) == S(10)) + assert(Abs(S(10)) == S(10)) + assert(Abs(S(-1)*x) == Abs(x)) + + # test composite functions + a: S = exp(x) + b: S = sin(a) + c: S = cos(b) + d: S = log(c) + e: S = Abs(d) + print(e) + assert(e == Abs(log(cos(sin(exp(x)))))) + +test_elementary_functions() \ No newline at end of file diff --git a/integration_tests/test_dict_increment.py b/integration_tests/test_dict_increment.py index ba363063456..b342e26bcfd 100644 --- a/integration_tests/test_dict_increment.py +++ b/integration_tests/test_dict_increment.py @@ -22,21 +22,21 @@ def test_dict_increment(): d_int_int[1] += i1 i2 += i1 assert d_int_int[1] == i2 - + i2 = 10 d_int_int = {0: 0, 1: 0} for i1 in range(i2): d_int_int[i1 % 2] += 1 assert d_int_int[0] == d_int_int[1] assert d_int_int[0] == i2 // 2 - + j1 = 2.0 d_int_float = {2: j1} while j1 < 4.0: d_int_float[2] += 0.1 j1 += 0.1 assert d_int_float[2] == j1 - + j1 = 0.0 j2 = 0.0 d_bool_float = {True: 0.0, False: 0.0} @@ -63,4 +63,4 @@ def test_dict_increment(): s1 += str(i1) assert d_int_str[-1] == s1 -test_dict_increment() \ No newline at end of file +test_dict_increment() diff --git a/integration_tests/test_list_compare.py b/integration_tests/test_list_compare.py new file mode 100644 index 00000000000..24fcc485d58 --- /dev/null +++ b/integration_tests/test_list_compare.py @@ -0,0 +1,53 @@ +from lpython import i32, f64 + +def test_list_compare(): + l1: list[i32] = [1, 2, 3] + l2: list[i32] = [1, 2, 3, 4] + l3: list[tuple[i32, f64, str]] = [(1, 2.0, 'a'), (3, 4.0, 'b')] + l4: list[tuple[i32, f64, str]] = [(1, 3.0, 'a')] + l5: list[list[str]] = [[''], ['']] + l6: list[str] = [] + l7: list[str] = [] + t1: tuple[i32, i32] + t2: tuple[i32, i32] + i: i32 + + assert l1 < l2 and l1 <= l2 + assert not l1 > l2 and not l1 >= l2 + i = l2.pop() + i = l2.pop() + assert l2 < l1 and l1 > l2 and l1 >= l2 + assert not (l1 < l2) + + l1 = [3, 4, 5] + l2 = [1, 6, 7] + assert l1 > l2 and l1 >= l2 + assert not l1 < l2 and not l1 <= l2 + + l1 = l2 + assert l1 == l2 and l1 <= l2 and l1 >= l2 + assert not l1 < l2 and not l1 > l2 + + assert l4 > l3 and l4 >= l3 + l4[0] = l3[0] + assert l4 < l3 + + for i in range(0, 10): + if i % 2 == 0: + l6.append('a') + else: + l7.append('a') + l5[0] = l6 + l5[1] = l7 + if i % 2 == 0: + assert l5[1 - i % 2] < l5[i % 2] + assert l5[1 - i % 2] <= l5[i % 2] + assert not l5[1 - i % 2] > l5[i % 2] + assert not l5[1 - i % 2] >= l5[i % 2] + + t1 = (1, 2) + t2 = (2, 3) + assert t1 < t2 and t1 <= t2 + assert not t1 > t2 and not t1 >= t2 + +test_list_compare() \ No newline at end of file diff --git a/integration_tests/test_unary_minus.py b/integration_tests/test_unary_op_01.py similarity index 100% rename from integration_tests/test_unary_minus.py rename to integration_tests/test_unary_op_01.py diff --git a/integration_tests/test_unary_plus.py b/integration_tests/test_unary_op_02.py similarity index 100% rename from integration_tests/test_unary_plus.py rename to integration_tests/test_unary_op_02.py diff --git a/integration_tests/test_integer_bitnot.py b/integration_tests/test_unary_op_03.py similarity index 100% rename from integration_tests/test_integer_bitnot.py rename to integration_tests/test_unary_op_03.py diff --git a/integration_tests/test_unsign_int_bitnot.py b/integration_tests/test_unary_op_04.py similarity index 100% rename from integration_tests/test_unsign_int_bitnot.py rename to integration_tests/test_unary_op_04.py diff --git a/integration_tests/test_unary_op_05.py b/integration_tests/test_unary_op_05.py new file mode 100644 index 00000000000..f3d7253224a --- /dev/null +++ b/integration_tests/test_unary_op_05.py @@ -0,0 +1,27 @@ +from lpython import u16, u32, u64 + +def f(): + + i: u16 + i = u16(67) + print(-i, +i, -(-i)) + assert -i == u16(65469) + assert +i == u16(67) + assert -(-i) == u16(67) + + j: u32 + j = u32(25) + print(-j, +j, -(-j)) + assert -j == u32(4294967271) + assert +j == u32(25) + assert -(-j) == u32(25) + + k: u64 + k = u64(100000000000123) + print(-k, +k, -(-k)) + # TODO: We are unable to store the following u64 in AST/R + # assert -k == u64(18446644073709551493) + assert +k == u64(100000000000123) + assert -(-k) == u64(100000000000123) + +f() diff --git a/integration_tests/test_unary_op_06.py b/integration_tests/test_unary_op_06.py new file mode 100644 index 00000000000..212d7b1609e --- /dev/null +++ b/integration_tests/test_unary_op_06.py @@ -0,0 +1,35 @@ +from lpython import i32, i64, u16, u64, f32, f64 + +def f(): + + i: i32 + j: i64 + i = -67 + j = i64(0) + + print(i, j) + print(not i, not j) + assert (not i) == False + assert (not j) == True + + k: u16 + l: u64 + k = u16(0) + l = u64(55) + + print(k, l) + print(not k, not l) + assert (not k) == True + assert (not l) == False + + m: f32 + n: f64 + m = f32(0.0) + n = -3.14 + + print(m, n) + print(not m, not n) + assert (not m) == True + assert (not n) == False + +f() diff --git a/src/bin/lpython.cpp b/src/bin/lpython.cpp index 4eca2b4da34..013c89e04f7 100644 --- a/src/bin/lpython.cpp +++ b/src/bin/lpython.cpp @@ -44,6 +44,9 @@ #include #include #endif + +extern std::string lcompilers_unique_ID; + namespace { using LCompilers::endswith; @@ -54,6 +57,7 @@ enum class Backend { llvm, cpp, c, x86, wasm, wasm_x86, wasm_x64 }; + std::string remove_extension(const std::string& filename) { size_t lastdot = filename.find_last_of("."); if (lastdot == std::string::npos) return filename; @@ -1610,6 +1614,9 @@ int main(int argc, char *argv[]) app.require_subcommand(0, 1); CLI11_PARSE(app, argc, argv); + lcompilers_unique_ID = LCompilers::get_unique_ID(); + + if( compiler_options.fast && compiler_options.enable_bounds_checking ) { // ReleaseSafe Mode } else if ( compiler_options.fast ) { diff --git a/src/libasr/ASR.asdl b/src/libasr/ASR.asdl index 86421150164..6703b0229da 100644 --- a/src/libasr/ASR.asdl +++ b/src/libasr/ASR.asdl @@ -322,7 +322,22 @@ expr | OverloadedCompare(expr left, cmpop op, expr right, ttype type, expr? value, expr overloaded) | OverloadedBinOp(expr left, binop op, expr right, ttype type, expr? value, expr overloaded) | OverloadedUnaryMinus(expr arg, ttype type, expr? value, expr overloaded) + -- This Cast changes the value (the bits) of the `arg`: | Cast(expr arg, cast_kind kind, ttype type, expr? value) + -- This ArrayPhysicalCast we only change the physical type, the logical type does not change + -- Note: the "new" physical type here will also be part of the "type" member + -- This allow to represent any combination, but we'll only support a few, at least we need: + -- Maybe it's easier to add an enumeration here: + -- Descriptor -> Pointer + -- Pointer -> Descriptor + + -- CompileTimeFixedSizeArray -> Pointer + -- CompileTimeFixedSizeArray -> Descriptor + -- Descriptor -> NumPy + -- NumPy -> Descriptor + -- ISODescriptor -> Descriptor + -- Descriptor -> ISODescriptor + | ArrayPhysicalCast(expr arg, array_physical_type old, array_physical_type new, ttype type, expr? value) | ComplexRe(expr arg, ttype type, expr? value) | ComplexIm(expr arg, ttype type, expr? value) | DictItem(expr a, expr key, expr? default, ttype type, expr? value) @@ -387,13 +402,19 @@ ttype | CPtr() | SymbolicExpression() | TypeParameter(identifier param) - | Array(ttype type, dimension* dims) + | Array(ttype type, dimension* dims, array_physical_type physical_type) | FunctionType(ttype* arg_types, ttype? return_var_type, abi abi, deftype deftype, string? bindc_name, bool elemental, bool pure, bool module, bool inline, bool static, ttype* type_params, symbol* restrictions, bool is_restriction) -restriction_arg = RestrictionArg(identifier restriction_name, symbol restriction_func) +-- TODO: prefix the enumerators here, improve the names +array_physical_type + = DescriptorArray + | PointerToDataArray + | FixedSizeArray + | NumPyArray + | ISODescriptorArray binop = Add | Sub | Mul | Div | Pow | BitAnd | BitOr | BitXor | BitLShift | BitRShift @@ -429,7 +450,9 @@ cast_kind | IntegerToCharacter | LogicalToCharacter | UnsignedIntegerToInteger + | UnsignedIntegerToUnsignedInteger | UnsignedIntegerToReal + | UnsignedIntegerToLogical | IntegerToUnsignedInteger | RealToUnsignedInteger | CPtrToUnsignedInteger diff --git a/src/libasr/asr_scopes.cpp b/src/libasr/asr_scopes.cpp index acbb50d9c68..ebd3b7c4761 100644 --- a/src/libasr/asr_scopes.cpp +++ b/src/libasr/asr_scopes.cpp @@ -4,6 +4,8 @@ #include #include +std::string lcompilers_unique_ID; + namespace LCompilers { template< typename T > diff --git a/src/libasr/asr_utils.cpp b/src/libasr/asr_utils.cpp index 00dbbeb5400..ec4dcf99b31 100644 --- a/src/libasr/asr_utils.cpp +++ b/src/libasr/asr_utils.cpp @@ -341,12 +341,8 @@ ASR::asr_t* getStructInstanceMember_t(Allocator& al, const Location& loc, } else { LCOMPILERS_ASSERT(ASR::is_a(*member)); ASR::Variable_t* member_variable = ASR::down_cast(member); - ASR::ttype_t* member_type = ASRUtils::type_get_past_allocatable(member_variable->m_type); - bool is_pointer = false; - if (ASRUtils::is_pointer(member_type)) { - is_pointer = true; - member_type = ASR::down_cast(member_type)->m_type; - } + ASR::ttype_t* member_type = ASRUtils::type_get_past_pointer( + ASRUtils::type_get_past_allocatable(member_variable->m_type)); ASR::ttype_t* member_type_ = ASRUtils::type_get_past_array(member_type); ASR::dimension_t* m_dims = nullptr; size_t n_dims = ASRUtils::extract_dimensions_from_ttype(member_type, m_dims); @@ -406,19 +402,20 @@ ASR::asr_t* getStructInstanceMember_t(Allocator& al, const Location& loc, } else if(ASR::is_a(*der_type_sym)) { member_type_ = ASRUtils::TYPE(ASR::make_Struct_t(al, loc, der_type_sym)); } - member_type = member_type_; - if( n_dims > 0 ) { - member_type = ASRUtils::make_Array_t_util(al, loc, - member_type_, m_dims, n_dims); - } + member_type = ASRUtils::make_Array_t_util(al, loc, + member_type_, m_dims, n_dims); break; } default : break; } - if (is_pointer) { - member_type = ASRUtils::TYPE(ASR::make_Pointer_t(al, loc, - ASRUtils::type_get_past_allocatable(member_type))); + + if( ASR::is_a(*member_variable->m_type) ) { + member_type = ASRUtils::TYPE(ASR::make_Allocatable_t(al, + member_variable->base.base.loc, member_type)); + } else if( ASR::is_a(*member_variable->m_type) ) { + member_type = ASRUtils::TYPE(ASR::make_Pointer_t(al, + member_variable->base.base.loc, member_type)); } ASR::symbol_t* member_ext = ASRUtils::import_struct_instance_member(al, member, current_scope, member_type); ASR::expr_t* value = nullptr; @@ -537,7 +534,7 @@ bool use_overloaded(ASR::expr_t* left, ASR::expr_t* right, current_function_dependencies.push_back(al, s2c(al, matched_func_name)); ASRUtils::insert_module_dependency(a_name, al, current_module_dependencies); ASRUtils::set_absent_optional_arguments_to_null(a_args, func, al); - asr = ASR::make_FunctionCall_t(al, loc, a_name, sym, + asr = ASRUtils::make_FunctionCall_t_util(al, loc, a_name, sym, a_args.p, 2, return_type, nullptr, nullptr); @@ -612,14 +609,15 @@ void process_overloaded_unary_minus_function(ASR::symbol_t* proc, ASR::expr_t* o return_type = ASRUtils::TYPE(ASR::make_Struct_t(al, loc, curr_scope->resolve_symbol(ASRUtils::symbol_name(struct_t->m_derived_type)))); if( is_array ) { - return_type = ASRUtils::make_Array_t_util(al, loc, return_type, m_dims, n_dims); + return_type = ASRUtils::make_Array_t_util( + al, loc, return_type, m_dims, n_dims); } } } current_function_dependencies.push_back(al, s2c(al, matched_func_name)); ASRUtils::insert_module_dependency(a_name, al, current_module_dependencies); ASRUtils::set_absent_optional_arguments_to_null(a_args, func, al); - asr = ASR::make_FunctionCall_t(al, loc, a_name, proc, + asr = ASRUtils::make_FunctionCall_t_util(al, loc, a_name, proc, a_args.p, 1, return_type, nullptr, nullptr); @@ -790,7 +788,7 @@ void process_overloaded_assignment_function(ASR::symbol_t* proc, ASR::expr_t* ta current_function_dependencies.push_back(al, s2c(al, matched_subrout_name)); ASRUtils::insert_module_dependency(a_name, al, current_module_dependencies); ASRUtils::set_absent_optional_arguments_to_null(a_args, subrout, al); - asr = ASR::make_SubroutineCall_t(al, loc, a_name, sym, + asr = ASRUtils::make_SubroutineCall_t_util(al, loc, a_name, sym, a_args.p, 2, nullptr); } } @@ -930,7 +928,7 @@ bool use_overloaded(ASR::expr_t* left, ASR::expr_t* right, current_function_dependencies.push_back(al, s2c(al, matched_func_name)); ASRUtils::insert_module_dependency(a_name, al, current_module_dependencies); ASRUtils::set_absent_optional_arguments_to_null(a_args, func, al); - asr = ASR::make_FunctionCall_t(al, loc, a_name, sym, + asr = ASRUtils::make_FunctionCall_t_util(al, loc, a_name, sym, a_args.p, 2, return_type, nullptr, nullptr); @@ -1129,14 +1127,14 @@ ASR::asr_t* symbol_resolve_external_generic_procedure_without_eval( if( func ) { ASRUtils::set_absent_optional_arguments_to_null(args, func, al); } - return ASR::make_SubroutineCall_t(al, loc, final_sym, + return ASRUtils::make_SubroutineCall_t_util(al, loc, final_sym, v, args.p, args.size(), nullptr); } else { if( func ) { ASRUtils::set_absent_optional_arguments_to_null(args, func, al); } - return ASR::make_FunctionCall_t(al, loc, final_sym, + return ASRUtils::make_FunctionCall_t_util(al, loc, final_sym, v, args.p, args.size(), return_type, nullptr, nullptr); diff --git a/src/libasr/asr_utils.h b/src/libasr/asr_utils.h index 8f443441cb2..683b4ea4fdf 100644 --- a/src/libasr/asr_utils.h +++ b/src/libasr/asr_utils.h @@ -82,6 +82,17 @@ static inline const ASR::symbol_t *symbol_get_past_external(const ASR::symbol_t } } +static inline ASR::ttype_t *type_get_past_const(ASR::ttype_t *f) +{ + if (ASR::is_a(*f)) { + ASR::Const_t *e = ASR::down_cast(f); + LCOMPILERS_ASSERT(!ASR::is_a(*e->m_type)); + return e->m_type; + } else { + return f; + } +} + static inline ASR::ttype_t *type_get_past_pointer(ASR::ttype_t *f) { if (ASR::is_a(*f)) { @@ -115,14 +126,44 @@ static inline ASR::ttype_t *type_get_past_array(ASR::ttype_t *f) } } -static inline ASR::ttype_t *type_get_past_const(ASR::ttype_t *f) -{ - if (ASR::is_a(*f)) { - ASR::Const_t *e = ASR::down_cast(f); - LCOMPILERS_ASSERT(!ASR::is_a(*e->m_type)); - return e->m_type; - } else { - return f; +static inline int extract_kind_from_ttype_t(const ASR::ttype_t* type) { + if (type == nullptr) { + return -1; + } + switch (type->type) { + case ASR::ttypeType::Array: { + return extract_kind_from_ttype_t(ASR::down_cast(type)->m_type); + } + case ASR::ttypeType::Integer : { + return ASR::down_cast(type)->m_kind; + } + case ASR::ttypeType::UnsignedInteger : { + return ASR::down_cast(type)->m_kind; + } + case ASR::ttypeType::Real : { + return ASR::down_cast(type)->m_kind; + } + case ASR::ttypeType::Complex: { + return ASR::down_cast(type)->m_kind; + } + case ASR::ttypeType::Character: { + return ASR::down_cast(type)->m_kind; + } + case ASR::ttypeType::Logical: { + return ASR::down_cast(type)->m_kind; + } + case ASR::ttypeType::Pointer: { + return extract_kind_from_ttype_t(ASR::down_cast(type)->m_type); + } + case ASR::ttypeType::Allocatable: { + return extract_kind_from_ttype_t(ASR::down_cast(type)->m_type); + } + case ASR::ttypeType::Const: { + return extract_kind_from_ttype_t(ASR::down_cast(type)->m_type); + } + default : { + return -1; + } } } @@ -228,6 +269,23 @@ static inline ASR::ttype_t* get_contained_type(ASR::ttype_t* asr_type) { } } +static inline ASR::array_physical_typeType extract_physical_type(ASR::ttype_t* e) { + switch( e->type ) { + case ASR::ttypeType::Array: { + return ASR::down_cast(e)->m_physical_type; + } + case ASR::ttypeType::Pointer: { + return extract_physical_type(ASRUtils::type_get_past_pointer(e)); + } + case ASR::ttypeType::Allocatable: { + return extract_physical_type(ASRUtils::type_get_past_allocatable(e)); + } + default: + throw LCompilersException("Cannot extract the physical type of " + + std::to_string(e->type) + " type."); + } +} + static inline ASR::abiType expr_abi(ASR::expr_t* e) { switch( e->type ) { case ASR::exprType::Var: { @@ -773,6 +831,9 @@ static inline bool is_value_constant(ASR::expr_t *a_value) { } else if(ASR::is_a(*a_value)) { ASR::ArrayReshape_t* array_reshape = ASR::down_cast(a_value); return is_value_constant(array_reshape->m_array) && is_value_constant(array_reshape->m_shape); + } else if(ASR::is_a(*a_value)) { + ASR::ArrayPhysicalCast_t* array_physical_t = ASR::down_cast(a_value); + return is_value_constant(array_physical_t->m_arg); } else if( ASR::is_a(*a_value) ) { ASR::StructTypeConstructor_t* struct_type_constructor = ASR::down_cast(a_value); @@ -912,7 +973,7 @@ static inline bool all_args_evaluated(const Vec &args) { static inline std::string get_mangled_name(ASR::Module_t* module, std::string symbol_name) { std::string module_name = module->m_name; if( module_name == symbol_name ) { - return "__" + module_name + "_" + symbol_name; + return "__" + std::string(module->m_name) + "_" + symbol_name; } else { return symbol_name; } @@ -1004,9 +1065,9 @@ static inline std::string type_python_1dim_helper(const std::string & res, } if( ASRUtils::expr_value(e->m_length) ) { - int64_t length_dim = -1; + int64_t length_dim = 0; ASRUtils::extract_value(ASRUtils::expr_value(e->m_length), length_dim); - return res + "[" + std::to_string(length_dim + 1) + "]"; + return res + "[" + std::to_string(length_dim) + "]"; } return res; @@ -1269,15 +1330,15 @@ static inline std::string type_to_str_python(const ASR::ttype_t *t, } case ASR::ttypeType::Struct: { ASR::Struct_t* d = ASR::down_cast(t); - return std::string(symbol_name(d->m_derived_type)); + return "struct " + std::string(symbol_name(d->m_derived_type)); } case ASR::ttypeType::Enum: { ASR::Enum_t* d = ASR::down_cast(t); - return std::string(symbol_name(d->m_enum_type)); + return "enum " + std::string(symbol_name(d->m_enum_type)); } case ASR::ttypeType::Union: { ASR::Union_t* d = ASR::down_cast(t); - return std::string(symbol_name(d->m_union_type)); + return "union " + std::string(symbol_name(d->m_union_type)); } case ASR::ttypeType::Pointer: { ASR::Pointer_t* p = ASR::down_cast(t); @@ -1494,47 +1555,6 @@ bool use_overloaded_assignment(ASR::expr_t* target, ASR::expr_t* value, void set_intrinsic(ASR::symbol_t* sym); -static inline int extract_kind_from_ttype_t(const ASR::ttype_t* type) { - if (type == nullptr) { - return -1; - } - switch (type->type) { - case ASR::ttypeType::Array: { - return extract_kind_from_ttype_t(ASR::down_cast(type)->m_type); - } - case ASR::ttypeType::Integer : { - return ASR::down_cast(type)->m_kind; - } - case ASR::ttypeType::UnsignedInteger : { - return ASR::down_cast(type)->m_kind; - } - case ASR::ttypeType::Real : { - return ASR::down_cast(type)->m_kind; - } - case ASR::ttypeType::Complex: { - return ASR::down_cast(type)->m_kind; - } - case ASR::ttypeType::Character: { - return ASR::down_cast(type)->m_kind; - } - case ASR::ttypeType::Logical: { - return ASR::down_cast(type)->m_kind; - } - case ASR::ttypeType::Pointer: { - return extract_kind_from_ttype_t(ASR::down_cast(type)->m_type); - } - case ASR::ttypeType::Allocatable: { - return extract_kind_from_ttype_t(ASR::down_cast(type)->m_type); - } - case ASR::ttypeType::Const: { - return extract_kind_from_ttype_t(ASR::down_cast(type)->m_type); - } - default : { - return -1; - } - } -} - static inline bool is_pointer(ASR::ttype_t *x) { return ASR::is_a(*x); } @@ -1730,19 +1750,54 @@ inline int extract_n_dims_from_ttype(ASR::ttype_t *x) { return extract_dimensions_from_ttype(x, m_dims_temp); } +static inline bool is_dimension_empty(ASR::dimension_t& dim) { + return ((dim.m_length == nullptr) || + (dim.m_start == nullptr)); +} + +static inline bool is_dimension_empty(ASR::dimension_t* dims, size_t n) { + for( size_t i = 0; i < n; i++ ) { + if( is_dimension_empty(dims[i]) ) { + return true; + } + } + return false; +} + inline ASR::ttype_t* make_Array_t_util(Allocator& al, const Location& loc, - ASR::ttype_t* type, ASR::dimension_t* m_dims, size_t n_dims) { + ASR::ttype_t* type, ASR::dimension_t* m_dims, size_t n_dims, + ASR::abiType abi=ASR::abiType::Source, bool is_argument=false, + ASR::array_physical_typeType physical_type=ASR::array_physical_typeType::DescriptorArray, + bool override_physical_type=false) { if( n_dims == 0 ) { return type; } - return ASRUtils::TYPE(ASR::make_Array_t(al, loc, type, m_dims, n_dims)); + + if( !override_physical_type ) { + if( abi == ASR::abiType::BindC ) { + physical_type = ASR::array_physical_typeType::PointerToDataArray; + } else { + if( ASRUtils::is_fixed_size_array(m_dims, n_dims) ) { + if( is_argument ) { + physical_type = ASR::array_physical_typeType::PointerToDataArray; + } else { + physical_type = ASR::array_physical_typeType::FixedSizeArray; + } + } else if( !ASRUtils::is_dimension_empty(m_dims, n_dims) ) { + physical_type = ASR::array_physical_typeType::PointerToDataArray; + } + } + } + return ASRUtils::TYPE(ASR::make_Array_t( + al, loc, type, m_dims, n_dims, physical_type)); } // Sets the dimension member of `ttype_t`. Returns `true` if dimensions set. // Returns `false` if the `ttype_t` does not have a dimension member. inline bool ttype_set_dimensions(ASR::ttype_t** x, ASR::dimension_t *m_dims, int64_t n_dims, - Allocator& al) { + Allocator& al, ASR::abiType abi=ASR::abiType::Source, + bool is_argument=false) { switch ((*x)->type) { case ASR::ttypeType::Array: { ASR::Array_t* array_t = ASR::down_cast(*x); @@ -1768,7 +1823,8 @@ inline bool ttype_set_dimensions(ASR::ttype_t** x, case ASR::ttypeType::Enum: case ASR::ttypeType::Union: case ASR::ttypeType::TypeParameter: { - *x = ASRUtils::make_Array_t_util(al, (*x)->base.loc, *x, m_dims, n_dims); + *x = ASRUtils::make_Array_t_util(al, + (*x)->base.loc, *x, m_dims, n_dims, abi, is_argument); return true; } default: @@ -1797,7 +1853,9 @@ static inline bool is_aggregate_type(ASR::ttype_t* asr_type) { static inline ASR::dimension_t* duplicate_dimensions(Allocator& al, ASR::dimension_t* m_dims, size_t n_dims); static inline ASR::ttype_t* duplicate_type(Allocator& al, const ASR::ttype_t* t, - Vec* dims = nullptr) { + Vec* dims=nullptr, + ASR::array_physical_typeType physical_type=ASR::array_physical_typeType::DescriptorArray, + bool override_physical_type=false) { size_t dimsn = 0; ASR::dimension_t* dimsp = nullptr; if (dims != nullptr) { @@ -1814,7 +1872,8 @@ static inline ASR::ttype_t* duplicate_type(Allocator& al, const ASR::ttype_t* t, dimsn = tnew->n_dims; } return ASRUtils::make_Array_t_util(al, tnew->base.base.loc, - duplicated_element_type, dimsp, dimsn); + duplicated_element_type, dimsp, dimsn, ASR::abiType::Source, + false, physical_type, override_physical_type); } case ASR::ttypeType::Integer: { ASR::Integer_t* tnew = ASR::down_cast(t); @@ -1859,13 +1918,23 @@ static inline ASR::ttype_t* duplicate_type(Allocator& al, const ASR::ttype_t* t, } case ASR::ttypeType::Pointer: { ASR::Pointer_t* ptr = ASR::down_cast(t); - ASR::ttype_t* dup_type = duplicate_type(al, ptr->m_type, dims); + ASR::ttype_t* dup_type = duplicate_type(al, ptr->m_type, dims, + physical_type, override_physical_type); + if( override_physical_type && + physical_type == ASR::array_physical_typeType::FixedSizeArray ) { + return dup_type; + } return ASRUtils::TYPE(ASR::make_Pointer_t(al, ptr->base.base.loc, ASRUtils::type_get_past_allocatable(dup_type))); } case ASR::ttypeType::Allocatable: { ASR::Allocatable_t* alloc_ = ASR::down_cast(t); - ASR::ttype_t* dup_type = duplicate_type(al, alloc_->m_type, dims); + ASR::ttype_t* dup_type = duplicate_type(al, alloc_->m_type, dims, + physical_type, override_physical_type); + if( override_physical_type && + physical_type == ASR::array_physical_typeType::FixedSizeArray ) { + return dup_type; + } return ASRUtils::TYPE(ASR::make_Allocatable_t(al, alloc_->base.base.loc, ASRUtils::type_get_past_allocatable(dup_type))); } @@ -1879,6 +1948,19 @@ static inline ASR::ttype_t* duplicate_type(Allocator& al, const ASR::ttype_t* t, return ASRUtils::TYPE(ASR::make_Const_t(al, c->base.base.loc, dup_type)); } + case ASR::ttypeType::List: { + ASR::List_t* l = ASR::down_cast(t); + ASR::ttype_t* dup_type = duplicate_type(al, l->m_type); + return ASRUtils::TYPE(ASR::make_List_t(al, l->base.base.loc, + dup_type)); + } + case ASR::ttypeType::Dict: { + ASR::Dict_t* d = ASR::down_cast(t); + ASR::ttype_t* dup_key_type = duplicate_type(al, d->m_key_type); + ASR::ttype_t* dup_value_type = duplicate_type(al, d->m_value_type); + return ASRUtils::TYPE(ASR::make_Dict_t(al, d->base.base.loc, + dup_key_type, dup_value_type)); + } case ASR::ttypeType::TypeParameter: { ASR::TypeParameter_t* tp = ASR::down_cast(t); //return ASRUtils::TYPE(ASR::make_TypeParameter_t(al, t->base.loc, @@ -1892,7 +1974,8 @@ static inline ASR::ttype_t* duplicate_type(Allocator& al, const ASR::ttype_t* t, Vec arg_types; arg_types.reserve(al, ft->n_arg_types); for( size_t i = 0; i < ft->n_arg_types; i++ ) { - ASR::ttype_t *t = ASRUtils::duplicate_type(al, ft->m_arg_types[i]); + ASR::ttype_t *t = ASRUtils::duplicate_type(al, ft->m_arg_types[i], + nullptr, physical_type, override_physical_type); arg_types.push_back(al, t); } return ASRUtils::TYPE(ASR::make_FunctionType_t(al, ft->base.base.loc, @@ -1904,7 +1987,10 @@ static inline ASR::ttype_t* duplicate_type(Allocator& al, const ASR::ttype_t* t, default : throw LCompilersException("Not implemented " + std::to_string(t->type)); } LCOMPILERS_ASSERT(t_ != nullptr); - return ASRUtils::make_Array_t_util(al, t_->base.loc, t_, dimsp, dimsn); + return ASRUtils::make_Array_t_util( + al, t_->base.loc, t_, dimsp, dimsn, + ASR::abiType::Source, false, physical_type, + override_physical_type); } static inline void set_absent_optional_arguments_to_null( @@ -1927,7 +2013,9 @@ static inline void set_absent_optional_arguments_to_null( LCOMPILERS_ASSERT(args.size() == (func->n_args - offset)); } -static inline ASR::ttype_t* duplicate_type_with_empty_dims(Allocator& al, ASR::ttype_t* t) { +static inline ASR::ttype_t* duplicate_type_with_empty_dims(Allocator& al, ASR::ttype_t* t, + ASR::array_physical_typeType physical_type=ASR::array_physical_typeType::DescriptorArray, + bool override_physical_type=false) { size_t n_dims = ASRUtils::extract_n_dims_from_ttype(t); Vec empty_dims; empty_dims.reserve(al, n_dims); @@ -1938,7 +2026,7 @@ static inline ASR::ttype_t* duplicate_type_with_empty_dims(Allocator& al, ASR::t empty_dim.m_length = nullptr; empty_dims.push_back(al, empty_dim); } - return duplicate_type(al, t, &empty_dims); + return duplicate_type(al, t, &empty_dims, physical_type, override_physical_type); } static inline ASR::ttype_t* duplicate_type_without_dims(Allocator& al, const ASR::ttype_t* t, const Location& loc) { @@ -2022,7 +2110,6 @@ inline int extract_kind_str(char* m_n, char *&kind_str) { while (*p != '\0') { if (*p == '_') { p++; - std::string kind = std::string(p); int ikind = std::atoi(p); if (ikind == 0) { // Not an integer, return a string @@ -2517,20 +2604,6 @@ ASR::asr_t* symbol_resolve_external_generic_procedure_without_eval( SymbolTable* current_scope, Allocator& al, const std::function err); -static inline bool is_dimension_empty(ASR::dimension_t& dim) { - return ((dim.m_length == nullptr) || - (dim.m_start == nullptr)); -} - -static inline bool is_dimension_empty(ASR::dimension_t* dims, size_t n) { - for( size_t i = 0; i < n; i++ ) { - if( is_dimension_empty(dims[i]) ) { - return true; - } - } - return false; -} - static inline ASR::intentType symbol_intent(const ASR::symbol_t *f) { switch( f->type ) { @@ -2602,6 +2675,7 @@ static inline ASR::ttype_t* get_type_parameter(ASR::ttype_t* t) { static inline ASR::symbol_t* import_struct_instance_member(Allocator& al, ASR::symbol_t* v, SymbolTable* scope, ASR::ttype_t*& mem_type) { + ASR::ttype_t* mem_type_ = mem_type; v = ASRUtils::symbol_get_past_external(v); ASR::symbol_t* struct_t = ASRUtils::get_asr_owner(v); std::string v_name = ASRUtils::symbol_name(v); @@ -2642,7 +2716,6 @@ static inline ASR::symbol_t* import_struct_instance_member(Allocator& al, ASR::s ASR::dimension_t* m_dims = nullptr; size_t n_dims = ASRUtils::extract_dimensions_from_ttype(mem_type, m_dims); - bool is_pointer = ASRUtils::is_pointer(mem_type); mem_type = ASRUtils::type_get_past_array( ASRUtils::type_get_past_pointer( ASRUtils::type_get_past_allocatable(mem_type))); @@ -2667,11 +2740,18 @@ static inline ASR::symbol_t* import_struct_instance_member(Allocator& al, ASR::s } } if( n_dims > 0 ) { - mem_type = ASRUtils::make_Array_t_util(al, mem_type->base.loc, mem_type, m_dims, n_dims); + mem_type = ASRUtils::make_Array_t_util( + al, mem_type->base.loc, mem_type, m_dims, n_dims); } - if( is_pointer ) { - mem_type = ASRUtils::TYPE(ASR::make_Pointer_t(al, mem_type->base.loc, mem_type)); + + if( ASR::is_a(*mem_type_) ) { + mem_type = ASRUtils::TYPE(ASR::make_Allocatable_t(al, + mem_type->base.loc, mem_type)); + } else if( ASR::is_a(*mem_type_) ) { + mem_type = ASRUtils::TYPE(ASR::make_Pointer_t(al, + mem_type->base.loc, mem_type)); } + return scope->get_symbol(v_ext_name); } @@ -2726,14 +2806,16 @@ class ReplaceArgVisitor: public ASR::BaseExprReplacer { Vec& orig_args; SetChar& current_function_dependencies; + SetChar& current_module_dependencies; public: ReplaceArgVisitor(Allocator& al_, SymbolTable* current_scope_, ASR::Function_t* orig_func_, Vec& orig_args_, - SetChar& current_function_dependencies_) : + SetChar& current_function_dependencies_, SetChar& current_module_dependencies_) : al(al_), current_scope(current_scope_), orig_func(orig_func_), - orig_args(orig_args_), current_function_dependencies(current_function_dependencies_) + orig_args(orig_args_), current_function_dependencies(current_function_dependencies_), + current_module_dependencies(current_module_dependencies_) {} void replace_FunctionCall(ASR::FunctionCall_t* x) { @@ -2804,13 +2886,13 @@ class ReplaceArgVisitor: public ASR::BaseExprReplacer { break; } current_function_dependencies.push_back(al, ASRUtils::symbol_name(new_es)); + ASRUtils::insert_module_dependency(new_es, al, current_module_dependencies); x->m_name = new_es; } void replace_Var(ASR::Var_t* x) { size_t arg_idx = 0; bool idx_found = false; - std::string arg_name = ASRUtils::symbol_name(x->m_v); // Finds the index of the argument to be used for substitution // Basically if we are calling maybe(string, ret_type=character(len=len(s))) // where string is a variable in current scope and s is one of the arguments @@ -2819,10 +2901,8 @@ class ReplaceArgVisitor: public ASR::BaseExprReplacer { // maybe(string, ret_type=character(len=len(string))) for( size_t j = 0; j < orig_func->n_args && !idx_found; j++ ) { if( ASR::is_a(*(orig_func->m_args[j])) ) { - std::string arg_name_2 = std::string(ASRUtils::symbol_name( - ASR::down_cast(orig_func->m_args[j])->m_v)); arg_idx = j; - idx_found = arg_name_2 == arg_name; + idx_found = ASR::down_cast(orig_func->m_args[j])->m_v == x->m_v; } } if( idx_found ) { @@ -2905,14 +2985,12 @@ class ReplaceWithFunctionParamVisitor: public ASR::BaseExprReplacer arg_types; arg_types.reserve(al, n_args); ReplaceWithFunctionParamVisitor replacer(al, a_args, n_args); @@ -2924,19 +3002,43 @@ inline ASR::asr_t* make_Function_t_util(Allocator& al, const Location& loc, arg_types.push_back(al, t); } ASR::ttype_t* return_var_type = nullptr; - if( m_return_var ) { + if( a_return_var ) { return_var_type = replacer.replace_args_with_FunctionParam( - ASRUtils::expr_type(m_return_var)); + ASRUtils::expr_type(a_return_var)); } - ASR::ttype_t* func_type = ASRUtils::TYPE(ASR::make_FunctionType_t( - al, loc, arg_types.p, arg_types.size(), return_var_type, m_abi, - m_deftype, m_bindc_name, m_elemental, m_pure, m_module, m_inline, - m_static, m_type_params, n_type_params, m_restrictions, n_restrictions, - m_is_restriction)); + + LCOMPILERS_ASSERT(arg_types.size() == n_args); + return ASR::make_FunctionType_t( + al, a_loc, arg_types.p, arg_types.size(), return_var_type, a_abi, a_deftype, + a_bindc_name, a_elemental, a_pure, a_module, a_inline, + a_static, a_type_params, n_type_params, a_restrictions, n_restrictions, + a_is_restriction); +} + +inline ASR::asr_t* make_FunctionType_t_util(Allocator &al, const Location &a_loc, + ASR::expr_t** a_args, size_t n_args, ASR::expr_t* a_return_var, ASR::FunctionType_t* ft) { + return ASRUtils::make_FunctionType_t_util(al, a_loc, a_args, n_args, a_return_var, + ft->m_abi, ft->m_deftype, ft->m_bindc_name, ft->m_elemental, ft->m_pure, ft->m_module, + ft->m_inline, ft->m_static, ft->m_type_params, ft->n_type_params, ft->m_restrictions, + ft->n_restrictions, ft->m_is_restriction); +} + +inline ASR::asr_t* make_Function_t_util(Allocator& al, const Location& loc, + SymbolTable* m_symtab, char* m_name, char** m_dependencies, size_t n_dependencies, + ASR::expr_t** a_args, size_t n_args, ASR::stmt_t** m_body, size_t n_body, + ASR::expr_t* m_return_var, ASR::abiType m_abi, ASR::accessType m_access, + ASR::deftypeType m_deftype, char* m_bindc_name, bool m_elemental, bool m_pure, + bool m_module, bool m_inline, bool m_static, ASR::ttype_t** m_type_params, size_t n_type_params, + ASR::symbol_t** m_restrictions, size_t n_restrictions, bool m_is_restriction, bool m_deterministic, + bool m_side_effect_free, char *m_c_header=nullptr) { + ASR::ttype_t* func_type = ASRUtils::TYPE(ASRUtils::make_FunctionType_t_util( + al, loc, a_args, n_args, m_return_var, m_abi, m_deftype, m_bindc_name, + m_elemental, m_pure, m_module, m_inline, m_static, m_type_params, n_type_params, + m_restrictions, n_restrictions, m_is_restriction)); return ASR::make_Function_t( al, loc, m_symtab, m_name, func_type, m_dependencies, n_dependencies, a_args, n_args, m_body, n_body, m_return_var, m_access, m_deterministic, - m_side_effect_free, m_module_file); + m_side_effect_free, m_c_header); } class SymbolDuplicator { @@ -3113,28 +3215,6 @@ class SymbolDuplicator { ASR::FunctionType_t* function_type = ASRUtils::get_FunctionType(function); - Vec new_ttypes; - new_ttypes.reserve(al, function_type->n_type_params); - for( size_t i = 0; i < function_type->n_type_params; i++ ) { - node_duplicator.success = true; - ASR::ttype_t* new_ttype = node_duplicator.duplicate_ttype(function_type->m_type_params[i]); - if( !node_duplicator.success ) { - return nullptr; - } - new_ttypes.push_back(al, new_ttype); - } - - Vec new_restrictions; - new_restrictions.reserve(al, function_type->n_restrictions); - for( size_t i = 0; i < function_type->n_restrictions; i++ ) { - std::string restriction_name = ASRUtils::symbol_name(function_type->m_restrictions[i]); - ASR::symbol_t* new_restriction = function_symtab->resolve_symbol(restriction_name); - if( !new_restriction ) { - throw LCompilersException("Symbol " + restriction_name + " not found."); - } - new_restrictions.push_back(al, new_restriction); - } - return ASR::down_cast(make_Function_t_util(al, function->base.base.loc, function_symtab, function->m_name, function->m_dependencies, function->n_dependencies, new_args.p, @@ -3142,7 +3222,8 @@ class SymbolDuplicator { function_type->m_abi, function->m_access, function_type->m_deftype, function_type->m_bindc_name, function_type->m_elemental, function_type->m_pure, function_type->m_module, function_type->m_inline, function_type->m_static, - new_ttypes.p, new_ttypes.size(), new_restrictions.p, new_restrictions.size(), + function_type->m_type_params, function_type->n_type_params, + function_type->m_restrictions, function_type->n_restrictions, function_type->m_is_restriction, function->m_deterministic, function->m_side_effect_free)); } @@ -3418,8 +3499,8 @@ static inline bool is_pass_array_by_data_possible(ASR::Function_t* x, std::vecto argi->m_intent == ASRUtils::intent_out || argi->m_intent == ASRUtils::intent_inout) && !ASR::is_a(*argi->m_type) && - !ASR::is_a(*ASRUtils::type_get_past_array(argi->m_type)) && - !ASRUtils::is_character(*argi->m_type)) { + !ASR::is_a(*argi->m_type) && + !ASR::is_a(*argi->m_type)) { v.push_back(i); } } @@ -3475,17 +3556,27 @@ static inline ASR::expr_t* get_bound(ASR::expr_t* arr_expr, int dim, int32_type, bound_type, bound_value)); } +static inline ASR::asr_t* make_ArraySize_t_util( + Allocator &al, const Location &a_loc, ASR::expr_t* a_v, + ASR::expr_t* a_dim, ASR::ttype_t* a_type, ASR::expr_t* a_value) { + if( ASR::is_a(*a_v) ) { + a_v = ASR::down_cast(a_v)->m_arg; + } + + return ASR::make_ArraySize_t(al, a_loc, a_v, a_dim, a_type, a_value); +} + static inline ASR::expr_t* get_size(ASR::expr_t* arr_expr, int dim, Allocator& al) { ASR::ttype_t* int32_type = ASRUtils::TYPE(ASR::make_Integer_t(al, arr_expr->base.loc, 4)); ASR::expr_t* dim_expr = ASRUtils::EXPR(ASR::make_IntegerConstant_t(al, arr_expr->base.loc, dim, int32_type)); - return ASRUtils::EXPR(ASR::make_ArraySize_t(al, arr_expr->base.loc, arr_expr, dim_expr, + return ASRUtils::EXPR(ASRUtils::make_ArraySize_t_util(al, arr_expr->base.loc, arr_expr, dim_expr, int32_type, nullptr)); } static inline ASR::expr_t* get_size(ASR::expr_t* arr_expr, Allocator& al) { ASR::ttype_t* int32_type = ASRUtils::TYPE(ASR::make_Integer_t(al, arr_expr->base.loc, 4)); - return ASRUtils::EXPR(ASR::make_ArraySize_t(al, arr_expr->base.loc, arr_expr, nullptr, int32_type, nullptr)); + return ASRUtils::EXPR(ASRUtils::make_ArraySize_t_util(al, arr_expr->base.loc, arr_expr, nullptr, int32_type, nullptr)); } static inline void get_dimensions(ASR::expr_t* array, Vec& dims, @@ -3705,6 +3796,173 @@ static inline bool is_allocatable(ASR::expr_t* expr) { return ASR::is_a(*ASRUtils::expr_type(expr)); } +static inline ASR::asr_t* make_ArrayPhysicalCast_t_util(Allocator &al, const Location &a_loc, + ASR::expr_t* a_arg, ASR::array_physical_typeType a_old, ASR::array_physical_typeType a_new, + ASR::ttype_t* a_type, ASR::expr_t* a_value) { + if( ASR::is_a(*a_arg) ) { + ASR::ArrayPhysicalCast_t* a_arg_ = ASR::down_cast(a_arg); + a_arg = a_arg_->m_arg; + a_old = ASRUtils::extract_physical_type(ASRUtils::expr_type(a_arg_->m_arg)); + } + + LCOMPILERS_ASSERT(ASRUtils::extract_physical_type(ASRUtils::expr_type(a_arg)) == a_old); + + return ASR::make_ArrayPhysicalCast_t(al, a_loc, a_arg, a_old, a_new, a_type, a_value); +} + +static inline void Call_t_body(Allocator& al, ASR::symbol_t* a_name, + ASR::call_arg_t* a_args, size_t n_args, ASR::expr_t* a_dt) { + bool is_method = a_dt != nullptr; + ASR::symbol_t* a_name_ = ASRUtils::symbol_get_past_external(a_name); + ASR::FunctionType_t* func_type = nullptr; + if( ASR::is_a(*a_name_) ) { + func_type = ASR::down_cast( + ASR::down_cast(a_name_)->m_function_signature); + } else if( ASR::is_a(*a_name_) ) { + func_type = ASR::down_cast( + ASR::down_cast(a_name_)->m_type); + } else if( ASR::is_a(*a_name_) ) { + ASR::Function_t* func = ASR::down_cast( + ASRUtils::symbol_get_past_external( + ASR::down_cast(a_name_)->m_proc)); + func_type = ASR::down_cast(func->m_function_signature); + } else { + LCOMPILERS_ASSERT(false); + } + + for( size_t i = 0; i < n_args; i++ ) { + if( a_args[i].m_value == nullptr || + ASR::is_a(*a_args[i].m_value) ) { + continue; + } + ASR::expr_t* arg = a_args[i].m_value; + ASR::ttype_t* arg_type = ASRUtils::type_get_past_allocatable( + ASRUtils::type_get_past_pointer(ASRUtils::expr_type(arg))); + ASR::ttype_t* orig_arg_type = ASRUtils::type_get_past_allocatable( + ASRUtils::type_get_past_pointer(func_type->m_arg_types[i + is_method])); + if( !ASRUtils::is_intrinsic_symbol(a_name_) && + !(ASR::is_a(*ASRUtils::type_get_past_array(arg_type)) || + ASR::is_a(*ASRUtils::type_get_past_array(orig_arg_type))) && + !(ASR::is_a(*ASRUtils::type_get_past_array(arg_type)) || + ASR::is_a(*ASRUtils::type_get_past_array(orig_arg_type))) && + a_dt == nullptr ) { /*TODO: Remove this if check one intrinsic procedures are implemented correctly*/ + LCOMPILERS_ASSERT_MSG( ASRUtils::check_equal_type(arg_type, orig_arg_type), + "ASRUtils::check_equal_type(" + ASRUtils::get_type_code(arg_type) + ", " + + ASRUtils::get_type_code(orig_arg_type) + ")"); + } + if( ASRUtils::is_array(arg_type) && ASRUtils::is_array(orig_arg_type) ) { + ASR::Array_t* arg_array_t = ASR::down_cast(ASRUtils::type_get_past_const(arg_type)); + ASR::Array_t* orig_arg_array_t = ASR::down_cast(ASRUtils::type_get_past_const(orig_arg_type)); + if( arg_array_t->m_physical_type != orig_arg_array_t->m_physical_type ) { + ASR::call_arg_t physical_cast_arg; + physical_cast_arg.loc = arg->base.loc; + Vec* dimensions = nullptr; + Vec dimension_; + if( ASRUtils::is_fixed_size_array(orig_arg_array_t->m_dims, orig_arg_array_t->n_dims) ) { + dimension_.reserve(al, orig_arg_array_t->n_dims); + dimension_.from_pointer_n_copy(al, orig_arg_array_t->m_dims, orig_arg_array_t->n_dims); + dimensions = &dimension_; + } + + physical_cast_arg.m_value = ASRUtils::EXPR(ASRUtils::make_ArrayPhysicalCast_t_util( + al, arg->base.loc, arg, arg_array_t->m_physical_type, orig_arg_array_t->m_physical_type, + ASRUtils::duplicate_type(al, ASRUtils::expr_type(arg), dimensions, orig_arg_array_t->m_physical_type, true), + nullptr)); + a_args[i] = physical_cast_arg; + } + } + } +} + +static inline ASR::asr_t* make_FunctionCall_t_util( + Allocator &al, const Location &a_loc, ASR::symbol_t* a_name, + ASR::symbol_t* a_original_name, ASR::call_arg_t* a_args, size_t n_args, + ASR::ttype_t* a_type, ASR::expr_t* a_value, ASR::expr_t* a_dt) { + + Call_t_body(al, a_name, a_args, n_args, a_dt); + + return ASR::make_FunctionCall_t(al, a_loc, a_name, a_original_name, + a_args, n_args, a_type, a_value, a_dt); +} + +static inline ASR::asr_t* make_SubroutineCall_t_util( + Allocator &al, const Location &a_loc, ASR::symbol_t* a_name, + ASR::symbol_t* a_original_name, ASR::call_arg_t* a_args, size_t n_args, + ASR::expr_t* a_dt) { + + Call_t_body(al, a_name, a_args, n_args, a_dt); + + return ASR::make_SubroutineCall_t(al, a_loc, a_name, a_original_name, + a_args, n_args, a_dt); +} + +static inline ASR::expr_t* cast_to_descriptor(Allocator& al, ASR::expr_t* arg) { + ASR::ttype_t* arg_type = ASRUtils::expr_type(arg); + ASR::Array_t* arg_array_t = ASR::down_cast( + ASRUtils::type_get_past_pointer( + ASRUtils::type_get_past_allocatable(arg_type))); + if( arg_array_t->m_physical_type != ASR::array_physical_typeType::DescriptorArray ) { + return ASRUtils::EXPR(ASRUtils::make_ArrayPhysicalCast_t_util( + al, arg->base.loc, arg, arg_array_t->m_physical_type, + ASR::array_physical_typeType::DescriptorArray, + ASRUtils::duplicate_type(al, ASRUtils::expr_type(arg), + nullptr, ASR::array_physical_typeType::DescriptorArray, true), + nullptr)); + } + return arg; +} + +static inline ASR::asr_t* make_IntrinsicFunction_t_util( + Allocator &al, const Location &a_loc, int64_t a_intrinsic_id, + ASR::expr_t** a_args, size_t n_args, int64_t a_overload_id, + ASR::ttype_t* a_type, ASR::expr_t* a_value) { + + for( size_t i = 0; i < n_args; i++ ) { + if( a_args[i] == nullptr || + ASR::is_a(*a_args[i]) ) { + continue; + } + ASR::expr_t* arg = a_args[i]; + ASR::ttype_t* arg_type = ASRUtils::type_get_past_allocatable( + ASRUtils::type_get_past_pointer(ASRUtils::expr_type(arg))); + + if( ASRUtils::is_array(arg_type) ) { + a_args[i] = cast_to_descriptor(al, arg); + } + } + + return ASR::make_IntrinsicFunction_t(al, a_loc, a_intrinsic_id, + a_args, n_args, a_overload_id, a_type, a_value); +} + +static inline ASR::asr_t* make_Associate_t_util( + Allocator &al, const Location &a_loc, + ASR::expr_t* a_target, ASR::expr_t* a_value) { + ASR::ttype_t* target_type = ASRUtils::expr_type(a_target); + ASR::ttype_t* value_type = ASRUtils::expr_type(a_value); + if( ASRUtils::is_array(target_type) && ASRUtils::is_array(value_type) ) { + ASR::array_physical_typeType target_ptype = ASRUtils::extract_physical_type(target_type); + ASR::array_physical_typeType value_ptype = ASRUtils::extract_physical_type(value_type); + if( target_ptype != value_ptype ) { + a_value = ASRUtils::EXPR(ASRUtils::make_ArrayPhysicalCast_t_util(al, a_loc, a_value, + value_ptype, target_ptype, ASRUtils::duplicate_type(al, + value_type, nullptr, target_ptype, true), nullptr)); + } + } + return ASR::make_Associate_t(al, a_loc, a_target, a_value); +} + +static inline ASR::asr_t* make_ArrayItem_t_util(Allocator &al, const Location &a_loc, + ASR::expr_t* a_v, ASR::array_index_t* a_args, size_t n_args, ASR::ttype_t* a_type, + ASR::arraystorageType a_storage_format, ASR::expr_t* a_value) { + if( ASR::is_a(*a_v) ) { + a_v = ASR::down_cast(a_v)->m_arg; + } + + return ASR::make_ArrayItem_t(al, a_loc, a_v, a_args, + n_args, a_type, a_storage_format, a_value); +} + } // namespace ASRUtils } // namespace LCompilers diff --git a/src/libasr/asr_verify.cpp b/src/libasr/asr_verify.cpp index 0398a232f75..7442434c36f 100644 --- a/src/libasr/asr_verify.cpp +++ b/src/libasr/asr_verify.cpp @@ -457,6 +457,10 @@ class VerifyVisitor : public BaseWalkVisitor " but isn't found in its dependency list."); } + require(ASRUtils::get_FunctionType(x)->n_arg_types == x.n_args, + "Number of argument types in FunctionType must be exactly same as " + "number of arguments in the function"); + visit_ttype(*x.m_function_signature); current_symtab = parent_symtab; function_dependencies = function_dependencies_copy; @@ -533,7 +537,7 @@ class VerifyVisitor : public BaseWalkVisitor ASR::expr_t* aligned_expr_value = ASRUtils::expr_value(x.m_alignment); std::string msg = "Alignment should always evaluate to a constant expressions."; require(aligned_expr_value, msg); - int64_t alignment_int; + int64_t alignment_int = 0; require(ASRUtils::extract_value(aligned_expr_value, alignment_int), msg); require(alignment_int != 0 && (alignment_int & (alignment_int - 1)) == 0, "Alignment " + std::to_string(alignment_int) + @@ -834,6 +838,15 @@ class VerifyVisitor : public BaseWalkVisitor } } + void visit_ArrayPhysicalCast(const ASR::ArrayPhysicalCast_t& x) { + BaseWalkVisitor::visit_ArrayPhysicalCast(x); + require(x.m_new == ASRUtils::extract_physical_type(x.m_type), + "Destination physical type conflicts with the physical type of target"); + require(x.m_old == ASRUtils::extract_physical_type(ASRUtils::expr_type(x.m_arg)), + "Old physical type conflicts with the physical type of argument " + std::to_string(x.m_old) + + " " + std::to_string(ASRUtils::extract_physical_type(ASRUtils::expr_type(x.m_arg)))); + } + void visit_SubroutineCall(const SubroutineCall_t &x) { require(symtab_in_scope(current_symtab, x.m_name), "SubroutineCall::m_name '" + std::string(symbol_name(x.m_name)) + "' cannot point outside of its symbol table"); @@ -1066,6 +1079,15 @@ class VerifyVisitor : public BaseWalkVisitor visit_ttype(*x.m_type); } + void visit_Allocate(const Allocate_t &x) { + for( size_t i = 0; i < x.n_args; i++ ) { + require(ASR::is_a(*ASRUtils::expr_type(x.m_args[i].m_a)) || + ASR::is_a(*ASRUtils::expr_type(x.m_args[i].m_a)), + "Allocate should only be called with Allocatable or Pointer type inputs"); + } + BaseWalkVisitor::visit_Allocate(x); + } + }; diff --git a/src/libasr/codegen/asr_to_c.cpp b/src/libasr/codegen/asr_to_c.cpp index 1dbe65a5f21..b49d7ccd2e4 100644 --- a/src/libasr/codegen/asr_to_c.cpp +++ b/src/libasr/codegen/asr_to_c.cpp @@ -11,9 +11,9 @@ #include #include #include -#include -#include -#include +#include +#include +#include #include #include diff --git a/src/libasr/codegen/asr_to_c_cpp.h b/src/libasr/codegen/asr_to_c_cpp.h index 6f845bd79e8..a8181029f02 100644 --- a/src/libasr/codegen/asr_to_c_cpp.h +++ b/src/libasr/codegen/asr_to_c_cpp.h @@ -986,6 +986,11 @@ PyMODINIT_FUNC PyInit_lpython_module_)" + fn_name + R"((void) { current_scope = current_scope_copy; } + void visit_ArrayPhysicalCast(const ASR::ArrayPhysicalCast_t& x) { + src = ""; + this->visit_expr(*x.m_arg); + } + void visit_FunctionCall(const ASR::FunctionCall_t &x) { CHECK_FAST_C_CPP(compiler_options, x) ASR::Function_t *fn = ASR::down_cast( @@ -1754,8 +1759,10 @@ PyMODINIT_FUNC PyInit_lpython_module_)" + fn_name + R"((void) { // src = src; break; } - case (ASR::cast_kindType::IntegerToInteger) : { + case (ASR::cast_kindType::IntegerToInteger) : + case (ASR::cast_kindType::UnsignedIntegerToUnsignedInteger) : { // In C++, we do not need to cast int <-> long long explicitly: + // we also do not need to cast uint8_t <-> uint32_t explicitly: // src = src; break; } @@ -1830,7 +1837,8 @@ PyMODINIT_FUNC PyInit_lpython_module_)" + fn_name + R"((void) { last_expr_precedence = 2; break; } - case (ASR::cast_kindType::IntegerToLogical) : { + case (ASR::cast_kindType::IntegerToLogical) : + case (ASR::cast_kindType::UnsignedIntegerToLogical) : { src = "(bool)(" + src + ")"; last_expr_precedence = 2; break; @@ -2061,6 +2069,12 @@ PyMODINIT_FUNC PyInit_lpython_module_)" + fn_name + R"((void) { handle_UnaryMinus(x); } + void visit_UnsignedIntegerUnaryMinus(const ASR::UnsignedIntegerUnaryMinus_t &x) { + handle_UnaryMinus(x); + int kind = ASRUtils::extract_kind_from_ttype_t(ASRUtils::expr_type(x.m_arg)); + src = "(uint" + std::to_string(kind * 8) + "_t)" + src; + } + void visit_RealUnaryMinus(const ASR::RealUnaryMinus_t &x) { handle_UnaryMinus(x); } @@ -2693,7 +2707,7 @@ PyMODINIT_FUNC PyInit_lpython_module_)" + fn_name + R"((void) { out += func_name; break; \ } - std::string performSymbolicOperation(const std::string& functionName, const ASR::IntrinsicFunction_t& x) { + std::string performBinarySymbolicOperation(const std::string& functionName, const ASR::IntrinsicFunction_t& x) { headers.insert("symengine/cwrapper.h"); std::string indent(4, ' '); LCOMPILERS_ASSERT(x.n_args == 2); @@ -2718,6 +2732,23 @@ PyMODINIT_FUNC PyInit_lpython_module_)" + fn_name + R"((void) { return target; } + std::string performUnarySymbolicOperation(const std::string& functionName, const ASR::IntrinsicFunction_t& x) { + headers.insert("symengine/cwrapper.h"); + std::string indent(4, ' '); + LCOMPILERS_ASSERT(x.n_args == 1); + std::string target = symengine_queue.push(); + std::string target_src = symengine_src; + this->visit_expr(*x.m_args[0]); + std::string arg1 = src; + std::string arg1_src = symengine_src; + if (ASR::is_a(*x.m_args[0])) { + symengine_queue.pop(); + } + symengine_src = target_src + arg1_src; + symengine_src += indent + functionName + "(" + target + ", " + arg1 + ");\n"; + return target; + } + void visit_IntrinsicFunction(const ASR::IntrinsicFunction_t &x) { std::string out; std::string indent(4, ' '); @@ -2736,27 +2767,51 @@ PyMODINIT_FUNC PyInit_lpython_module_)" + fn_name + R"((void) { SET_INTRINSIC_NAME(Exp2, "exp2"); SET_INTRINSIC_NAME(Expm1, "expm1"); case (static_cast(ASRUtils::IntrinsicFunctions::SymbolicAdd)): { - src = performSymbolicOperation("basic_add", x); + src = performBinarySymbolicOperation("basic_add", x); return; } case (static_cast(ASRUtils::IntrinsicFunctions::SymbolicSub)): { - src = performSymbolicOperation("basic_sub", x); + src = performBinarySymbolicOperation("basic_sub", x); return; } case (static_cast(ASRUtils::IntrinsicFunctions::SymbolicMul)): { - src = performSymbolicOperation("basic_mul", x); + src = performBinarySymbolicOperation("basic_mul", x); return; } case (static_cast(ASRUtils::IntrinsicFunctions::SymbolicDiv)): { - src = performSymbolicOperation("basic_div", x); + src = performBinarySymbolicOperation("basic_div", x); return; } case (static_cast(ASRUtils::IntrinsicFunctions::SymbolicPow)): { - src = performSymbolicOperation("basic_pow", x); + src = performBinarySymbolicOperation("basic_pow", x); return; } case (static_cast(ASRUtils::IntrinsicFunctions::SymbolicDiff)): { - src = performSymbolicOperation("basic_diff", x); + src = performBinarySymbolicOperation("basic_diff", x); + return; + } + case (static_cast(ASRUtils::IntrinsicFunctions::SymbolicSin)): { + src = performUnarySymbolicOperation("basic_sin", x); + return; + } + case (static_cast(ASRUtils::IntrinsicFunctions::SymbolicCos)): { + src = performUnarySymbolicOperation("basic_cos", x); + return; + } + case (static_cast(ASRUtils::IntrinsicFunctions::SymbolicLog)): { + src = performUnarySymbolicOperation("basic_log", x); + return; + } + case (static_cast(ASRUtils::IntrinsicFunctions::SymbolicExp)): { + src = performUnarySymbolicOperation("basic_exp", x); + return; + } + case (static_cast(ASRUtils::IntrinsicFunctions::SymbolicAbs)): { + src = performUnarySymbolicOperation("basic_abs", x); + return; + } + case (static_cast(ASRUtils::IntrinsicFunctions::SymbolicExpand)): { + src = performUnarySymbolicOperation("basic_expand", x); return; } case (static_cast(ASRUtils::IntrinsicFunctions::SymbolicPi)): { @@ -2785,22 +2840,6 @@ PyMODINIT_FUNC PyInit_lpython_module_)" + fn_name + R"((void) { src = target; return; } - case (static_cast(ASRUtils::IntrinsicFunctions::SymbolicExpand)): { - headers.insert("symengine/cwrapper.h"); - LCOMPILERS_ASSERT(x.n_args == 1); - std::string target = symengine_queue.push(); - std::string target_src = symengine_src; - this->visit_expr(*x.m_args[0]); - std::string arg1 = src; - std::string arg1_src = symengine_src; - if (ASR::is_a(*x.m_args[0])) { - symengine_queue.pop(); - } - symengine_src = target_src + arg1_src; - symengine_src += indent + "basic_expand(" + target + ", " + arg1 + ");\n"; - src = target; - return; - } default : { throw LCompilersException("IntrinsicFunction: `" + ASRUtils::get_intrinsic_name(x.m_intrinsic_id) diff --git a/src/libasr/codegen/asr_to_julia.cpp b/src/libasr/codegen/asr_to_julia.cpp index 675752c5c93..07c35545aa5 100644 --- a/src/libasr/codegen/asr_to_julia.cpp +++ b/src/libasr/codegen/asr_to_julia.cpp @@ -920,6 +920,10 @@ class ASRToJuliaVisitor : public ASR::BaseVisitor } } + void visit_ArrayPhysicalCast(const ASR::ArrayPhysicalCast_t& /*x*/) { + + } + void visit_Allocate(const ASR::Allocate_t& x) { std::string indent(indentation_level * indentation_spaces, ' '); diff --git a/src/libasr/codegen/asr_to_llvm.cpp b/src/libasr/codegen/asr_to_llvm.cpp index f83b7139fb4..2fc19347454 100644 --- a/src/libasr/codegen/asr_to_llvm.cpp +++ b/src/libasr/codegen/asr_to_llvm.cpp @@ -47,54 +47,10 @@ #include #include #include - #include -#if LLVM_VERSION_MAJOR >= 11 -# define FIXED_VECTOR_TYPE llvm::FixedVectorType -#else -# define FIXED_VECTOR_TYPE llvm::VectorType -#endif - - namespace LCompilers { -namespace { - - // This exception is used to abort the visitor pattern when an error occurs. - // This is only used locally in this file, not propagated outside. An error - // must be already present in ASRToLLVMVisitor::diag before throwing this - // exception. This is checked with an assert when the CodeGenAbort is - // caught. - class CodeGenAbort - { - }; - - // Local exception that is only used in this file to exit the visitor - // pattern and caught later (not propagated outside). It accepts an error - // message that is then appended at the end of ASRToLLVMVisitor::diag. The - // `diag` can already contain other errors or warnings. This is a - // convenience class. One can also report the error into `diag` directly and - // call `CodeGenAbort` instead. - class CodeGenError - { - public: - diag::Diagnostic d; - public: - CodeGenError(const std::string &msg) - : d{diag::Diagnostic(msg, diag::Level::Error, diag::Stage::CodeGen)} - { } - - CodeGenError(const std::string &msg, const Location &loc) - : d{diag::Diagnostic(msg, diag::Level::Error, diag::Stage::CodeGen, { - diag::Label("", {loc}) - })} - { } - }; - -} - - using ASR::is_a; using ASR::down_cast; using ASR::down_cast2; @@ -108,12 +64,6 @@ using ASRUtils::intent_return_var; using ASRUtils::determine_module_dependencies; using ASRUtils::is_arg_dummy; -// Platform dependent fast unique hash: -uint64_t static get_hash(ASR::asr_t *node) -{ - return (uint64_t)node; -} - void string_init(llvm::LLVMContext &context, llvm::Module &module, llvm::IRBuilder<> &builder, llvm::Value* arg_size, llvm::Value* arg_string) { std::string func_name = "_lfortran_string_init"; @@ -198,14 +148,6 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor so that we can jump to the end of the block when we reach an exit */ std::vector loop_or_block_end_names; - std::unique_ptr llvm_utils; - std::unique_ptr list_api; - std::unique_ptr tuple_api; - std::unique_ptr dict_api_lp; - std::unique_ptr dict_api_sc; - std::unique_ptr set_api; // linear probing - std::unique_ptr arr_descr; - int64_t ptr_loads; bool lookup_enum_value_for_nonints; bool is_assignment_target; @@ -228,6 +170,13 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor std::string current_select_type_block_der_type; SymbolTable* current_scope; + std::unique_ptr llvm_utils; + std::unique_ptr list_api; + std::unique_ptr tuple_api; + std::unique_ptr dict_api_lp; + std::unique_ptr dict_api_sc; + std::unique_ptr set_api; // linear probing + std::unique_ptr arr_descr; ASRToLLVMVisitor(Allocator &al, llvm::LLVMContext &context, std::string infile, CompilerOptions &compiler_options_, diag::Diagnostics &diagnostics) : @@ -237,28 +186,32 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor infile{infile}, al{al}, prototype_only(false), - llvm_utils(std::make_unique(context, builder.get())), + ptr_loads(2), + lookup_enum_value_for_nonints(false), + is_assignment_target(false), + compiler_options(compiler_options_), + current_select_type_block_type(nullptr), + current_scope(nullptr), + llvm_utils(std::make_unique(context, builder.get(), + der_type_name, name2dertype, name2dercontext, struct_type_stack, + dertype2parent, name2memidx, compiler_options, arr_arg_type_cache, + fname2arg_type)), list_api(std::make_unique(context, llvm_utils.get(), builder.get())), tuple_api(std::make_unique(context, llvm_utils.get(), builder.get())), dict_api_lp(std::make_unique(context, llvm_utils.get(), builder.get())), dict_api_sc(std::make_unique(context, llvm_utils.get(), builder.get())), set_api(std::make_unique(context, llvm_utils.get(), builder.get())), arr_descr(LLVMArrUtils::Descriptor::get_descriptor(context, - builder.get(), - llvm_utils.get(), - LLVMArrUtils::DESCR_TYPE::_SimpleCMODescriptor)), - ptr_loads(2), - lookup_enum_value_for_nonints(false), - is_assignment_target(false), - compiler_options(compiler_options_), - current_select_type_block_type(nullptr), - current_scope(nullptr) + builder.get(), llvm_utils.get(), + LLVMArrUtils::DESCR_TYPE::_SimpleCMODescriptor)) { llvm_utils->tuple_api = tuple_api.get(); llvm_utils->list_api = list_api.get(); llvm_utils->dict_api = nullptr; llvm_utils->set_api = set_api.get(); llvm_utils->arr_api = arr_descr.get(); + llvm_utils->dict_api_lp = dict_api_lp.get(); + llvm_utils->dict_api_sc = dict_api_sc.get(); } llvm::Value* CreateLoad(llvm::Value *x) { @@ -436,91 +389,6 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor return is_ok; } - llvm::Type* - get_el_type(ASR::ttype_t* m_type_) { - int a_kind = ASRUtils::extract_kind_from_ttype_t(m_type_); - llvm::Type* el_type = nullptr; - if (ASR::is_a(*m_type_)) { - ASR::ttype_t *t2 = ASR::down_cast(m_type_)->m_type; - switch(t2->type) { - case ASR::ttypeType::Integer: { - el_type = getIntType(a_kind, true); - break; - } - case ASR::ttypeType::UnsignedInteger: { - el_type = getIntType(a_kind, true); - break; - } - case ASR::ttypeType::Real: { - el_type = getFPType(a_kind, true); - break; - } - case ASR::ttypeType::Complex: { - el_type = getComplexType(a_kind, true); - break; - } - case ASR::ttypeType::Logical: { - el_type = llvm::Type::getInt1Ty(context); - break; - } - case ASR::ttypeType::Struct: { - el_type = getStructType(m_type_); - break; - } - case ASR::ttypeType::Union: { - el_type = getUnionType(m_type_); - break; - } - case ASR::ttypeType::Character: { - el_type = character_type; - break; - } - default: - LCOMPILERS_ASSERT(false); - break; - } - } else { - switch(m_type_->type) { - case ASR::ttypeType::Integer: { - el_type = getIntType(a_kind); - break; - } - case ASR::ttypeType::UnsignedInteger: { - el_type = getIntType(a_kind); - break; - } - case ASR::ttypeType::Real: { - el_type = getFPType(a_kind); - break; - } - case ASR::ttypeType::Complex: { - el_type = getComplexType(a_kind); - break; - } - case ASR::ttypeType::Logical: { - el_type = llvm::Type::getInt1Ty(context); - break; - } - case ASR::ttypeType::Struct: { - el_type = getStructType(m_type_); - break; - } - case ASR::ttypeType::Character: { - el_type = character_type; - break; - } - case ASR::ttypeType::Class: { - el_type = getClassType(m_type_); - break; - } - default: - LCOMPILERS_ASSERT(false); - break; - } - } - return el_type; - } - void fill_array_details(llvm::Value* arr, llvm::Type* llvm_data_type, ASR::dimension_t* m_dims, int n_dims, bool is_data_only=false, bool reserve_data_memory=true) { @@ -569,363 +437,6 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor n_dims, llvm_dims, module.get()); } - inline llvm::Type* getIntType(int a_kind, bool get_pointer=false) { - llvm::Type* type_ptr = nullptr; - if( get_pointer ) { - switch(a_kind) - { - case 1: - type_ptr = llvm::Type::getInt8PtrTy(context); - break; - case 2: - type_ptr = llvm::Type::getInt16PtrTy(context); - break; - case 4: - type_ptr = llvm::Type::getInt32PtrTy(context); - break; - case 8: - type_ptr = llvm::Type::getInt64PtrTy(context); - break; - default: - throw CodeGenError("Only 8, 16, 32 and 64 bits integer kinds are supported."); - } - } else { - switch(a_kind) - { - case 1: - type_ptr = llvm::Type::getInt8Ty(context); - break; - case 2: - type_ptr = llvm::Type::getInt16Ty(context); - break; - case 4: - type_ptr = llvm::Type::getInt32Ty(context); - break; - case 8: - type_ptr = llvm::Type::getInt64Ty(context); - break; - default: - throw CodeGenError("Only 8, 16, 32 and 64 bits integer kinds are supported, found " + std::to_string(a_kind)); - } - } - return type_ptr; - } - - inline llvm::Type* getFPType(int a_kind, bool get_pointer=false) { - llvm::Type* type_ptr = nullptr; - if( get_pointer ) { - switch(a_kind) - { - case 4: - type_ptr = llvm::Type::getFloatPtrTy(context); - break; - case 8: - type_ptr = llvm::Type::getDoublePtrTy(context); - break; - default: - throw CodeGenError("Only 32 and 64 bits real kinds are supported."); - } - } else { - switch(a_kind) - { - case 4: - type_ptr = llvm::Type::getFloatTy(context); - break; - case 8: - type_ptr = llvm::Type::getDoubleTy(context); - break; - default: - throw CodeGenError("Only 32 and 64 bits real kinds are supported."); - } - } - return type_ptr; - } - - inline llvm::Type* getComplexType(int a_kind, bool get_pointer=false) { - llvm::Type* type = nullptr; - switch(a_kind) - { - case 4: - type = complex_type_4; - break; - case 8: - type = complex_type_8; - break; - default: - throw CodeGenError("Only 32 and 64 bits complex kinds are supported."); - } - if( type != nullptr ) { - if( get_pointer ) { - return type->getPointerTo(); - } else { - return type; - } - } - return nullptr; - } - - llvm::Type* getMemberType(ASR::ttype_t* mem_type, ASR::Variable_t* member) { - llvm::Type* llvm_mem_type = nullptr; - switch( mem_type->type ) { - case ASR::ttypeType::Integer: { - int a_kind = down_cast(mem_type)->m_kind; - llvm_mem_type = getIntType(a_kind); - break; - } - case ASR::ttypeType::Real: { - int a_kind = down_cast(mem_type)->m_kind; - llvm_mem_type = getFPType(a_kind); - break; - } - case ASR::ttypeType::Struct: { - llvm_mem_type = getStructType(mem_type); - break; - } - case ASR::ttypeType::Enum: { - llvm_mem_type = llvm::Type::getInt32Ty(context); - break ; - } - case ASR::ttypeType::Union: { - llvm_mem_type = getUnionType(mem_type); - break; - } - case ASR::ttypeType::Pointer: { - ASR::Pointer_t* ptr_type = ASR::down_cast(mem_type); - llvm_mem_type = getMemberType(ptr_type->m_type, member)->getPointerTo(); - break; - } - case ASR::ttypeType::Complex: { - int a_kind = down_cast(mem_type)->m_kind; - llvm_mem_type = getComplexType(a_kind); - break; - } - case ASR::ttypeType::Character: { - llvm_mem_type = character_type; - break; - } - case ASR::ttypeType::CPtr: { - llvm_mem_type = llvm::Type::getVoidTy(context)->getPointerTo(); - break; - } - default: - throw CodeGenError("Cannot identify the type of member, '" + - std::string(member->m_name) + - "' in derived type, '" + der_type_name + "'.", - member->base.base.loc); - } - return llvm_mem_type; - } - - void createStructContext(ASR::StructType_t* der_type) { - std::string der_type_name = std::string(der_type->m_name); - if (name2dercontext.find(der_type_name) == name2dercontext.end() ) { - llvm::StructType* der_type_llvm = llvm::StructType::create(context, - {}, - der_type_name, - der_type->m_is_packed); - name2dercontext[der_type_name] = der_type_llvm; - if( der_type->m_parent != nullptr ) { - ASR::StructType_t *par_der_type = ASR::down_cast( - symbol_get_past_external(der_type->m_parent)); - createStructContext(par_der_type); - } - for( size_t i = 0; i < der_type->n_members; i++ ) { - std::string member_name = der_type->m_members[i]; - ASR::symbol_t* sym = der_type->m_symtab->get_symbol(member_name); - if (ASR::is_a(*sym)) { - ASR::StructType_t *d_type = ASR::down_cast(sym); - createStructContext(d_type); - } - } - } - } - - llvm::Type* getStructType(ASR::StructType_t* der_type, bool is_pointer=false) { - std::string der_type_name = std::string(der_type->m_name); - createStructContext(der_type); - if (std::find(struct_type_stack.begin(), struct_type_stack.end(), - der_type_name) != struct_type_stack.end()) { - LCOMPILERS_ASSERT(name2dercontext.find(der_type_name) != name2dercontext.end()); - return name2dercontext[der_type_name]; - } - struct_type_stack.push_back(der_type_name); - llvm::StructType** der_type_llvm; - if (name2dertype.find(der_type_name) != name2dertype.end() ) { - der_type_llvm = &name2dertype[der_type_name]; - } else { - der_type_llvm = &name2dercontext[der_type_name]; - std::vector member_types; - int member_idx = 0; - if( der_type->m_parent != nullptr ) { - ASR::StructType_t *par_der_type = ASR::down_cast( - symbol_get_past_external(der_type->m_parent)); - llvm::Type* par_llvm = getStructType(par_der_type); - member_types.push_back(par_llvm); - dertype2parent[der_type_name] = std::string(par_der_type->m_name); - member_idx += 1; - } - for( size_t i = 0; i < der_type->n_members; i++ ) { - std::string member_name = der_type->m_members[i]; - ASR::Variable_t* member = ASR::down_cast(der_type->m_symtab->get_symbol(member_name)); - llvm::Type* llvm_mem_type = get_type_from_ttype_t_util(member->m_type, member->m_abi); - member_types.push_back(llvm_mem_type); - name2memidx[der_type_name][std::string(member->m_name)] = member_idx; - member_idx++; - } - (*der_type_llvm)->setBody(member_types); - name2dertype[der_type_name] = *der_type_llvm; - } - struct_type_stack.pop_back(); - if ( is_pointer ) { - return (*der_type_llvm)->getPointerTo(); - } - return (llvm::Type*) *der_type_llvm; - } - - llvm::Type* getStructType(ASR::ttype_t* _type, bool is_pointer=false) { - ASR::StructType_t* der_type; - if( ASR::is_a(*_type) ) { - ASR::Struct_t* der = ASR::down_cast(_type); - ASR::symbol_t* der_sym = ASRUtils::symbol_get_past_external(der->m_derived_type); - der_type = ASR::down_cast(der_sym); - } else if( ASR::is_a(*_type) ) { - ASR::Class_t* der = ASR::down_cast(_type); - ASR::symbol_t* der_sym = ASRUtils::symbol_get_past_external(der->m_class_type); - der_type = ASR::down_cast(der_sym); - } else { - LCOMPILERS_ASSERT(false); - return nullptr; // silence a warning - } - llvm::Type* type = getStructType(der_type, is_pointer); - LCOMPILERS_ASSERT(type != nullptr); - return type; - } - - llvm::Type* getUnionType(ASR::UnionType_t* union_type, bool is_pointer=false) { - std::string union_type_name = std::string(union_type->m_name); - llvm::StructType* union_type_llvm = nullptr; - if( name2dertype.find(union_type_name) != name2dertype.end() ) { - union_type_llvm = name2dertype[union_type_name]; - } else { - const std::map& scope = union_type->m_symtab->get_scope(); - llvm::DataLayout data_layout(module.get()); - llvm::Type* max_sized_type = nullptr; - size_t max_type_size = 0; - for( auto itr = scope.begin(); itr != scope.end(); itr++ ) { - ASR::Variable_t* member = ASR::down_cast(ASRUtils::symbol_get_past_external(itr->second)); - llvm::Type* llvm_mem_type = getMemberType(member->m_type, member); - size_t type_size = data_layout.getTypeAllocSize(llvm_mem_type); - if( max_type_size < type_size ) { - max_sized_type = llvm_mem_type; - type_size = max_type_size; - } - } - union_type_llvm = llvm::StructType::create(context, {max_sized_type}, union_type_name); - name2dertype[union_type_name] = union_type_llvm; - } - if( is_pointer ) { - return union_type_llvm->getPointerTo(); - } - return (llvm::Type*) union_type_llvm; - } - - llvm::Type* getUnionType(ASR::ttype_t* _type, bool is_pointer=false) { - ASR::Union_t* union_ = ASR::down_cast(_type); - ASR::symbol_t* union_sym = ASRUtils::symbol_get_past_external(union_->m_union_type); - ASR::UnionType_t* union_type = ASR::down_cast(union_sym); - return getUnionType(union_type, is_pointer); - } - - llvm::Type* getClassType(ASR::ClassType_t* der_type, bool is_pointer=false) { - const std::map& scope = der_type->m_symtab->get_scope(); - std::vector member_types; - int member_idx = 0; - for( auto itr = scope.begin(); itr != scope.end(); itr++ ) { - if (!ASR::is_a(*itr->second) && - !ASR::is_a(*itr->second) && - !ASR::is_a(*itr->second)) { - ASR::Variable_t* member = ASR::down_cast(itr->second); - llvm::Type* mem_type = nullptr; - switch( member->m_type->type ) { - case ASR::ttypeType::Integer: { - int a_kind = down_cast(member->m_type)->m_kind; - mem_type = getIntType(a_kind); - break; - } - case ASR::ttypeType::Real: { - int a_kind = down_cast(member->m_type)->m_kind; - mem_type = getFPType(a_kind); - break; - } - case ASR::ttypeType::Class: { - mem_type = getClassType(member->m_type); - break; - } - case ASR::ttypeType::Complex: { - int a_kind = down_cast(member->m_type)->m_kind; - mem_type = getComplexType(a_kind); - break; - } - default: - throw CodeGenError("Cannot identify the type of member, '" + - std::string(member->m_name) + - "' in derived type, '" + der_type_name + "'.", - member->base.base.loc); - } - member_types.push_back(mem_type); - name2memidx[der_type_name][std::string(member->m_name)] = member_idx; - member_idx++; - } - } - llvm::StructType* der_type_llvm = llvm::StructType::create(context, member_types, der_type_name); - name2dertype[der_type_name] = der_type_llvm; - if( is_pointer ) { - return der_type_llvm->getPointerTo(); - } - return (llvm::Type*) der_type_llvm; - } - - llvm::Type* getClassType(ASR::StructType_t* der_type, bool is_pointer=false) { - std::string der_type_name = std::string(der_type->m_name) + std::string("_polymorphic"); - llvm::StructType* der_type_llvm = nullptr; - if( name2dertype.find(der_type_name) != name2dertype.end() ) { - der_type_llvm = name2dertype[der_type_name]; - } - LCOMPILERS_ASSERT(der_type_llvm != nullptr); - if( is_pointer ) { - return der_type_llvm->getPointerTo(); - } - return (llvm::Type*) der_type_llvm; - } - - llvm::Type* getClassType(ASR::ttype_t* _type, bool is_pointer=false) { - ASR::Class_t* der = ASR::down_cast(_type); - ASR::symbol_t* der_sym = ASRUtils::symbol_get_past_external(der->m_class_type); - std::string der_sym_name = ASRUtils::symbol_name(der_sym); - std::string der_type_name = der_sym_name + std::string("_polymorphic"); - llvm::StructType* der_type_llvm; - if( name2dertype.find(der_type_name) != name2dertype.end() ) { - der_type_llvm = name2dertype[der_type_name]; - } else { - std::vector member_types; - member_types.push_back(getIntType(8)); - if( der_sym_name == "~abstract_type" ) { - member_types.push_back(llvm::Type::getVoidTy(context)->getPointerTo()); - } else if( ASR::is_a(*der_sym) ) { - ASR::ClassType_t* class_type_t = ASR::down_cast(der_sym); - member_types.push_back(getClassType(class_type_t, is_pointer)); - } else if( ASR::is_a(*der_sym) ) { - ASR::StructType_t* struct_type_t = ASR::down_cast(der_sym); - member_types.push_back(getStructType(struct_type_t, is_pointer)); - } - der_type_llvm = llvm::StructType::create(context, member_types, der_type_name); - name2dertype[der_type_name] = der_type_llvm; - } - - return (llvm::Type*) der_type_llvm; - } - - /* * Dispatches the required function from runtime library to * perform the specified binary operation. @@ -1268,7 +779,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor */ llvm::Value* lfortran_intrinsic(llvm::Function *fn, llvm::Value* pa, int a_kind) { - llvm::Type *presult_type = getFPType(a_kind); + llvm::Type *presult_type = llvm_utils->getFPType(a_kind); llvm::AllocaInst *presult = builder->CreateAlloca(presult_type, nullptr); llvm::Value *a = CreateLoad(pa); std::vector args = {a, presult}; @@ -1295,23 +806,11 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor // Define LLVM types that we might need // Complex type is represented as an identified struct in LLVM // %complex = type { float, float } - std::vector els_4 = { - llvm::Type::getFloatTy(context), - llvm::Type::getFloatTy(context)}; - std::vector els_8 = { - llvm::Type::getDoubleTy(context), - llvm::Type::getDoubleTy(context)}; - std::vector els_4_ptr = { - llvm::Type::getFloatPtrTy(context), - llvm::Type::getFloatPtrTy(context)}; - std::vector els_8_ptr = { - llvm::Type::getDoublePtrTy(context), - llvm::Type::getDoublePtrTy(context)}; - complex_type_4 = llvm::StructType::create(context, els_4, "complex_4"); - complex_type_8 = llvm::StructType::create(context, els_8, "complex_8"); - complex_type_4_ptr = llvm::StructType::create(context, els_4_ptr, "complex_4_ptr"); - complex_type_8_ptr = llvm::StructType::create(context, els_8_ptr, "complex_8_ptr"); - character_type = llvm::Type::getInt8PtrTy(context); + complex_type_4 = llvm_utils->complex_type_4; + complex_type_8 = llvm_utils->complex_type_8; + complex_type_4_ptr = llvm_utils->complex_type_4_ptr; + complex_type_8_ptr = llvm_utils->complex_type_8_ptr; + character_type = llvm_utils->character_type; list_type = llvm::Type::getInt8PtrTy(context); llvm::Type* bound_arg = static_cast(arr_descr->get_dimension_descriptor_type(true)); @@ -1416,7 +915,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor continue;; } } - llvm::Type* llvm_data_type = get_type_from_ttype_t_util(asr_data_type); + llvm::Type* llvm_data_type = llvm_utils->get_type_from_ttype_t_util(asr_data_type, module.get()); fill_malloc_array_details(x_arr, llvm_data_type, curr_arg.m_dims, curr_arg.n_dims); } if (x.m_stat) { @@ -1445,13 +944,13 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } } - inline void call_lfortran_free(llvm::Function* fn) { + inline void call_lfortran_free(llvm::Function* fn, llvm::Type* llvm_data_type) { llvm::Value* arr = CreateLoad(arr_descr->get_pointer_to_data(tmp)); llvm::AllocaInst *arg_arr = builder->CreateAlloca(character_type, nullptr); builder->CreateStore(builder->CreateBitCast(arr, character_type), arg_arr); std::vector args = {CreateLoad(arg_arr)}; builder->CreateCall(fn, args); - arr_descr->set_is_allocated_flag(tmp, false); + arr_descr->reset_is_allocated_flag(tmp, llvm_data_type); } llvm::Function* _Deallocate() { @@ -1488,7 +987,8 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor return alloc_fun; } - void visit_ImplicitDeallocate(const ASR::ImplicitDeallocate_t& x) { + template + void visit_Deallocate(const T& x) { llvm::Function* free_fn = _Deallocate(); for( size_t i = 0; i < x.n_vars; i++ ) { const ASR::expr_t* tmp_expr = x.m_vars[i]; @@ -1503,40 +1003,76 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } ASR::Variable_t *v = ASR::down_cast( symbol_get_past_external(curr_obj)); - + int64_t ptr_loads_copy = ptr_loads; + ptr_loads = 1 - LLVM::is_llvm_pointer(*v->m_type); fetch_var(v); - if (ASRUtils::is_character(*v->m_type)) { - int dims = ASRUtils::extract_n_dims_from_ttype(v->m_type); - if (dims == 0) { - call_lfortran_free_string(free_fn); + ptr_loads = ptr_loads_copy; + int dims = ASRUtils::extract_n_dims_from_ttype(v->m_type); + if (dims == 0) { + if (ASRUtils::is_character(*v->m_type)) { + llvm::Value* tmp_ = tmp; + if( LLVM::is_llvm_pointer(*v->m_type) ) { + tmp = LLVM::CreateLoad(*builder, tmp); + } + llvm::Value *cond = builder->CreateICmpNE( + builder->CreatePtrToInt(tmp, llvm::Type::getInt64Ty(context)), + builder->CreatePtrToInt(llvm::ConstantPointerNull::get(character_type), + llvm::Type::getInt64Ty(context)) ); + llvm_utils->create_if_else(cond, [=]() { + builder->CreateCall(free_fn, {tmp}); + builder->CreateStore( + llvm::ConstantPointerNull::get(character_type), tmp_); + }, [](){}); continue; + } else { + llvm::Value* tmp_ = tmp; + if( LLVM::is_llvm_pointer(*v->m_type) ) { + tmp = LLVM::CreateLoad(*builder, tmp); + } + llvm::Type* llvm_data_type = llvm_utils->get_type_from_ttype_t_util( + ASRUtils::type_get_past_array( + ASRUtils::type_get_past_pointer( + ASRUtils::type_get_past_allocatable(v->m_type))), + module.get(), v->m_abi); + llvm::Value *cond = builder->CreateICmpNE( + builder->CreatePtrToInt(tmp, llvm::Type::getInt64Ty(context)), + builder->CreatePtrToInt( + llvm::ConstantPointerNull::get(llvm_data_type->getPointerTo()), + llvm::Type::getInt64Ty(context)) ); + llvm_utils->create_if_else(cond, [=]() { + llvm::AllocaInst *arg_tmp = builder->CreateAlloca(character_type, nullptr); + builder->CreateStore(builder->CreateBitCast(tmp, character_type), arg_tmp); + std::vector args = {CreateLoad(arg_tmp)}; + builder->CreateCall(free_fn, args); + builder->CreateStore( + llvm::ConstantPointerNull::get(llvm_data_type->getPointerTo()), tmp_); + }, [](){}); + } + } else { + if( LLVM::is_llvm_pointer(*v->m_type) ) { + tmp = LLVM::CreateLoad(*builder, tmp); } + llvm::Type* llvm_data_type = llvm_utils->get_type_from_ttype_t_util( + ASRUtils::type_get_past_array( + ASRUtils::type_get_past_pointer( + ASRUtils::type_get_past_allocatable(v->m_type))), + module.get(), v->m_abi); + llvm::Value *cond = arr_descr->get_is_allocated_flag(tmp, llvm_data_type); + llvm_utils->create_if_else(cond, [=]() { + call_lfortran_free(free_fn, llvm_data_type); + }, [](){}); } - llvm::Value *cond = arr_descr->get_is_allocated_flag(tmp); - llvm_utils->create_if_else(cond, [=]() { - call_lfortran_free(free_fn); - }, [](){}); } } + + void visit_ImplicitDeallocate(const ASR::ImplicitDeallocate_t& x) { + visit_Deallocate(x); + } + + void visit_ExplicitDeallocate(const ASR::ExplicitDeallocate_t& x) { - llvm::Function* free_fn = _Deallocate(); - for( size_t i = 0; i < x.n_vars; i++ ) { - const ASR::expr_t* tmp_expr = x.m_vars[i]; - ASR::symbol_t* curr_obj = nullptr; - if( ASR::is_a(*tmp_expr) ) { - const ASR::Var_t* tmp_var = ASR::down_cast(tmp_expr); - curr_obj = tmp_var->m_v; - } else { - throw CodeGenError("Cannot deallocate variables in expression " + - std::to_string(tmp_expr->type), - tmp_expr->base.loc); - } - ASR::Variable_t *v = ASR::down_cast( - symbol_get_past_external(curr_obj)); - fetch_var(v); - call_lfortran_free(free_fn); - } + visit_Deallocate(x); } void visit_ListConstant(const ASR::ListConstant_t& x) { @@ -1545,11 +1081,10 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor bool is_list_local = false; ASR::dimension_t* m_dims_local = nullptr; int n_dims_local = -1, a_kind_local = -1; - llvm::Type* llvm_el_type = get_type_from_ttype_t(list_type->m_type, - nullptr, - ASR::storage_typeType::Default, is_array_type_local, + llvm::Type* llvm_el_type = llvm_utils->get_type_from_ttype_t(list_type->m_type, + nullptr, ASR::storage_typeType::Default, is_array_type_local, is_malloc_array_type_local, is_list_local, m_dims_local, - n_dims_local, a_kind_local); + n_dims_local, a_kind_local, module.get()); std::string type_code = ASRUtils::get_type_code(list_type->m_type); int32_t type_size = -1; if( ASR::is_a(*list_type->m_type) || @@ -1576,19 +1111,11 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor tmp = const_list; } - void set_dict_api(ASR::Dict_t* dict_type) { - if( ASR::is_a(*dict_type->m_key_type) ) { - llvm_utils->dict_api = dict_api_sc.get(); - } else { - llvm_utils->dict_api = dict_api_lp.get(); - } - } - void visit_DictConstant(const ASR::DictConstant_t& x) { - llvm::Type* const_dict_type = get_dict_type(x.m_type); + llvm::Type* const_dict_type = llvm_utils->get_dict_type(x.m_type, module.get()); llvm::Value* const_dict = builder->CreateAlloca(const_dict_type, nullptr, "const_dict"); ASR::Dict_t* x_dict = ASR::down_cast(x.m_type); - set_dict_api(x_dict); + llvm_utils->set_dict_api(x_dict); std::string key_type_code = ASRUtils::get_type_code(x_dict->m_key_type); std::string value_type_code = ASRUtils::get_type_code(x_dict->m_value_type); llvm_utils->dict_api->dict_init(key_type_code, value_type_code, const_dict, module.get(), x.n_keys); @@ -1610,7 +1137,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } void visit_SetConstant(const ASR::SetConstant_t& x) { - llvm::Type* const_set_type = get_set_type(x.m_type); + llvm::Type* const_set_type = llvm_utils->get_set_type(x.m_type, module.get()); llvm::Value* const_set = builder->CreateAlloca(const_set_type, nullptr, "const_set"); ASR::Set_t* x_set = ASR::down_cast(x.m_type); std::string el_type_code = ASRUtils::get_type_code(x_set->m_type); @@ -1639,10 +1166,9 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor ASR::dimension_t* m_dims = nullptr; int n_dims = 0, a_kind = -1; for( size_t i = 0; i < tuple_type->n_type; i++ ) { - llvm_el_types.push_back(get_type_from_ttype_t(tuple_type->m_type[i], - nullptr, - m_storage, is_array_type, is_malloc_array_type, - is_list, m_dims, n_dims, a_kind)); + llvm_el_types.push_back(llvm_utils->get_type_from_ttype_t(tuple_type->m_type[i], + nullptr, m_storage, is_array_type, is_malloc_array_type, + is_list, m_dims, n_dims, a_kind, module.get())); } llvm::Type* const_tuple_type = tuple_api->get_tuple_type(type_code, llvm_el_types); llvm::Value* const_tuple = builder->CreateAlloca(const_tuple_type, nullptr, "const_tuple"); @@ -1677,7 +1203,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor if (!fn) { llvm::FunctionType *function_type = llvm::FunctionType::get( llvm::Type::getInt32Ty(context), { - getIntType(int_kind) + llvm_utils->getIntType(int_kind) }, false); fn = llvm::Function::Create(function_type, llvm::Function::ExternalLinkage, runtime_func_name, *module); @@ -1727,7 +1253,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } tmp = builder->CreateCall(fn, {c}); if( ASRUtils::extract_kind_from_ttype_t(x.m_type) == 8 ) { - tmp = builder->CreateSExt(tmp, getIntType(8)); + tmp = builder->CreateSExt(tmp, llvm_utils->getIntType(8)); } } @@ -1736,15 +1262,28 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor this->visit_expr_wrapper(x.m_value, true); return; } + ASR::ttype_t *type_ = ASRUtils::expr_type(x.m_mask); + int64_t ptr_loads_copy = ptr_loads; + ptr_loads = 2 - !LLVM::is_llvm_pointer(*type_); this->visit_expr(*x.m_mask); + ptr_loads = ptr_loads_copy; llvm::Value *mask = tmp; - ASR::ttype_t *type_ = ASRUtils::expr_type(x.m_mask); LCOMPILERS_ASSERT(ASR::is_a( *ASRUtils::type_get_past_array(type_))) // TODO int32_t n = ASRUtils::extract_n_dims_from_ttype(type_); llvm::Value *size = llvm::ConstantInt::get(context, llvm::APInt(32, n)); - if (ASR::is_a(*x.m_mask)) { - mask = LLVM::CreateLoad(*builder, llvm_utils->create_gep(mask, 0)); + switch( ASRUtils::extract_physical_type(type_) ) { + case ASR::array_physical_typeType::DescriptorArray: { + mask = LLVM::CreateLoad(*builder, arr_descr->get_pointer_to_data(mask)); + break; + } + case ASR::array_physical_typeType::FixedSizeArray: { + mask = llvm_utils->create_gep(mask, 0); + break; + } + default: { + LCOMPILERS_ASSERT(false); + } } std::string runtime_func_name = "_lfortran_all"; llvm::Function *fn = module->getFunction(runtime_func_name); @@ -1774,7 +1313,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } else { func_name = "llvm.sqrt.f64"; } - llvm::Type *type = getFPType(kind_value); + llvm::Type *type = llvm_utils->getFPType(kind_value); llvm::Function *fn_sqrt = module->getFunction(func_name); if (!fn_sqrt) { llvm::FunctionType *function_type = llvm::FunctionType::get( @@ -1814,7 +1353,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor der_type_name = ASRUtils::symbol_name(d->m_derived_type); } member_type_asr = member_var->m_type; - llvm::Type* member_type_llvm = getMemberType(member_type_asr, member_var)->getPointerTo(); + llvm::Type* member_type_llvm = llvm_utils->getMemberType(member_type_asr, member_var, module.get())->getPointerTo(); tmp = builder->CreateBitCast(union_llvm, member_type_llvm); if( is_assignment_target ) { return ; @@ -1854,17 +1393,17 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor ptr_loads = ptr_loads_copy; llvm::Value *key = tmp; if (x.m_default) { - llvm::Type *val_type = get_type_from_ttype_t_util(dict_type->m_value_type); + llvm::Type *val_type = llvm_utils->get_type_from_ttype_t_util(dict_type->m_value_type, module.get()); llvm::Value *def_value_ptr = builder->CreateAlloca(val_type, nullptr); ptr_loads = !LLVM::is_llvm_struct(dict_type->m_value_type); this->visit_expr_wrapper(x.m_default, true); ptr_loads = ptr_loads_copy; builder->CreateStore(tmp, def_value_ptr); - set_dict_api(dict_type); + llvm_utils->set_dict_api(dict_type); tmp = llvm_utils->dict_api->get_item(pdict, key, *module, dict_type, def_value_ptr, LLVM::is_llvm_struct(dict_type->m_value_type)); } else { - set_dict_api(dict_type); + llvm_utils->set_dict_api(dict_type); tmp = llvm_utils->dict_api->read_item(pdict, key, *module, dict_type, compiler_options.enable_bounds_checking, LLVM::is_llvm_struct(dict_type->m_value_type)); @@ -1884,7 +1423,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor ptr_loads = ptr_loads_copy; llvm::Value *key = tmp; - set_dict_api(dict_type); + llvm_utils->set_dict_api(dict_type); tmp = llvm_utils->dict_api->pop_item(pdict, key, *module, dict_type, LLVM::is_llvm_struct(dict_type->m_value_type)); } @@ -1910,10 +1449,31 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor this->visit_expr(*x.m_right); llvm::Value* right = tmp; ptr_loads = ptr_loads_copy; - tmp = llvm_utils->is_equal_by_value(left, right, *module, - ASRUtils::expr_type(x.m_left)); - if (x.m_op == ASR::cmpopType::NotEq) { - tmp = builder->CreateNot(tmp); + + ASR::ttype_t* int32_type = ASRUtils::TYPE(ASR::make_Integer_t(al, x.base.base.loc, 4)); + + if(x.m_op == ASR::cmpopType::Eq || x.m_op == ASR::cmpopType::NotEq) { + tmp = llvm_utils->is_equal_by_value(left, right, *module, + ASRUtils::expr_type(x.m_left)); + if (x.m_op == ASR::cmpopType::NotEq) { + tmp = builder->CreateNot(tmp); + } + } + else if(x.m_op == ASR::cmpopType::Lt) { + tmp = llvm_utils->is_ineq_by_value(left, right, *module, + ASRUtils::expr_type(x.m_left), 0, int32_type); + } + else if(x.m_op == ASR::cmpopType::LtE) { + tmp = llvm_utils->is_ineq_by_value(left, right, *module, + ASRUtils::expr_type(x.m_left), 1, int32_type); + } + else if(x.m_op == ASR::cmpopType::Gt) { + tmp = llvm_utils->is_ineq_by_value(left, right, *module, + ASRUtils::expr_type(x.m_left), 2, int32_type); + } + else if(x.m_op == ASR::cmpopType::GtE) { + tmp = llvm_utils->is_ineq_by_value(left, right, *module, + ASRUtils::expr_type(x.m_left), 3, int32_type); } } @@ -1929,7 +1489,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor ptr_loads = ptr_loads_copy; llvm::Value* pdict = tmp; ASR::Dict_t* x_dict = ASR::down_cast(ASRUtils::expr_type(x.m_arg)); - set_dict_api(x_dict); + llvm_utils->set_dict_api(x_dict); tmp = llvm_utils->dict_api->len(pdict); } @@ -1983,7 +1543,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor llvm::Value *value = tmp; ptr_loads = ptr_loads_copy; - set_dict_api(dict_type); + llvm_utils->set_dict_api(dict_type); llvm_utils->dict_api->write_item(pdict, key, value, module.get(), dict_type->m_key_type, dict_type->m_value_type, name2memidx); @@ -2223,11 +1783,10 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor bool is_list_local = false; ASR::dimension_t* m_dims_local = nullptr; int n_dims_local = -1, a_kind_local = -1; - llvm::Type* llvm_el_type = get_type_from_ttype_t(list_type->m_type, - nullptr, - ASR::storage_typeType::Default, is_array_type_local, - is_malloc_array_type_local, is_list_local, m_dims_local, - n_dims_local, a_kind_local); + llvm::Type* llvm_el_type = llvm_utils->get_type_from_ttype_t(list_type->m_type, + nullptr, ASR::storage_typeType::Default, is_array_type_local, + is_malloc_array_type_local, is_list_local, m_dims_local, + n_dims_local, a_kind_local, module.get()); std::string type_code = ASRUtils::get_type_code(list_type->m_type); int32_t type_size = -1; if( ASR::is_a(*list_type->m_type) || @@ -2259,10 +1818,28 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor this->visit_expr(*x.m_right); llvm::Value* right = tmp; ptr_loads = ptr_loads_copy; - tmp = llvm_utils->is_equal_by_value(left, right, *module, - ASRUtils::expr_type(x.m_left)); - if (x.m_op == ASR::cmpopType::NotEq) { - tmp = builder->CreateNot(tmp); + if(x.m_op == ASR::cmpopType::Eq || x.m_op == ASR::cmpopType::NotEq) { + tmp = llvm_utils->is_equal_by_value(left, right, *module, + ASRUtils::expr_type(x.m_left)); + if (x.m_op == ASR::cmpopType::NotEq) { + tmp = builder->CreateNot(tmp); + } + } + else if(x.m_op == ASR::cmpopType::Lt) { + tmp = llvm_utils->is_ineq_by_value(left, right, *module, + ASRUtils::expr_type(x.m_left), 0); + } + else if(x.m_op == ASR::cmpopType::LtE) { + tmp = llvm_utils->is_ineq_by_value(left, right, *module, + ASRUtils::expr_type(x.m_left), 1); + } + else if(x.m_op == ASR::cmpopType::Gt) { + tmp = llvm_utils->is_ineq_by_value(left, right, *module, + ASRUtils::expr_type(x.m_left), 2); + } + else if(x.m_op == ASR::cmpopType::GtE) { + tmp = llvm_utils->is_ineq_by_value(left, right, *module, + ASRUtils::expr_type(x.m_left), 3); } } @@ -2309,10 +1886,9 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor ASR::dimension_t* m_dims = nullptr; int n_dims = 0, a_kind = -1; for( size_t i = 0; i < tuple_type_left->n_type; i++ ) { - llvm_el_types.push_back(get_type_from_ttype_t(tuple_type_left->m_type[i], - nullptr, - m_storage, is_array_type, is_malloc_array_type, - is_list, m_dims, n_dims, a_kind)); + llvm_el_types.push_back(llvm_utils->get_type_from_ttype_t(tuple_type_left->m_type[i], + nullptr, m_storage, is_array_type, is_malloc_array_type, + is_list, m_dims, n_dims, a_kind, module.get())); v_type.push_back(al, tuple_type_left->m_type[i]); } is_array_type = false; is_malloc_array_type = false; @@ -2320,10 +1896,9 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor m_dims = nullptr; n_dims = 0; a_kind = -1; for( size_t i = 0; i < tuple_type_right->n_type; i++ ) { - llvm_el_types.push_back(get_type_from_ttype_t(tuple_type_right->m_type[i], - nullptr, - m_storage, is_array_type, is_malloc_array_type, - is_list, m_dims, n_dims, a_kind)); + llvm_el_types.push_back(llvm_utils->get_type_from_ttype_t(tuple_type_right->m_type[i], + nullptr, m_storage, is_array_type, is_malloc_array_type, + is_list, m_dims, n_dims, a_kind, module.get())); v_type.push_back(al, tuple_type_right->m_type[i]); } llvm::Type* concat_tuple_type = tuple_api->get_tuple_type(type_code, llvm_el_types); @@ -2341,9 +1916,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor return; } ASR::ttype_t* x_mv_type = ASRUtils::expr_type(x.m_v); - bool is_argument = false; llvm::Value* array = nullptr; - bool is_data_only = false; ASR::Variable_t *v = nullptr; if( ASR::is_a(*x.m_v) ) { v = ASRUtils::EXPR2VAR(x.m_v); @@ -2356,10 +1929,6 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } uint32_t v_h = get_hash((ASR::asr_t*)v); array = llvm_symtab[v_h]; - is_argument = (v->m_intent == ASRUtils::intent_in) - || (v->m_intent == ASRUtils::intent_out) - || (v->m_intent == ASRUtils::intent_inout) - || (v->m_intent == ASRUtils::intent_unspecified); } else { int64_t ptr_loads_copy = ptr_loads; ptr_loads = 0; @@ -2411,33 +1980,40 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor ptr_loads = ptr_loads_copy; indices.push_back(tmp); } + + ASR::ttype_t* x_mv_type_ = ASRUtils::type_get_past_allocatable( + ASRUtils::type_get_past_pointer(ASRUtils::type_get_past_const(x_mv_type))); + LCOMPILERS_ASSERT(ASR::is_a(*x_mv_type_)); + ASR::Array_t* array_t = ASR::down_cast(x_mv_type_); bool is_bindc_array = ASRUtils::expr_abi(x.m_v) == ASR::abiType::BindC; - if (ASR::is_a(*x_mv_type) || + if ( LLVM::is_llvm_pointer(*x_mv_type) || ((is_bindc_array && !ASRUtils::is_fixed_size_array(m_dims, n_dims)) && - ASR::is_a(*x.m_v))) { + ASR::is_a(*x.m_v)) ) { array = CreateLoad(array); } - is_data_only = is_data_only || (is_argument && !ASRUtils::is_dimension_empty(m_dims, n_dims)); - is_data_only = is_data_only || is_bindc_array; + Vec llvm_diminfo; llvm_diminfo.reserve(al, 2 * x.n_args + 1); - if( is_data_only ) { + if( array_t->m_physical_type == ASR::array_physical_typeType::PointerToDataArray || + array_t->m_physical_type == ASR::array_physical_typeType::FixedSizeArray ) { + int ptr_loads_copy = ptr_loads; for( size_t idim = 0; idim < x.n_args; idim++ ) { + ptr_loads = 2 - !LLVM::is_llvm_pointer(*ASRUtils::expr_type(m_dims[idim].m_start)); this->visit_expr_wrapper(m_dims[idim].m_start, true); llvm::Value* dim_start = tmp; + ptr_loads = 2 - !LLVM::is_llvm_pointer(*ASRUtils::expr_type(m_dims[idim].m_length)); this->visit_expr_wrapper(m_dims[idim].m_length, true); llvm::Value* dim_size = tmp; llvm_diminfo.push_back(al, dim_start); llvm_diminfo.push_back(al, dim_size); } + ptr_loads = ptr_loads_copy; } LCOMPILERS_ASSERT(ASRUtils::extract_n_dims_from_ttype(x_mv_type) > 0); bool is_polymorphic = current_select_type_block_type != nullptr; tmp = arr_descr->get_single_element(array, indices, x.n_args, - is_data_only, - ASRUtils::is_fixed_size_array(m_dims, n_dims) - && (is_bindc_array || - (v && ASR::is_a(*ASRUtils::get_asr_owner(&(v->base))) ) ), + array_t->m_physical_type == ASR::array_physical_typeType::PointerToDataArray, + array_t->m_physical_type == ASR::array_physical_typeType::FixedSizeArray, llvm_diminfo.p, is_polymorphic, current_select_type_block_type); } } @@ -2491,11 +2067,43 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor this->visit_expr(*x.m_shape); llvm::Value* shape = tmp; ASR::ttype_t* x_m_array_type = ASRUtils::expr_type(x.m_array); - ASR::ttype_t* asr_data_type = ASRUtils::duplicate_type_without_dims(al, - x_m_array_type, x_m_array_type->base.loc); - ASR::ttype_t* asr_shape_type = ASRUtils::get_contained_type(ASRUtils::expr_type(x.m_shape)); - llvm::Type* llvm_data_type = get_type_from_ttype_t_util(asr_data_type); - tmp = arr_descr->reshape(array, llvm_data_type, shape, asr_shape_type, module.get()); + ASR::array_physical_typeType array_physical_type = ASRUtils::extract_physical_type(x_m_array_type); + switch( array_physical_type ) { + case ASR::array_physical_typeType::DescriptorArray: { + ASR::ttype_t* asr_data_type = ASRUtils::duplicate_type_without_dims(al, + x_m_array_type, x_m_array_type->base.loc); + ASR::ttype_t* asr_shape_type = ASRUtils::get_contained_type(ASRUtils::expr_type(x.m_shape)); + llvm::Type* llvm_data_type = llvm_utils->get_type_from_ttype_t_util(asr_data_type, module.get()); + tmp = arr_descr->reshape(array, llvm_data_type, shape, asr_shape_type, module.get()); + break; + } + case ASR::array_physical_typeType::FixedSizeArray: { + llvm::BasicBlock &entry_block = builder->GetInsertBlock()->getParent()->getEntryBlock(); + llvm::IRBuilder<> builder0(context); + builder0.SetInsertPoint(&entry_block, entry_block.getFirstInsertionPt()); + llvm::Type* target_type = llvm_utils->get_type_from_ttype_t_util(x_m_array_type, module.get()); + llvm::Value *target = builder0.CreateAlloca( + target_type, nullptr, "fixed_size_reshaped_array"); + array = llvm_utils->create_gep(array, 0); + llvm::Value* target_ = llvm_utils->create_gep(target, 0); + ASR::dimension_t* asr_dims = nullptr; + size_t asr_n_dims = ASRUtils::extract_dimensions_from_ttype(x_m_array_type, asr_dims); + int64_t size = ASRUtils::get_fixed_size_of_array(asr_dims, asr_n_dims); + llvm::Type* llvm_data_type = llvm_utils->get_type_from_ttype_t_util(ASRUtils::type_get_past_array( + ASRUtils::type_get_past_allocatable(ASRUtils::type_get_past_pointer(x_m_array_type))), module.get()); + llvm::DataLayout data_layout(module.get()); + uint64_t data_size = data_layout.getTypeAllocSize(llvm_data_type); + llvm::Value* llvm_size = llvm::ConstantInt::get(context, llvm::APInt(32, size)); + llvm_size = builder->CreateMul(llvm_size, + llvm::ConstantInt::get(context, llvm::APInt(32, data_size))); + builder->CreateMemCpy(target_, llvm::MaybeAlign(), array, llvm::MaybeAlign(), llvm_size); + tmp = target; + break; + } + default: { + LCOMPILERS_ASSERT(false); + } + } } void lookup_EnumValue(const ASR::EnumValue_t& x) { @@ -2580,8 +2188,8 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } void visit_SizeOfType(const ASR::SizeOfType_t& x) { - llvm::Type* llvm_type = get_type_from_ttype_t_util(x.m_arg); - llvm::Type* llvm_type_size = get_type_from_ttype_t_util(x.m_type); + llvm::Type* llvm_type = llvm_utils->get_type_from_ttype_t_util(x.m_arg, module.get()); + llvm::Type* llvm_type_size = llvm_utils->get_type_from_ttype_t_util(x.m_type, module.get()); llvm::DataLayout data_layout(module.get()); int64_t type_size = data_layout.getTypeAllocSize(llvm_type); tmp = llvm::ConstantInt::get(llvm_type_size, llvm::APInt(64, type_size)); @@ -2671,7 +2279,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor int a_kind = down_cast(x.m_type)->m_kind; llvm::Type *type; int init_value_bits = 8*a_kind; - type = getIntType(a_kind); + type = llvm_utils->getIntType(a_kind); llvm::Constant *ptr = module->getOrInsertGlobal(x.m_name, type); if (!external) { @@ -2692,7 +2300,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor int a_kind = down_cast(x.m_type)->m_kind; llvm::Type *type; int init_value_bits = 8*a_kind; - type = getFPType(a_kind); + type = llvm_utils->getFPType(a_kind); llvm::Constant *ptr = module->getOrInsertGlobal(x.m_name, type); if (!external) { if (init_value) { @@ -2774,7 +2382,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } llvm_symtab[h] = ptr; } else { - llvm::Type* type = get_type_from_ttype_t_util(x.m_type); + llvm::Type* type = llvm_utils->get_type_from_ttype_t_util(x.m_type, module.get()); llvm::Constant *ptr = module->getOrInsertGlobal(x.m_name, type); if (!external) { @@ -2793,9 +2401,10 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor ASR::dimension_t* m_dims = nullptr; int n_dims = -1, a_kind = -1; bool is_array_type = false, is_malloc_array_type = false, is_list = false; - llvm::Type* x_ptr = get_type_from_ttype_t(x.m_type, nullptr, x.m_storage, is_array_type, - is_malloc_array_type, is_list, - m_dims, n_dims, a_kind); + llvm::Type* x_ptr = llvm_utils->get_type_from_ttype_t( + x.m_type, nullptr, x.m_storage, is_array_type, + is_malloc_array_type, is_list, + m_dims, n_dims, a_kind, module.get()); llvm::Constant *ptr = module->getOrInsertGlobal(x.m_name, x_ptr); if (!external) { @@ -2812,7 +2421,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor llvm_symtab[h] = ptr; } else if (x.m_type->type == ASR::ttypeType::List) { llvm::StructType* list_type = static_cast( - get_type_from_ttype_t_util(x.m_type)); + llvm_utils->get_type_from_ttype_t_util(x.m_type, module.get())); llvm::Constant *ptr = module->getOrInsertGlobal(x.m_name, list_type); module->getNamedGlobal(x.m_name)->setInitializer( llvm::ConstantStruct::get(list_type, @@ -2820,7 +2429,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor llvm_symtab[h] = ptr; } else if (x.m_type->type == ASR::ttypeType::Tuple) { llvm::StructType* tuple_type = static_cast( - get_type_from_ttype_t_util(x.m_type)); + llvm_utils->get_type_from_ttype_t_util(x.m_type, module.get())); llvm::Constant *ptr = module->getOrInsertGlobal(x.m_name, tuple_type); module->getNamedGlobal(x.m_name)->setInitializer( llvm::ConstantStruct::get(tuple_type, @@ -2828,7 +2437,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor llvm_symtab[h] = ptr; } else if(x.m_type->type == ASR::ttypeType::Dict) { llvm::StructType* dict_type = static_cast( - get_type_from_ttype_t_util(x.m_type)); + llvm_utils->get_type_from_ttype_t_util(x.m_type, module.get())); llvm::Constant *ptr = module->getOrInsertGlobal(x.m_name, dict_type); module->getNamedGlobal(x.m_name)->setInitializer( llvm::ConstantStruct::get(dict_type, @@ -2842,7 +2451,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } void visit_PointerNullConstant(const ASR::PointerNullConstant_t& x){ - llvm::Type* value_type = get_type_from_ttype_t_util(x.m_type); + llvm::Type* value_type = llvm_utils->get_type_from_ttype_t_util(x.m_type, module.get()); tmp = llvm::ConstantPointerNull::get(static_cast(value_type)); } @@ -2857,8 +2466,9 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor bool is_array_type = false, is_malloc_array_type = false, is_list = false; ASR::dimension_t* m_dims = nullptr; int n_dims = -1, a_kind = -1; - llvm::Type* value_type = get_type_from_ttype_t(x.m_type, nullptr, m_storage, is_array_type, - is_malloc_array_type, is_list, m_dims, n_dims, a_kind); + llvm::Type* value_type = llvm_utils->get_type_from_ttype_t( + x.m_type, nullptr, m_storage, is_array_type, + is_malloc_array_type, is_list, m_dims, n_dims, a_kind, module.get()); if( is_integer ) { int64_t min_value = INT64_MAX; int64_t max_value = INT64_MIN; @@ -3104,265 +2714,33 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor return false; } - int32_t get_type_size(ASR::ttype_t* asr_type, llvm::Type* llvm_type, - int32_t a_kind) { - if( LLVM::is_llvm_struct(asr_type) || - ASR::is_a(*asr_type) || - ASR::is_a(*asr_type) ) { - llvm::DataLayout data_layout(module.get()); - return data_layout.getTypeAllocSize(llvm_type); - } - return a_kind; - } - - llvm::Type* get_dict_type(ASR::ttype_t* asr_type) { - ASR::Dict_t* asr_dict = ASR::down_cast(asr_type); - bool is_local_array_type = false, is_local_malloc_array_type = false; - bool is_local_list = false; - ASR::dimension_t* local_m_dims = nullptr; - int local_n_dims = 0; - int local_a_kind = -1; - ASR::storage_typeType local_m_storage = ASR::storage_typeType::Default; - llvm::Type* key_llvm_type = get_type_from_ttype_t(asr_dict->m_key_type, nullptr, local_m_storage, - is_local_array_type, is_local_malloc_array_type, - is_local_list, local_m_dims, local_n_dims, - local_a_kind); - int32_t key_type_size = get_type_size(asr_dict->m_key_type, key_llvm_type, local_a_kind); - llvm::Type* value_llvm_type = get_type_from_ttype_t(asr_dict->m_value_type, nullptr, local_m_storage, - is_local_array_type, is_local_malloc_array_type, - is_local_list, local_m_dims, local_n_dims, - local_a_kind); - int32_t value_type_size = get_type_size(asr_dict->m_value_type, value_llvm_type, local_a_kind); - std::string key_type_code = ASRUtils::get_type_code(asr_dict->m_key_type); - std::string value_type_code = ASRUtils::get_type_code(asr_dict->m_value_type); - set_dict_api(asr_dict); - return llvm_utils->dict_api->get_dict_type(key_type_code, value_type_code, key_type_size, - value_type_size, key_llvm_type, value_llvm_type); - } - - llvm::Type* get_set_type(ASR::ttype_t* asr_type) { - ASR::Set_t* asr_set = ASR::down_cast(asr_type); - bool is_local_array_type = false, is_local_malloc_array_type = false; - bool is_local_list = false; - ASR::dimension_t* local_m_dims = nullptr; - int local_n_dims = 0; - int local_a_kind = -1; - ASR::storage_typeType local_m_storage = ASR::storage_typeType::Default; - llvm::Type* el_llvm_type = get_type_from_ttype_t(asr_set->m_type, nullptr, local_m_storage, - is_local_array_type, is_local_malloc_array_type, - is_local_list, local_m_dims, local_n_dims, - local_a_kind); - int32_t el_type_size = get_type_size(asr_set->m_type, el_llvm_type, local_a_kind); - std::string el_type_code = ASRUtils::get_type_code(asr_set->m_type); - return llvm_utils->set_api->get_set_type(el_type_code, el_type_size, el_llvm_type); - } - - llvm::Type* get_type_from_ttype_t(ASR::ttype_t* asr_type, - ASR::symbol_t *type_declaration, - ASR::storage_typeType m_storage, - bool& is_array_type, bool& is_malloc_array_type, - bool& is_list, ASR::dimension_t*& m_dims, - int& n_dims, int& a_kind, ASR::abiType m_abi=ASR::abiType::Source, - bool is_pointer=false) { - llvm::Type* llvm_type = nullptr; - bool is_allocatable = ASR::is_a(*asr_type); - asr_type = ASRUtils::type_get_past_allocatable(asr_type); - switch (asr_type->type) { - case ASR::ttypeType::Array: { - ASR::Array_t* v_type = down_cast(asr_type); - m_dims = v_type->m_dims; - n_dims = v_type->n_dims; - a_kind = ASRUtils::extract_kind_from_ttype_t(v_type->m_type); - if( m_abi == ASR::abiType::BindC ) { - if( ASRUtils::is_fixed_size_array(v_type->m_dims, v_type->n_dims) ) { - llvm_type = llvm::ArrayType::get(get_el_type(v_type->m_type), ASRUtils::get_fixed_size_of_array( - v_type->m_dims, v_type->n_dims)); - } else { - llvm_type = get_el_type(v_type->m_type)->getPointerTo(); - } - } else { - is_array_type = true; - llvm::Type* el_type = get_el_type(v_type->m_type); - if( is_allocatable ) { - is_malloc_array_type = true; - llvm_type = arr_descr->get_malloc_array_type(asr_type, el_type); - } else { - llvm_type = arr_descr->get_array_type(asr_type, el_type); - } - } - break ; - } - case (ASR::ttypeType::Integer) : { - ASR::Integer_t* v_type = down_cast(asr_type); - a_kind = v_type->m_kind; - llvm_type = getIntType(a_kind); - break; - } - case (ASR::ttypeType::UnsignedInteger) : { - ASR::UnsignedInteger_t* v_type = down_cast(asr_type); - a_kind = v_type->m_kind; - // LLVM does not distinguish signed and unsigned integer types - // Only integer operations can be signed/unsigned - llvm_type = getIntType(a_kind); - break; - } - case (ASR::ttypeType::Real) : { - ASR::Real_t* v_type = down_cast(asr_type); - a_kind = v_type->m_kind; - llvm_type = getFPType(a_kind); - break; - } - case (ASR::ttypeType::Complex) : { - ASR::Complex_t* v_type = down_cast(asr_type); - a_kind = v_type->m_kind; - llvm_type = getComplexType(a_kind); - break; - } - case (ASR::ttypeType::Character) : { - ASR::Character_t* v_type = down_cast(asr_type); - a_kind = v_type->m_kind; - llvm_type = character_type; - break; - } - case (ASR::ttypeType::Logical) : { - ASR::Logical_t* v_type = down_cast(asr_type); - a_kind = v_type->m_kind; - llvm_type = llvm::Type::getInt1Ty(context); - break; - } - case (ASR::ttypeType::Struct) : { - llvm_type = getStructType(asr_type, false); - break; - } - case (ASR::ttypeType::Class) : { - llvm_type = getClassType(asr_type, is_pointer); - break; - } - case (ASR::ttypeType::Union) : { - llvm_type = getUnionType(asr_type, false); - break; - } - case (ASR::ttypeType::Pointer) : { - ASR::ttype_t *t2 = ASR::down_cast(asr_type)->m_type; - bool is_pointer_ = ASR::is_a(*t2); - llvm_type = get_type_from_ttype_t(t2, nullptr, m_storage, is_array_type, - is_malloc_array_type, is_list, m_dims, - n_dims, a_kind, m_abi, is_pointer_); - if( !is_pointer_ ) { - llvm_type = llvm_type->getPointerTo(); - } - if (n_dims == 0 && ASR::is_a(*t2)){ - llvm_type = character_type; - } - break; - } - case (ASR::ttypeType::List) : { - is_list = true; - ASR::List_t* asr_list = ASR::down_cast(asr_type); - llvm::Type* el_llvm_type = get_type_from_ttype_t(asr_list->m_type, nullptr, m_storage, - is_array_type, is_malloc_array_type, - is_list, m_dims, n_dims, - a_kind, m_abi); - std::string el_type_code = ASRUtils::get_type_code(asr_list->m_type); - int32_t type_size = -1; - if( LLVM::is_llvm_struct(asr_list->m_type) || - ASR::is_a(*asr_list->m_type) || - ASR::is_a(*asr_list->m_type) ) { - llvm::DataLayout data_layout(module.get()); - type_size = data_layout.getTypeAllocSize(el_llvm_type); - } else { - type_size = a_kind; - } - llvm_type = list_api->get_list_type(el_llvm_type, el_type_code, type_size); - break; - } - case (ASR::ttypeType::Dict): { - llvm_type = get_dict_type(asr_type); - break; - } - case (ASR::ttypeType::Set): { - llvm_type = get_set_type(asr_type); - break; - } - case (ASR::ttypeType::Tuple) : { - ASR::Tuple_t* asr_tuple = ASR::down_cast(asr_type); - std::string type_code = ASRUtils::get_type_code(asr_tuple->m_type, - asr_tuple->n_type); - std::vector llvm_el_types; - for( size_t i = 0; i < asr_tuple->n_type; i++ ) { - bool is_local_array_type = false, is_local_malloc_array_type = false; - bool is_local_list = false; - ASR::dimension_t* local_m_dims = nullptr; - int local_n_dims = 0; - int local_a_kind = -1; - ASR::storage_typeType local_m_storage = ASR::storage_typeType::Default; - llvm_el_types.push_back(get_type_from_ttype_t(asr_tuple->m_type[i], nullptr, local_m_storage, - is_local_array_type, is_local_malloc_array_type, - is_local_list, local_m_dims, local_n_dims, local_a_kind, m_abi)); - } - llvm_type = tuple_api->get_tuple_type(type_code, llvm_el_types); - break; - } - case (ASR::ttypeType::CPtr) : { - llvm_type = llvm::Type::getVoidTy(context)->getPointerTo(); - break; - } - case (ASR::ttypeType::Enum) : { - llvm_type = llvm::Type::getInt32Ty(context); - break ; - } - case (ASR::ttypeType::Const) : { - llvm_type = get_type_from_ttype_t(ASRUtils::get_contained_type(asr_type), - nullptr, - m_storage, is_array_type, is_malloc_array_type, is_list, - m_dims, n_dims, a_kind, m_abi); - break; - } - case (ASR::ttypeType::FunctionType) : { - ASR::Function_t* fn = ASR::down_cast( - symbol_get_past_external(type_declaration)); - llvm_type = get_function_type(*fn)->getPointerTo(); - break; - } - default : - throw CodeGenError("Support for type " + ASRUtils::type_to_str(asr_type) + - " not yet implemented."); - } - return llvm_type; - } - - inline llvm::Type* get_type_from_ttype_t_util(ASR::ttype_t* asr_type, ASR::abiType asr_abi=ASR::abiType::Source) { - ASR::storage_typeType m_storage_local = ASR::storage_typeType::Default; - bool is_array_type_local, is_malloc_array_type_local; - bool is_list_local; - ASR::dimension_t* m_dims_local; - int n_dims_local, a_kind_local; - return get_type_from_ttype_t(asr_type, nullptr, m_storage_local, is_array_type_local, - is_malloc_array_type_local, is_list_local, - m_dims_local, n_dims_local, a_kind_local, asr_abi); - } - - void fill_array_details_(llvm::Value* ptr, ASR::dimension_t* m_dims, + void fill_array_details_(llvm::Value* ptr, llvm::Type* type_, ASR::dimension_t* m_dims, size_t n_dims, bool is_malloc_array_type, bool is_array_type, bool is_list, ASR::ttype_t* m_type, bool is_data_only=false) { - if( is_malloc_array_type && - m_type->type != ASR::ttypeType::Pointer && + ASR::ttype_t* asr_data_type = ASRUtils::type_get_past_array( + ASRUtils::type_get_past_pointer( + ASRUtils::type_get_past_allocatable(m_type))); + llvm::Type* llvm_data_type = llvm_utils->get_type_from_ttype_t_util(asr_data_type, module.get()); + llvm::Value* ptr_ = nullptr; + if( is_malloc_array_type && m_type->type != ASR::ttypeType::Pointer && !is_list && !is_data_only ) { - arr_descr->fill_dimension_descriptor(ptr, n_dims); + ptr_ = builder->CreateAlloca(type_, nullptr, "arr_desc"); + arr_descr->fill_dimension_descriptor(ptr_, n_dims); } if( is_array_type && !is_malloc_array_type && m_type->type != ASR::ttypeType::Pointer && !is_list ) { - ASR::ttype_t* asr_data_type = ASRUtils::type_get_past_pointer( - ASRUtils::type_get_past_allocatable(ASRUtils::type_get_past_array(m_type))); - llvm::Type* llvm_data_type = get_type_from_ttype_t_util(asr_data_type); fill_array_details(ptr, llvm_data_type, m_dims, n_dims, is_data_only); } if( is_array_type && is_malloc_array_type && m_type->type != ASR::ttypeType::Pointer && !is_list && !is_data_only ) { // Set allocatable arrays as unallocated - arr_descr->set_is_allocated_flag(ptr, false); + LCOMPILERS_ASSERT(ptr_ != nullptr); + arr_descr->reset_is_allocated_flag(ptr_, llvm_data_type); + } + if( ptr_ ) { + LLVM::CreateStore(*builder, ptr_, ptr); } } @@ -3400,9 +2778,9 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor // Assume that struct member array is not allocatable ASR::dimension_t* m_dims = nullptr; size_t n_dims = ASRUtils::extract_dimensions_from_ttype(symbol_type, m_dims); - bool is_data_only = (ASRUtils::symbol_abi(item.second) == ASR::abiType::BindC && - ASRUtils::is_fixed_size_array(m_dims, n_dims)); - fill_array_details_(ptr_member, m_dims, n_dims, false, true, false, symbol_type, is_data_only); + bool is_data_only = (ASRUtils::extract_physical_type(symbol_type) == ASR::array_physical_typeType::PointerToDataArray || + ASRUtils::extract_physical_type(symbol_type) == ASR::array_physical_typeType::FixedSizeArray); + fill_array_details_(ptr_member, nullptr, m_dims, n_dims, false, true, false, symbol_type, is_data_only); } else if( ASR::is_a(*symbol_type) ) { allocate_array_members_of_struct(ptr_member, symbol_type); } @@ -3417,7 +2795,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor return ; } if( type2vtabtype.find(struct_type_sym) == type2vtabtype.end() ) { - std::vector type_vec = {getIntType(8)}; + std::vector type_vec = {llvm_utils->getIntType(8)}; type2vtabtype[struct_type_sym] = llvm::StructType::create( context, type_vec, std::string("__vtab_") + @@ -3426,7 +2804,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor llvm::Type* vtab_type = type2vtabtype[struct_type_sym]; llvm::Value* vtab_obj = builder->CreateAlloca(vtab_type); llvm::Value* struct_type_hash_ptr = llvm_utils->create_gep(vtab_obj, 0); - llvm::Value* struct_type_hash = llvm::ConstantInt::get(getIntType(8), + llvm::Value* struct_type_hash = llvm::ConstantInt::get(llvm_utils->getIntType(8), llvm::APInt(64, get_class_hash(struct_type_sym))); builder->CreateStore(struct_type_hash, struct_type_hash_ptr); type2vtab[struct_type_sym][symtab] = vtab_obj; @@ -3520,9 +2898,12 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor if (v->m_intent == intent_local || v->m_intent == intent_return_var || !v->m_intent) { - type = get_type_from_ttype_t(v->m_type, v->m_type_declaration, v->m_storage, is_array_type, - is_malloc_array_type, is_list, m_dims, n_dims, - a_kind); + type = llvm_utils->get_type_from_ttype_t( + v->m_type, v->m_type_declaration, v->m_storage, is_array_type, + is_malloc_array_type, is_list, m_dims, n_dims, a_kind, module.get()); + llvm::Type* type_ = llvm_utils->get_type_from_ttype_t_util( + ASRUtils::type_get_past_allocatable(v->m_type), module.get(), v->m_abi); + /* * The following if block is used for converting any * general array descriptor to a pointer type which @@ -3557,7 +2938,27 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } } } - llvm::AllocaInst *ptr = builder->CreateAlloca(type, nullptr, v->m_name); + llvm::Value* array_size = nullptr; + if( ASRUtils::is_array(v->m_type) && + ASRUtils::extract_physical_type(v->m_type) == + ASR::array_physical_typeType::PointerToDataArray && + !LLVM::is_llvm_pointer(*v->m_type) ) { + type = llvm_utils->get_type_from_ttype_t( + ASRUtils::type_get_past_array(v->m_type), + v->m_type_declaration, v->m_storage, is_array_type, + is_malloc_array_type, is_list, m_dims, n_dims, a_kind, module.get()); + ASR::dimension_t* m_dims = nullptr; + size_t n_dims = ASRUtils::extract_dimensions_from_ttype(v->m_type, m_dims); + array_size = llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), llvm::APInt(32, 1)); + int ptr_loads_copy = ptr_loads; + ptr_loads = 2; + for( size_t i = 0; i < n_dims; i++ ) { + this->visit_expr_wrapper(m_dims[i].m_length, true); + array_size = builder->CreateMul(array_size, tmp); + } + ptr_loads = ptr_loads_copy; + } + llvm::AllocaInst *ptr = builder->CreateAlloca(type, array_size, v->m_name); if( ASR::is_a(*v->m_type) && !(is_array_type || is_malloc_array_type) ) { allocate_array_members_of_struct(ptr, v->m_type); @@ -3596,9 +2997,12 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } llvm_symtab[h] = ptr; - fill_array_details_(ptr, m_dims, n_dims, - is_malloc_array_type, - is_array_type, is_list, v->m_type); + if( ASRUtils::is_array(v->m_type) && + ASRUtils::extract_physical_type(v->m_type) == + ASR::array_physical_typeType::DescriptorArray ) { + fill_array_details_(ptr, type_, m_dims, n_dims, + is_malloc_array_type, is_array_type, is_list, v->m_type); + } ASR::expr_t* init_expr = v->m_symbolic_value; if( !ASR::is_a(*v->m_type) ) { for( size_t i = 0; i < v->n_dependencies; i++ ) { @@ -3621,10 +3025,29 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor this->visit_expr_wrapper(v->m_symbolic_value, true); } llvm::Value *init_value = tmp; - if (ASR::is_a(*v->m_symbolic_value) || ( v->m_value && ASR::is_a(*v->m_value) )) { - target_var = arr_descr->get_pointer_to_data(target_var); + if( ASRUtils::is_array(v->m_type) && + ASRUtils::is_array(ASRUtils::expr_type(v->m_symbolic_value)) && + (ASR::is_a(*v->m_symbolic_value) || + (v->m_value && ASR::is_a(*v->m_value))) ) { + ASR::array_physical_typeType target_ptype = ASRUtils::extract_physical_type(v->m_type); + if( target_ptype == ASR::array_physical_typeType::DescriptorArray ) { + target_var = arr_descr->get_pointer_to_data(target_var); + builder->CreateStore(init_value, target_var); + } else if( target_ptype == ASR::array_physical_typeType::FixedSizeArray ) { + llvm::Value* arg_size = llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), + llvm::APInt(32, ASR::down_cast(v->m_value)->n_args)); + llvm::Type* llvm_data_type = llvm_utils->get_type_from_ttype_t_util( + ASRUtils::type_get_past_array(ASRUtils::expr_type(v->m_value)), module.get()); + llvm::DataLayout data_layout(module.get()); + size_t dt_size = data_layout.getTypeAllocSize(llvm_data_type); + arg_size = builder->CreateMul(llvm::ConstantInt::get( + llvm::Type::getInt32Ty(context), llvm::APInt(32, dt_size)), arg_size); + builder->CreateMemCpy(llvm_utils->create_gep(target_var, 0), + llvm::MaybeAlign(), init_value, llvm::MaybeAlign(), arg_size); + } + } else { + builder->CreateStore(init_value, target_var); } - builder->CreateStore(init_value, target_var); } else { if (is_a(*v->m_type) && !is_array_type && !is_list) { ASR::Character_t *t = down_cast(v->m_type); @@ -3636,329 +3059,30 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor llvm::Value *init_value = builder->CreateGlobalStringPtr(s2c(al, empty)); builder->CreateStore(init_value, target_var); } else if (strlen == -2) { - // Allocatable string. Initialize to `nullptr` (unallocated) - llvm::Value *init_value = llvm::Constant::getNullValue(type); - builder->CreateStore(init_value, target_var); - } else if (strlen == -3) { - LCOMPILERS_ASSERT(t->m_len_expr) - this->visit_expr(*t->m_len_expr); - llvm::Value *arg_size = tmp; - arg_size = builder->CreateAdd(arg_size, llvm::ConstantInt::get(context, llvm::APInt(32, 1))); - // TODO: this temporary string is never deallocated (leaks memory) - llvm::Value *init_value = LLVM::lfortran_malloc(context, *module, *builder, arg_size); - string_init(context, *module, *builder, arg_size, init_value); - builder->CreateStore(init_value, target_var); - } else { - throw CodeGenError("Unsupported len value in ASR"); - } - } else if (is_list) { - ASR::List_t* asr_list = ASR::down_cast(v->m_type); - std::string type_code = ASRUtils::get_type_code(asr_list->m_type); - list_api->list_init(type_code, ptr, *module); - } - } - } - } - } - } - - llvm::Type* get_arg_type_from_ttype_t(ASR::ttype_t* asr_type, - ASR::symbol_t *type_declaration, - ASR::abiType m_abi, ASR::abiType arg_m_abi, - ASR::storage_typeType m_storage, - bool arg_m_value_attr, - int& n_dims, int& a_kind, bool& is_array_type, - ASR::intentType arg_intent, bool get_pointer=true) { - llvm::Type* type = nullptr; - bool is_allocatable = ASR::is_a(*asr_type); - asr_type = ASRUtils::type_get_past_allocatable(asr_type); - switch (asr_type->type) { - case ASR::ttypeType::Array: { - ASR::Array_t* v_type = down_cast(asr_type); - type = nullptr; - if( ASR::is_a(*v_type->m_type) ) { - ASR::Complex_t* complex_t = ASR::down_cast(v_type->m_type); - if (m_abi != ASR::abiType::BindC && - (!ASRUtils::is_dimension_empty(v_type->m_dims, v_type->n_dims))) { - type = getComplexType(complex_t->m_kind, true); - } - } - if( type != nullptr ) { - break; - } - - if (m_abi == ASR::abiType::BindC || - (!ASRUtils::is_dimension_empty(v_type->m_dims, v_type->n_dims))) { - // Bind(C) arrays are represened as a pointer - type = get_type_from_ttype_t_util(v_type->m_type, arg_m_abi)->getPointerTo(); - } else { - is_array_type = true; - llvm::Type* el_type = get_el_type(v_type->m_type); - if( is_allocatable ) { - type = arr_descr->get_malloc_array_type(asr_type, el_type, get_pointer); - } else { - type = arr_descr->get_array_type(asr_type, el_type, get_pointer); - } - } - break; - } - case (ASR::ttypeType::Integer) : { - ASR::Integer_t* v_type = down_cast(asr_type); - a_kind = v_type->m_kind; - if (arg_m_abi == ASR::abiType::BindC - && arg_m_value_attr) { - type = getIntType(a_kind, false); - } else { - type = getIntType(a_kind, true); - } - break; - } - case (ASR::ttypeType::UnsignedInteger) : { - ASR::UnsignedInteger_t* v_type = down_cast(asr_type); - a_kind = v_type->m_kind; - if (arg_m_abi == ASR::abiType::BindC - && arg_m_value_attr) { - type = getIntType(a_kind, false); - } else { - type = getIntType(a_kind, true); - } - break; - } - case (ASR::ttypeType::Pointer) : { - ASR::ttype_t *t2 = ASRUtils::type_get_past_pointer(asr_type); - bool is_pointer_ = ASR::is_a(*t2); - type = get_arg_type_from_ttype_t(t2, nullptr, m_abi, arg_m_abi, - m_storage, arg_m_value_attr, n_dims, a_kind, - is_array_type, arg_intent, get_pointer); - if( !is_pointer_ ) { - type = type->getPointerTo(); - } - break; - } - case (ASR::ttypeType::Const) : { - ASR::ttype_t *t2 = ASRUtils::get_contained_type(asr_type); - type = get_arg_type_from_ttype_t(t2, nullptr, m_abi, arg_m_abi, - m_storage, arg_m_value_attr, n_dims, a_kind, - is_array_type, arg_intent, get_pointer); - break; - } - case (ASR::ttypeType::Real) : { - ASR::Real_t* v_type = down_cast(asr_type); - a_kind = v_type->m_kind; - if (arg_m_abi == ASR::abiType::BindC - && arg_m_value_attr) { - type = getFPType(a_kind, false); - } else { - type = getFPType(a_kind, true); - } - break; - } - case (ASR::ttypeType::Complex) : { - ASR::Complex_t* v_type = down_cast(asr_type); - a_kind = v_type->m_kind; - if (m_abi != ASR::abiType::BindC) { - type = getComplexType(a_kind, true); - } else { - if (arg_m_abi == ASR::abiType::BindC - && arg_m_value_attr) { - if (a_kind == 4) { - if (compiler_options.platform == Platform::Windows) { - // type_fx2 is i64 - llvm::Type* type_fx2 = llvm::Type::getInt64Ty(context); - type = type_fx2; - } else if (compiler_options.platform == Platform::macOS_ARM) { - // type_fx2 is [2 x float] - llvm::Type* type_fx2 = llvm::ArrayType::get(llvm::Type::getFloatTy(context), 2); - type = type_fx2; - } else { - // type_fx2 is <2 x float> - llvm::Type* type_fx2 = FIXED_VECTOR_TYPE::get(llvm::Type::getFloatTy(context), 2); - type = type_fx2; - } - } else { - LCOMPILERS_ASSERT(a_kind == 8) - if (compiler_options.platform == Platform::Windows) { - // 128 bit aggregate type is passed by reference - type = getComplexType(a_kind, true); + // Allocatable string. Initialize to `nullptr` (unallocated) + llvm::Value *init_value = llvm::Constant::getNullValue(type); + builder->CreateStore(init_value, target_var); + } else if (strlen == -3) { + LCOMPILERS_ASSERT(t->m_len_expr) + this->visit_expr(*t->m_len_expr); + llvm::Value *arg_size = tmp; + arg_size = builder->CreateAdd(arg_size, llvm::ConstantInt::get(context, llvm::APInt(32, 1))); + // TODO: this temporary string is never deallocated (leaks memory) + llvm::Value *init_value = LLVM::lfortran_malloc(context, *module, *builder, arg_size); + string_init(context, *module, *builder, arg_size, init_value); + builder->CreateStore(init_value, target_var); } else { - // Pass by value - type = getComplexType(a_kind, false); + throw CodeGenError("Unsupported len value in ASR"); } + } else if (is_list) { + ASR::List_t* asr_list = ASR::down_cast(v->m_type); + std::string type_code = ASRUtils::get_type_code(asr_list->m_type); + list_api->list_init(type_code, ptr, *module); } - } else { - type = getComplexType(a_kind, true); - } - } - break; - } - case (ASR::ttypeType::Character) : { - ASR::Character_t* v_type = down_cast(asr_type); - a_kind = v_type->m_kind; - if (arg_m_abi == ASR::abiType::BindC) { - type = character_type; - } else { - type = character_type->getPointerTo(); - } - break; - } - case (ASR::ttypeType::Logical) : { - ASR::Logical_t* v_type = down_cast(asr_type); - a_kind = v_type->m_kind; - if (arg_m_abi == ASR::abiType::BindC - && arg_m_value_attr) { - type = llvm::Type::getInt1Ty(context); - } else { - type = llvm::Type::getInt1PtrTy(context); - } - break; - } - case (ASR::ttypeType::Struct) : { - type = getStructType(asr_type, true); - break; - } - case (ASR::ttypeType::Class) : { - type = getClassType(asr_type, true)->getPointerTo(); - break; - } - case (ASR::ttypeType::CPtr) : { - type = llvm::Type::getVoidTy(context)->getPointerTo(); - break; - } - case (ASR::ttypeType::Tuple) : { - type = get_type_from_ttype_t_util(asr_type)->getPointerTo(); - break; - } - case (ASR::ttypeType::List) : { - bool is_array_type = false, is_malloc_array_type = false; - bool is_list = true; - ASR::dimension_t *m_dims = nullptr; - ASR::List_t* asr_list = ASR::down_cast(asr_type); - llvm::Type* el_llvm_type = get_type_from_ttype_t(asr_list->m_type, nullptr, m_storage, - is_array_type, - is_malloc_array_type, - is_list, m_dims, n_dims, - a_kind, m_abi); - int32_t type_size = -1; - if( LLVM::is_llvm_struct(asr_list->m_type) || - ASR::is_a(*asr_list->m_type) || - ASR::is_a(*asr_list->m_type) ) { - llvm::DataLayout data_layout(module.get()); - type_size = data_layout.getTypeAllocSize(el_llvm_type); - } else { - type_size = a_kind; - } - std::string el_type_code = ASRUtils::get_type_code(asr_list->m_type); - type = list_api->get_list_type(el_llvm_type, el_type_code, type_size)->getPointerTo(); - break; - } - case ASR::ttypeType::Enum: { - if (arg_m_abi == ASR::abiType::BindC - && arg_m_value_attr) { - type = llvm::Type::getInt32Ty(context); - } else { - type = llvm::Type::getInt32PtrTy(context); - } - break ; - } - case (ASR::ttypeType::Dict): { - ASR::Dict_t* asr_dict = ASR::down_cast(asr_type); - std::string key_type_code = ASRUtils::get_type_code(asr_dict->m_key_type); - std::string value_type_code = ASRUtils::get_type_code(asr_dict->m_value_type); - - bool is_array_type = false, is_malloc_array_type = false; - bool is_list = false; - ASR::dimension_t* m_dims = nullptr; - llvm::Type* key_llvm_type = get_type_from_ttype_t(asr_dict->m_key_type, type_declaration, m_storage, - is_array_type, - is_malloc_array_type, - is_list, m_dims, n_dims, - a_kind, m_abi); - llvm::Type* value_llvm_type = get_type_from_ttype_t(asr_dict->m_value_type, type_declaration, m_storage, - is_array_type, - is_malloc_array_type, - is_list, m_dims, n_dims, - a_kind, m_abi); - int32_t key_type_size = get_type_size(asr_dict->m_key_type, key_llvm_type, a_kind); - int32_t value_type_size = get_type_size(asr_dict->m_value_type, value_llvm_type, a_kind); - set_dict_api(asr_dict); - type = llvm_utils->dict_api->get_dict_type(key_type_code, value_type_code, - key_type_size, value_type_size, - key_llvm_type, value_llvm_type)->getPointerTo(); - break; - } - case ASR::ttypeType::FunctionType: { - ASR::Function_t* fn = ASR::down_cast( - symbol_get_past_external(type_declaration)); - type = get_function_type(*fn)->getPointerTo(); - break ; - } - default : - LCOMPILERS_ASSERT(false); - } - return type; - } - - template - std::vector convert_args(const T &x) { - std::vector args; - for (size_t i=0; i(*symbol_get_past_external( - ASR::down_cast(x.m_args[i])->m_v))) { - ASR::Variable_t *arg = EXPR2VAR(x.m_args[i]); - LCOMPILERS_ASSERT(is_arg_dummy(arg->m_intent)); - // We pass all arguments as pointers for now, - // except bind(C) value arguments that are passed by value - llvm::Type *type = nullptr, *type_original = nullptr; - int n_dims = 0, a_kind = 4; - bool is_array_type = false; - type_original = get_arg_type_from_ttype_t(arg->m_type, - arg->m_type_declaration, - ASRUtils::get_FunctionType(x)->m_abi, - arg->m_abi, arg->m_storage, arg->m_value_attr, - n_dims, a_kind, is_array_type, arg->m_intent, - false); - if( is_array_type ) { - type = type_original->getPointerTo(); - } else { - type = type_original; - } - if( arg->m_intent == ASRUtils::intent_out && - ASR::is_a(*arg->m_type) ) { - type = type->getPointerTo(); - } - std::uint32_t m_h; - std::string m_name = std::string(x.m_name); - if( x.class_type == ASR::symbolType::Function ) { - ASR::Function_t* _func = (ASR::Function_t*)(&(x.base)); - m_h = get_hash((ASR::asr_t*)_func); - } - if( is_array_type && arg->m_type->type != ASR::ttypeType::Pointer ) { - if( ASRUtils::get_FunctionType(x)->m_abi == ASR::abiType::Source ) { - llvm::Type* orig_type = type_original; - type = arr_descr->get_argument_type(orig_type, m_h, arg->m_name, arr_arg_type_cache); - is_array_type = false; - } else if( ASRUtils::get_FunctionType(x)->m_abi == ASR::abiType::Intrinsic && - fname2arg_type.find(m_name) != fname2arg_type.end()) { - type = fname2arg_type[m_name].second; - is_array_type = false; } } - args.push_back(type); - } else if (is_a(*symbol_get_past_external( - ASR::down_cast(x.m_args[i])->m_v))) { - /* This is likely a procedure passed as an argument. For the - type, we need to pass in a function pointer with the - correct call signature. */ - ASR::Function_t* fn = ASR::down_cast( - symbol_get_past_external(ASR::down_cast( - x.m_args[i])->m_v)); - llvm::Type* type = get_function_type(*fn)->getPointerTo(); - args.push_back(type); - } else { - throw CodeGenError("Argument type not implemented"); } } - return args; } bool is_function_variable(const ASR::Variable_t &v) { @@ -4003,7 +3127,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor llvm_arg.setName(arg_s); llvm_symtab_fn_arg[h] = &llvm_arg; if (llvm_symtab_fn.find(h) == llvm_symtab_fn.end()) { - llvm::FunctionType* fntype = get_function_type(*arg); + llvm::FunctionType* fntype = llvm_utils->get_function_type(*arg, module.get()); llvm::Function* fn = llvm::Function::Create(fntype, llvm::Function::ExternalLinkage, arg->m_name, module.get()); llvm_symtab_fn[h] = fn; } @@ -4057,7 +3181,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor */ F = llvm_symtab_fn[h]; } else { - llvm::FunctionType* function_type = get_function_type(x); + llvm::FunctionType* function_type = llvm_utils->get_function_type(x, module.get()); if( ASRUtils::get_FunctionType(x)->m_deftype == ASR::deftypeType::Interface ) { ASR::FunctionType_t* asr_function_type = ASRUtils::get_FunctionType(x); for( size_t i = 0; i < asr_function_type->n_arg_types; i++ ) { @@ -4111,7 +3235,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor ASR::Var_t *arg = down_cast(x.m_args[i]); if ( arg->m_v == item.second ) { interface_as_arg = true; - llvm::FunctionType* fntype = get_function_type(*v); + llvm::FunctionType* fntype = llvm_utils->get_function_type(*v, module.get()); llvm::Function* fn = llvm::Function::Create(fntype, llvm::Function::ExternalLinkage, v->m_name, module.get()); uint32_t hash = get_hash((ASR::asr_t*)v); llvm_symtab_fn[hash] = fn; @@ -4126,171 +3250,6 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } } - - llvm::FunctionType* get_function_type(const ASR::Function_t &x) { - llvm::Type *return_type; - if (x.m_return_var) { - ASR::ttype_t *return_var_type0 = EXPR2VAR(x.m_return_var)->m_type; - ASR::ttypeType return_var_type = return_var_type0->type; - switch (return_var_type) { - case (ASR::ttypeType::Integer) : { - int a_kind = down_cast(return_var_type0)->m_kind; - return_type = getIntType(a_kind); - break; - } - case (ASR::ttypeType::UnsignedInteger) : { - int a_kind = down_cast(return_var_type0)->m_kind; - return_type = getIntType(a_kind); - break; - } - case (ASR::ttypeType::Real) : { - int a_kind = down_cast(return_var_type0)->m_kind; - return_type = getFPType(a_kind); - break; - } - case (ASR::ttypeType::Complex) : { - int a_kind = down_cast(return_var_type0)->m_kind; - if (a_kind == 4) { - if (ASRUtils::get_FunctionType(x)->m_abi == ASR::abiType::BindC) { - if (compiler_options.platform == Platform::Windows) { - // i64 - return_type = llvm::Type::getInt64Ty(context); - } else if (compiler_options.platform == Platform::macOS_ARM) { - // {float, float} - return_type = getComplexType(a_kind); - } else { - // <2 x float> - return_type = FIXED_VECTOR_TYPE::get(llvm::Type::getFloatTy(context), 2); - } - } else { - return_type = getComplexType(a_kind); - } - } else { - LCOMPILERS_ASSERT(a_kind == 8) - if (ASRUtils::get_FunctionType(x)->m_abi == ASR::abiType::BindC) { - if (compiler_options.platform == Platform::Windows) { - // pass as subroutine - return_type = getComplexType(a_kind, true); - std::vector args = convert_args(x); - args.insert(args.begin(), return_type); - llvm::FunctionType *function_type = llvm::FunctionType::get( - llvm::Type::getVoidTy(context), args, false); - return function_type; - } else { - return_type = getComplexType(a_kind); - } - } else { - return_type = getComplexType(a_kind); - } - } - break; - } - case (ASR::ttypeType::Character) : - return_type = character_type; - break; - case (ASR::ttypeType::Logical) : - return_type = llvm::Type::getInt1Ty(context); - break; - case (ASR::ttypeType::CPtr) : - return_type = llvm::Type::getVoidTy(context)->getPointerTo(); - break; - case (ASR::ttypeType::Const) : { - return_type = get_type_from_ttype_t_util(ASRUtils::get_contained_type(return_var_type0)); - break; - } - case (ASR::ttypeType::Pointer) : { - return_type = get_type_from_ttype_t_util(ASRUtils::get_contained_type(return_var_type0))->getPointerTo(); - break; - } - case (ASR::ttypeType::Allocatable) : { - // TODO: Do getPointerTo as well. - return_type = get_type_from_ttype_t_util(ASRUtils::get_contained_type(return_var_type0)); - break; - } - case (ASR::ttypeType::Struct) : - throw CodeGenError("Struct return type not implemented yet"); - break; - case (ASR::ttypeType::Tuple) : { - ASR::Tuple_t* asr_tuple = ASR::down_cast(return_var_type0); - std::string type_code = ASRUtils::get_type_code(asr_tuple->m_type, - asr_tuple->n_type); - std::vector llvm_el_types; - for( size_t i = 0; i < asr_tuple->n_type; i++ ) { - bool is_local_array_type = false, is_local_malloc_array_type = false; - bool is_local_list = false; - ASR::dimension_t* local_m_dims = nullptr; - int local_n_dims = 0; - int local_a_kind = -1; - ASR::storage_typeType local_m_storage = ASR::storage_typeType::Default; - llvm_el_types.push_back(get_type_from_ttype_t(asr_tuple->m_type[i], nullptr, local_m_storage, - is_local_array_type, is_local_malloc_array_type, - is_local_list, local_m_dims, local_n_dims, local_a_kind)); - } - return_type = tuple_api->get_tuple_type(type_code, llvm_el_types); - break; - } - case (ASR::ttypeType::List) : { - bool is_array_type = false, is_malloc_array_type = false; - bool is_list = true; - ASR::dimension_t *m_dims = nullptr; - ASR::storage_typeType m_storage = ASR::storage_typeType::Default; - int n_dims = 0, a_kind = -1; - ASR::List_t* asr_list = ASR::down_cast(return_var_type0); - llvm::Type* el_llvm_type = get_type_from_ttype_t(asr_list->m_type, nullptr, m_storage, - is_array_type, - is_malloc_array_type, - is_list, m_dims, n_dims, - a_kind); - int32_t type_size = -1; - if( LLVM::is_llvm_struct(asr_list->m_type) || - ASR::is_a(*asr_list->m_type) || - ASR::is_a(*asr_list->m_type) ) { - llvm::DataLayout data_layout(module.get()); - type_size = data_layout.getTypeAllocSize(el_llvm_type); - } else { - type_size = a_kind; - } - std::string el_type_code = ASRUtils::get_type_code(asr_list->m_type); - return_type = list_api->get_list_type(el_llvm_type, el_type_code, type_size); - break; - } - case (ASR::ttypeType::Dict) : { - ASR::Dict_t* asr_dict = ASR::down_cast(return_var_type0); - std::string key_type_code = ASRUtils::get_type_code(asr_dict->m_key_type); - std::string value_type_code = ASRUtils::get_type_code(asr_dict->m_value_type); - - bool is_local_array_type = false, is_local_malloc_array_type = false; - bool is_local_list = false; - ASR::dimension_t* local_m_dims = nullptr; - ASR::storage_typeType local_m_storage = ASR::storage_typeType::Default; - int local_n_dims = 0, local_a_kind = -1; - - llvm::Type* key_llvm_type = get_type_from_ttype_t(asr_dict->m_key_type, - nullptr, local_m_storage, is_local_array_type, is_local_malloc_array_type, - is_local_list, local_m_dims, local_n_dims,local_a_kind); - llvm::Type* value_llvm_type = get_type_from_ttype_t(asr_dict->m_value_type, - nullptr, local_m_storage,is_local_array_type, is_local_malloc_array_type, - is_local_list, local_m_dims, local_n_dims,local_a_kind); - int32_t key_type_size = get_type_size(asr_dict->m_key_type, key_llvm_type, local_a_kind); - int32_t value_type_size = get_type_size(asr_dict->m_value_type, value_llvm_type, local_a_kind); - - set_dict_api(asr_dict); - - return_type = llvm_utils->dict_api->get_dict_type(key_type_code, value_type_code, key_type_size,value_type_size, key_llvm_type, value_llvm_type); - break; - } - default : - throw CodeGenError("Type not implemented " + std::to_string(return_var_type)); - } - } else { - return_type = llvm::Type::getVoidTy(context); - } - std::vector args = convert_args(x); - llvm::FunctionType *function_type = llvm::FunctionType::get( - return_type, args, false); - return function_type; - } - inline void define_function_entry(const ASR::Function_t& x) { uint32_t h = get_hash((ASR::asr_t*)&x); parent_function = &x; @@ -4448,7 +3407,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor tmp = CreateLoad(tmp); } ASR::ttype_t* arg_type = ASRUtils::get_contained_type(ASRUtils::expr_type(x.m_arg)); - if( arr_descr->is_array(arg_type) ) { + if( ASRUtils::is_array(arg_type) ) { tmp = CreateLoad(arr_descr->get_pointer_to_data(tmp)); } tmp = builder->CreateBitCast(tmp, @@ -4467,9 +3426,23 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor !ASR::is_a(*asr_type)) { llvm_tmp = CreateLoad(llvm_tmp); } - if( arr_descr->is_array(asr_type) && + + if( ASRUtils::is_array(asr_type) && !ASR::is_a(*asr_type) ) { - llvm_tmp = CreateLoad(arr_descr->get_pointer_to_data(llvm_tmp)); + ASR::array_physical_typeType physical_type = ASRUtils::extract_physical_type(asr_type); + switch( physical_type ) { + case ASR::array_physical_typeType::DescriptorArray: { + llvm_tmp = CreateLoad(arr_descr->get_pointer_to_data(llvm_tmp)); + break; + } + case ASR::array_physical_typeType::FixedSizeArray: { + llvm_tmp = llvm_utils->create_gep(llvm_tmp, 0); + break; + } + default: { + LCOMPILERS_ASSERT(false); + } + } } // // TODO: refactor this into a function, it is being used a few times @@ -4536,7 +3509,8 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor llvm_shape = tmp; } ASR::ttype_t* fptr_type = ASRUtils::expr_type(fptr); - llvm::Type* llvm_fptr_type = get_type_from_ttype_t_util(ASRUtils::get_contained_type(fptr_type)); + llvm::Type* llvm_fptr_type = llvm_utils->get_type_from_ttype_t_util( + ASRUtils::get_contained_type(fptr_type), module.get()); llvm::Value* fptr_array = builder->CreateAlloca(llvm_fptr_type); builder->CreateStore(llvm::ConstantInt::get(context, llvm::APInt(32, 0)), arr_descr->get_offset(fptr_array, false)); @@ -4551,11 +3525,12 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor builder->CreateStore(fptr_array, llvm_fptr); llvm_fptr = fptr_array; ASR::ttype_t* fptr_data_type = ASRUtils::duplicate_type_without_dims(al, ASRUtils::get_contained_type(fptr_type), fptr_type->base.loc); - llvm::Type* llvm_fptr_data_type = get_type_from_ttype_t_util(fptr_data_type); + llvm::Type* llvm_fptr_data_type = llvm_utils->get_type_from_ttype_t_util(fptr_data_type, module.get()); llvm::Value* fptr_data = arr_descr->get_pointer_to_data(llvm_fptr); llvm::Value* fptr_des = arr_descr->get_pointer_to_dimension_descriptor_array(llvm_fptr); llvm::Value* shape_data = llvm_shape; - if( llvm_shape && !ASR::is_a(*shape) && arr_descr->is_array(asr_shape_type) ) { + if( llvm_shape && (ASRUtils::extract_physical_type(asr_shape_type) == + ASR::array_physical_typeType::DescriptorArray) ) { shape_data = CreateLoad(arr_descr->get_pointer_to_data(llvm_shape)); } llvm_cptr = builder->CreateBitCast(llvm_cptr, llvm_fptr_data_type->getPointerTo()); @@ -4583,7 +3558,13 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor ptr_loads = ptr_loads_copy; new_lb = tmp; } - llvm::Value* new_ub = shape_data ? CreateLoad(llvm_utils->create_ptr_gep(shape_data, i)) : i32_one; + llvm::Value* new_ub = nullptr; + if( ASRUtils::extract_physical_type(asr_shape_type) == ASR::array_physical_typeType::DescriptorArray || + ASRUtils::extract_physical_type(asr_shape_type) == ASR::array_physical_typeType::PointerToDataArray ) { + new_ub = shape_data ? CreateLoad(llvm_utils->create_ptr_gep(shape_data, i)) : i32_one; + } else if( ASRUtils::extract_physical_type(asr_shape_type) == ASR::array_physical_typeType::FixedSizeArray ) { + new_ub = shape_data ? CreateLoad(llvm_utils->create_gep(shape_data, i)) : i32_one; + } builder->CreateStore(new_lb, desi_lb); llvm::Value* new_size = builder->CreateAdd(builder->CreateSub(new_ub, new_lb), i32_one); builder->CreateStore(new_size, desi_size); @@ -4598,8 +3579,8 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor this->visit_expr(*fptr); llvm::Value* llvm_fptr = tmp; ptr_loads = ptr_loads_copy; - llvm::Type* llvm_fptr_type = get_type_from_ttype_t_util( - ASRUtils::get_contained_type(ASRUtils::expr_type(fptr))); + llvm::Type* llvm_fptr_type = llvm_utils->get_type_from_ttype_t_util( + ASRUtils::get_contained_type(ASRUtils::expr_type(fptr)), module.get()); llvm_cptr = builder->CreateBitCast(llvm_cptr, llvm_fptr_type->getPointerTo()); builder->CreateStore(llvm_cptr, llvm_fptr); } @@ -4610,23 +3591,66 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor this->visit_expr_wrapper(x.m_value, true); return; } + llvm::BasicBlock &entry_block = builder->GetInsertBlock()->getParent()->getEntryBlock(); + llvm::IRBuilder<> builder0(context); + builder0.SetInsertPoint(&entry_block, entry_block.getFirstInsertionPt()); + llvm::AllocaInst *res = builder0.CreateAlloca( + llvm::Type::getInt1Ty(context), nullptr, "is_associated"); ASR::Variable_t *p = EXPR2VAR(x.m_ptr); uint32_t value_h = get_hash((ASR::asr_t*)p); llvm::Value *ptr = llvm_symtab[value_h], *nptr; ptr = CreateLoad(ptr); - ptr = builder->CreatePtrToInt(ptr, getIntType(8, false)); - if (x.m_tgt) { - ASR::Variable_t *t = EXPR2VAR(x.m_tgt); - uint32_t t_h = get_hash((ASR::asr_t*)t); - nptr = llvm_symtab[t_h]; - nptr = builder->CreatePtrToInt(nptr, getIntType(8, false)); - tmp = builder->CreateICmpEQ(ptr, nptr); - } else { - llvm::Type* value_type = get_type_from_ttype_t_util(p->m_type); - nptr = llvm::ConstantPointerNull::get(static_cast(value_type)); - nptr = builder->CreatePtrToInt(nptr, getIntType(8, false)); - tmp = builder->CreateICmpNE(ptr, nptr); + if( ASR::is_a(*ASRUtils::expr_type(x.m_ptr)) && + x.m_tgt && ASR::is_a(*ASRUtils::expr_type(x.m_tgt)) ) { + int64_t ptr_loads_copy = ptr_loads; + ptr_loads = 0; + this->visit_expr_wrapper(x.m_tgt, true); + ptr_loads = ptr_loads_copy; + tmp = builder->CreateICmpEQ( + builder->CreatePtrToInt(ptr, llvm_utils->getIntType(8, false)), + builder->CreatePtrToInt(tmp, llvm_utils->getIntType(8, false))); + return ; } + llvm_utils->create_if_else(builder->CreateICmpEQ( + builder->CreatePtrToInt(ptr, llvm_utils->getIntType(8, false)), + llvm::ConstantInt::get(llvm::Type::getInt64Ty(context), llvm::APInt(64, 0))), + [&]() { + builder->CreateStore( + llvm::ConstantInt::get(llvm::Type::getInt1Ty(context), llvm::APInt(1, 0)), + res); + }, + [&]() { + if (x.m_tgt) { + int64_t ptr_loads_copy = ptr_loads; + ptr_loads = 0; + this->visit_expr_wrapper(x.m_tgt, true); + ptr_loads = ptr_loads_copy; + // ASR::Variable_t *t = EXPR2VAR(x.m_tgt); + // uint32_t t_h = get_hash((ASR::asr_t*)t); + // nptr = llvm_symtab[t_h]; + nptr = tmp; + if( ASRUtils::is_array(ASRUtils::expr_type(x.m_tgt)) ) { + ASR::array_physical_typeType tgt_ptype = ASRUtils::extract_physical_type( + ASRUtils::expr_type(x.m_tgt)); + if( tgt_ptype == ASR::array_physical_typeType::FixedSizeArray ) { + nptr = llvm_utils->create_gep(nptr, 0); + } + if( tgt_ptype != ASR::array_physical_typeType::DescriptorArray ) { + ptr = LLVM::CreateLoad(*builder, arr_descr->get_pointer_to_data(ptr)); + } + } + nptr = builder->CreatePtrToInt(nptr, llvm_utils->getIntType(8, false)); + ptr = builder->CreatePtrToInt(ptr, llvm_utils->getIntType(8, false)); + builder->CreateStore(builder->CreateICmpEQ(ptr, nptr), res); + } else { + llvm::Type* value_type = llvm_utils->get_type_from_ttype_t_util(p->m_type, module.get()); + nptr = llvm::ConstantPointerNull::get(static_cast(value_type)); + nptr = builder->CreatePtrToInt(nptr, llvm_utils->getIntType(8, false)); + ptr = builder->CreatePtrToInt(ptr, llvm_utils->getIntType(8, false)); + builder->CreateStore(builder->CreateICmpNE(ptr, nptr), res); + } + }); + tmp = LLVM::CreateLoad(*builder, res); } void handle_array_section_association_to_pointer(const ASR::Associate_t& x) { @@ -4645,8 +3669,10 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor llvm::BasicBlock &entry_block = builder->GetInsertBlock()->getParent()->getEntryBlock(); llvm::IRBuilder<> builder0(context); builder0.SetInsertPoint(&entry_block, entry_block.getFirstInsertionPt()); - llvm::Type* target_type = get_type_from_ttype_t_util( - ASRUtils::type_get_past_pointer(value_array_type)); + ASR::ttype_t* target_desc_type = ASRUtils::duplicate_type_with_empty_dims(al, + ASRUtils::type_get_past_pointer(value_array_type), + ASR::array_physical_typeType::DescriptorArray, true); + llvm::Type* target_type = llvm_utils->get_type_from_ttype_t_util(target_desc_type, module.get()); llvm::AllocaInst *target = builder0.CreateAlloca( target_type, nullptr, "array_section_descriptor"); int value_rank = array_section->n_args, target_rank = 0; @@ -4673,11 +3699,14 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor LCOMPILERS_ASSERT(target_rank > 0); llvm::Value* target_dim_des_ptr = arr_descr->get_pointer_to_dimension_descriptor_array(target, false); llvm::Value* target_dim_des_val = builder0.CreateAlloca(arr_descr->get_dimension_descriptor_type(false), - llvm::ConstantInt::get(getIntType(4), llvm::APInt(32, target_rank))); + llvm::ConstantInt::get(llvm_utils->getIntType(4), llvm::APInt(32, target_rank))); builder->CreateStore(target_dim_des_val, target_dim_des_ptr); ASR::ttype_t* array_type = ASRUtils::expr_type(array_section->m_v); - if( ASRUtils::is_data_only_array(array_type, ASR::abiType::Source) && - ASRUtils::expr_intent(array_section->m_v) != ASR::intentType::Local ) { + if( ASRUtils::extract_physical_type(array_type) == ASR::array_physical_typeType::PointerToDataArray || + ASRUtils::extract_physical_type(array_type) == ASR::array_physical_typeType::FixedSizeArray ) { + if( ASRUtils::extract_physical_type(array_type) == ASR::array_physical_typeType::FixedSizeArray ) { + value_desc = llvm_utils->create_gep(value_desc, 0); + } ASR::dimension_t* m_dims = nullptr; // Fill in m_dims: [[maybe_unused]] int array_value_rank = ASRUtils::extract_dimensions_from_ttype(array_type, m_dims); @@ -4705,15 +3734,18 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor if( ASR::is_a(*x.m_value) ) { handle_array_section_association_to_pointer(x); } else { - ASR::Variable_t *asr_target = EXPR2VAR(x.m_target); - ASR::Variable_t *asr_value = EXPR2VAR(x.m_value); - uint32_t value_h = get_hash((ASR::asr_t*)asr_value); - uint32_t target_h = get_hash((ASR::asr_t*)asr_target); - llvm::Value* llvm_target = llvm_symtab[target_h]; - llvm::Value* llvm_value = llvm_symtab[value_h]; + int64_t ptr_loads_copy = ptr_loads; + ptr_loads = 0; + visit_expr(*x.m_target); + llvm::Value* llvm_target = tmp; + visit_expr(*x.m_value); + llvm::Value* llvm_value = tmp; + ptr_loads = ptr_loads_copy; ASR::dimension_t* m_dims = nullptr; - int n_dims = ASRUtils::extract_dimensions_from_ttype(asr_target->m_type, m_dims); - ASR::ttype_t *type = ASRUtils::get_contained_type(asr_target->m_type); + ASR::ttype_t* target_type = ASRUtils::expr_type(x.m_target); + ASR::ttype_t* value_type = ASRUtils::expr_type(x.m_value); + int n_dims = ASRUtils::extract_dimensions_from_ttype(target_type, m_dims); + ASR::ttype_t *type = ASRUtils::get_contained_type(target_type); type = ASRUtils::type_get_past_allocatable(type); if (ASR::is_a(*type)) { int dims = n_dims; @@ -4724,14 +3756,14 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } } bool is_target_class = ASR::is_a( - *ASRUtils::type_get_past_pointer(asr_target->m_type)); + *ASRUtils::type_get_past_pointer(target_type)); bool is_value_class = ASR::is_a( - *ASRUtils::type_get_past_pointer(asr_value->m_type)); + *ASRUtils::type_get_past_pointer(value_type)); if( is_target_class && !is_value_class ) { llvm::Value* vtab_address_ptr = llvm_utils->create_gep(llvm_target, 0); llvm_target = llvm_utils->create_gep(llvm_target, 1); ASR::Struct_t* struct_t = ASR::down_cast( - ASRUtils::type_get_past_pointer(asr_value->m_type)); + ASRUtils::type_get_past_pointer(value_type)); ASR::symbol_t* struct_sym = ASRUtils::symbol_get_past_external(struct_t->m_derived_type); if (type2vtab.find(struct_sym) == type2vtab.end() || type2vtab[struct_sym].find(current_scope) == type2vtab[struct_sym].end()) { @@ -4742,37 +3774,40 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor builder->CreateStore(struct_type_hash, vtab_address_ptr); ASR::Class_t* class_t = ASR::down_cast( - ASRUtils::type_get_past_pointer(asr_target->m_type)); + ASRUtils::type_get_past_pointer(target_type)); ASR::StructType_t* struct_type_t = ASR::down_cast( ASRUtils::symbol_get_past_external(class_t->m_class_type)); - llvm_value = builder->CreateBitCast(llvm_value, getStructType(struct_type_t, true)); + llvm_value = builder->CreateBitCast(llvm_value, llvm_utils->getStructType(struct_type_t, module.get(), true)); builder->CreateStore(llvm_value, llvm_target); } else if( is_target_class && is_value_class ) { [[maybe_unused]] ASR::Class_t* target_class_t = ASR::down_cast( - ASRUtils::type_get_past_pointer(asr_target->m_type)); + ASRUtils::type_get_past_pointer(target_type)); [[maybe_unused]] ASR::Class_t* value_class_t = ASR::down_cast( - ASRUtils::type_get_past_pointer(asr_target->m_type)); + ASRUtils::type_get_past_pointer(target_type)); LCOMPILERS_ASSERT(target_class_t->m_class_type == value_class_t->m_class_type); llvm::Value* value_vtabid = CreateLoad(llvm_utils->create_gep(llvm_value, 0)); llvm::Value* value_class = CreateLoad(llvm_utils->create_gep(llvm_value, 1)); builder->CreateStore(value_vtabid, llvm_utils->create_gep(llvm_target, 0)); builder->CreateStore(value_class, llvm_utils->create_gep(llvm_target, 1)); } else { - bool is_value_data_only_array = ASRUtils::is_data_only_array( - asr_value->m_type, asr_value->m_abi); - if( ASR::is_a(*asr_value->m_type) ) { + bool is_value_data_only_array = (ASRUtils::is_array(value_type) && ( + ASRUtils::extract_physical_type(value_type) == ASR::array_physical_typeType::PointerToDataArray || + ASRUtils::extract_physical_type(value_type) == ASR::array_physical_typeType::FixedSizeArray)); + if( LLVM::is_llvm_pointer(*value_type) ) { llvm_value = LLVM::CreateLoad(*builder, llvm_value); } - if( is_value_data_only_array && - asr_value->m_intent != ASR::intentType::Local ) { - ASR::ttype_t* target_type = ASRUtils::type_get_past_pointer(asr_target->m_type); - llvm::Type* llvm_target_type = get_type_from_ttype_t_util(target_type); + if( is_value_data_only_array ) { + if( ASRUtils::extract_physical_type(value_type) == ASR::array_physical_typeType::FixedSizeArray ) { + llvm_value = llvm_utils->create_gep(llvm_value, 0); + } + ASR::ttype_t* target_type_ = ASRUtils::type_get_past_pointer(target_type); + llvm::Type* llvm_target_type = llvm_utils->get_type_from_ttype_t_util(target_type_, module.get()); llvm::Value* llvm_target_ = builder->CreateAlloca(llvm_target_type); ASR::dimension_t* m_dims = nullptr; - size_t n_dims = ASRUtils::extract_dimensions_from_ttype(asr_value->m_type, m_dims); + size_t n_dims = ASRUtils::extract_dimensions_from_ttype(value_type, m_dims); ASR::ttype_t* data_type = ASRUtils::duplicate_type_without_dims( - al, target_type, target_type->base.loc); - llvm::Type* llvm_data_type = get_type_from_ttype_t_util(data_type); + al, target_type_, target_type_->base.loc); + llvm::Type* llvm_data_type = llvm_utils->get_type_from_ttype_t_util(data_type, module.get()); fill_array_details(llvm_target_, llvm_data_type, m_dims, n_dims, false, false); builder->CreateStore(llvm_value, arr_descr->get_pointer_to_data(llvm_target_)); llvm_value = llvm_target_; @@ -4916,7 +3951,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor src_deepcopies.reserve(al, asr_value_tuple->n_elements); for( size_t i = 0; i < asr_value_tuple->n_elements; i++ ) { ASR::ttype_t* asr_tuple_i_type = ASRUtils::expr_type(asr_value_tuple->m_elements[i]); - llvm::Type* llvm_tuple_i_type = get_type_from_ttype_t_util(asr_tuple_i_type); + llvm::Type* llvm_tuple_i_type = llvm_utils->get_type_from_ttype_t_util(asr_tuple_i_type, module.get()); llvm::Value* llvm_tuple_i = builder->CreateAlloca(llvm_tuple_i_type, nullptr); ptr_loads = !LLVM::is_llvm_struct(asr_tuple_i_type); visit_expr(*asr_value_tuple->m_elements[i]); @@ -4957,7 +3992,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor llvm::Value* target_dict = tmp; ptr_loads = ptr_loads_copy; ASR::Dict_t* value_dict_type = ASR::down_cast(asr_value_type); - set_dict_api(value_dict_type); + llvm_utils->set_dict_api(value_dict_type); llvm_utils->dict_api->dict_deepcopy(value_dict, target_dict, value_dict_type, module.get(), name2memidx); return ; @@ -4993,10 +4028,20 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor ASR::is_a(*x.m_value) ) { ASR::Variable_t *asr_target = EXPR2VAR(x.m_target); ASR::GetPointer_t* get_ptr = ASR::down_cast(x.m_value); - ASR::Variable_t *asr_value = EXPR2VAR(get_ptr->m_arg); - uint32_t value_h = get_hash((ASR::asr_t*)asr_value); uint32_t target_h = get_hash((ASR::asr_t*)asr_target); - builder->CreateStore(llvm_symtab[value_h], llvm_symtab[target_h]); + int ptr_loads_copy = ptr_loads; + ptr_loads = 2 - LLVM::is_llvm_pointer(*ASRUtils::expr_type(get_ptr->m_arg)); + visit_expr_wrapper(get_ptr->m_arg, true); + ptr_loads = ptr_loads_copy; + if( ASRUtils::is_array(ASRUtils::expr_type(get_ptr->m_arg)) ) { + visit_ArrayPhysicalCastUtil( + tmp, get_ptr->m_arg, ASRUtils::type_get_past_pointer( + ASRUtils::type_get_past_allocatable(get_ptr->m_type)), + ASRUtils::expr_type(get_ptr->m_arg), + ASRUtils::extract_physical_type(ASRUtils::expr_type(get_ptr->m_arg)), + ASR::array_physical_typeType::DescriptorArray); + } + builder->CreateStore(tmp, llvm_symtab[target_h]); return ; } llvm::Value *target, *value; @@ -5071,7 +4116,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor target = CreateLoad(target); } ASR::ttype_t *cont_type = ASRUtils::get_contained_type(asr_target_type); - if (ASRUtils::is_array(cont_type) && arr_descr->is_array(cont_type) ) { + if (ASRUtils::is_array(cont_type) && ASRUtils::is_array(cont_type) ) { if( asr_target->m_type->type == ASR::ttypeType::Character) { target = CreateLoad(arr_descr->get_pointer_to_data(target)); @@ -5112,9 +4157,51 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor ASRUtils::is_array(value_type) && ASRUtils::check_equal_type(target_type, value_type) ) { bool data_only_copy = false; - bool is_target_data_only_array = ASRUtils::expr_abi(x.m_target) == ASR::abiType::BindC; - bool is_value_data_only_array = ASRUtils::expr_abi(x.m_value) == ASR::abiType::BindC; - if( is_target_data_only_array || is_value_data_only_array ) { + ASR::array_physical_typeType target_ptype = ASRUtils::extract_physical_type(target_type); + ASR::array_physical_typeType value_ptype = ASRUtils::extract_physical_type(value_type); + bool is_target_data_only_array = (target_ptype == ASR::array_physical_typeType::PointerToDataArray); + bool is_value_data_only_array = (value_ptype == ASR::array_physical_typeType::PointerToDataArray); + bool is_target_fixed_sized_array = (target_ptype == ASR::array_physical_typeType::FixedSizeArray); + bool is_value_fixed_sized_array = (value_ptype == ASR::array_physical_typeType::FixedSizeArray); + // bool is_target_descriptor_based_array = (target_ptype == ASR::array_physical_typeType::DescriptorArray); + bool is_value_descriptor_based_array = (value_ptype == ASR::array_physical_typeType::DescriptorArray); + if( is_value_fixed_sized_array && is_target_fixed_sized_array ) { + value = llvm_utils->create_gep(value, 0); + target = llvm_utils->create_gep(target, 0); + ASR::dimension_t* asr_dims = nullptr; + size_t asr_n_dims = ASRUtils::extract_dimensions_from_ttype(target_type, asr_dims); + int64_t size = ASRUtils::get_fixed_size_of_array(asr_dims, asr_n_dims); + llvm::Type* llvm_data_type = llvm_utils->get_type_from_ttype_t_util(ASRUtils::type_get_past_array( + ASRUtils::type_get_past_allocatable(ASRUtils::type_get_past_pointer(target_type))), module.get()); + llvm::DataLayout data_layout(module.get()); + uint64_t data_size = data_layout.getTypeAllocSize(llvm_data_type); + llvm::Value* llvm_size = llvm::ConstantInt::get(context, llvm::APInt(32, size)); + llvm_size = builder->CreateMul(llvm_size, + llvm::ConstantInt::get(context, llvm::APInt(32, data_size))); + builder->CreateMemCpy(target, llvm::MaybeAlign(), value, llvm::MaybeAlign(), llvm_size); + } else if( is_value_descriptor_based_array && is_target_fixed_sized_array ) { + value = LLVM::CreateLoad(*builder, arr_descr->get_pointer_to_data(value)); + target = llvm_utils->create_gep(target, 0); + ASR::dimension_t* asr_dims = nullptr; + size_t asr_n_dims = ASRUtils::extract_dimensions_from_ttype(target_type, asr_dims); + int64_t size = ASRUtils::get_fixed_size_of_array(asr_dims, asr_n_dims); + llvm::Type* llvm_data_type = llvm_utils->get_type_from_ttype_t_util(ASRUtils::type_get_past_array( + ASRUtils::type_get_past_allocatable(ASRUtils::type_get_past_pointer(target_type))), module.get()); + llvm::DataLayout data_layout(module.get()); + uint64_t data_size = data_layout.getTypeAllocSize(llvm_data_type); + llvm::Value* llvm_size = llvm::ConstantInt::get(context, llvm::APInt(32, size)); + llvm_size = builder->CreateMul(llvm_size, + llvm::ConstantInt::get(context, llvm::APInt(32, data_size))); + builder->CreateMemCpy(target, llvm::MaybeAlign(), value, llvm::MaybeAlign(), llvm_size); + } else if( is_target_data_only_array || is_value_data_only_array ) { + if( is_value_fixed_sized_array ) { + value = llvm_utils->create_gep(value, 0); + is_value_data_only_array = true; + } + if( is_target_fixed_sized_array ) { + target = llvm_utils->create_gep(target, 0); + is_target_data_only_array = true; + } llvm::Value *target_data = nullptr, *value_data = nullptr, *llvm_size = nullptr; if( is_target_data_only_array ) { target_data = target; @@ -5161,12 +4248,16 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor value_data = LLVM::CreateLoad(*builder, arr_descr->get_pointer_to_data(value)); } if( llvm_size ) { + llvm::Type* llvm_data_type = llvm_utils->get_type_from_ttype_t_util( + ASRUtils::type_get_past_allocatable( + ASRUtils::type_get_past_pointer( + ASRUtils::type_get_past_array(target_type))), module.get()); arr_descr->copy_array_data_only(value_data, target_data, module.get(), - target_type, llvm_size); + llvm_data_type, llvm_size); } } else { arr_descr->copy_array(value, target, module.get(), - target_type, false, false); + target_type, false, false); } } else if( ASR::is_a(*x.m_target) ) { ASR::DictItem_t* dict_item_t = ASR::down_cast(x.m_target); @@ -5182,7 +4273,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor llvm::Value *key = tmp; ptr_loads = ptr_loads_copy; - set_dict_api(dict_type); + llvm_utils->set_dict_api(dict_type); // Note - The value is fully loaded to an LLVM value (not at all a pointer) // as opposed to DictInsert where LLVM values are loaded depending upon // the ASR type of value. Might give issues here. @@ -5194,6 +4285,81 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } } + void visit_ArrayPhysicalCastUtil(llvm::Value* arg, ASR::expr_t* m_arg, + ASR::ttype_t* m_type, ASR::ttype_t* m_type_for_dimensions, + ASR::array_physical_typeType m_old, ASR::array_physical_typeType m_new) { + + if( m_old == m_new ) { + return ; + } + + #define PointerToData_to_Descriptor() llvm::BasicBlock &entry_block = builder->GetInsertBlock()->getParent()->getEntryBlock(); \ + llvm::IRBuilder<> builder0(context); \ + builder0.SetInsertPoint(&entry_block, entry_block.getFirstInsertionPt()); \ + llvm::Type* target_type = llvm_utils->get_type_from_ttype_t_util( \ + ASRUtils::type_get_past_allocatable( \ + ASRUtils::type_get_past_pointer(m_type)), module.get()); \ + llvm::AllocaInst *target = builder0.CreateAlloca( \ + target_type, nullptr, "array_descriptor"); \ + builder->CreateStore(tmp, arr_descr->get_pointer_to_data(target)); \ + ASR::dimension_t* m_dims = nullptr; \ + int n_dims = ASRUtils::extract_dimensions_from_ttype(m_type_for_dimensions, m_dims); \ + llvm::Type* llvm_data_type = llvm_utils->get_type_from_ttype_t_util( \ + ASRUtils::type_get_past_pointer(ASRUtils::type_get_past_allocatable(m_type)), module.get()); \ + fill_array_details(target, llvm_data_type, m_dims, n_dims, false, false); \ + if( LLVM::is_llvm_pointer(*m_type) ) { \ + llvm::AllocaInst* target_ptr = builder0.CreateAlloca( \ + target_type->getPointerTo(), nullptr, "array_descriptor_ptr"); \ + builder->CreateStore(target, target_ptr); \ + target = target_ptr; \ + } \ + tmp = target; \ + + + if( m_new == ASR::array_physical_typeType::PointerToDataArray && + m_old == ASR::array_physical_typeType::DescriptorArray ) { + tmp = LLVM::CreateLoad(*builder, arr_descr->get_pointer_to_data(arg)); + } else if( + m_new == ASR::array_physical_typeType::PointerToDataArray && + m_old == ASR::array_physical_typeType::FixedSizeArray) { + if( (ASRUtils::expr_value(m_arg) && + !ASR::is_a(*ASRUtils::expr_value(m_arg))) || + ASRUtils::expr_value(m_arg) == nullptr ) { + tmp = llvm_utils->create_gep(tmp, 0); + } + } else if( + m_new == ASR::array_physical_typeType::DescriptorArray && + m_old == ASR::array_physical_typeType::FixedSizeArray) { + if( (ASRUtils::expr_value(m_arg) && + !ASR::is_a(*ASRUtils::expr_value(m_arg))) || + ASRUtils::expr_value(m_arg) == nullptr ) { + tmp = llvm_utils->create_gep(tmp, 0); + } + PointerToData_to_Descriptor() + } else if( + m_new == ASR::array_physical_typeType::DescriptorArray && + m_old == ASR::array_physical_typeType::PointerToDataArray) { + PointerToData_to_Descriptor() + } else if( + m_new == ASR::array_physical_typeType::FixedSizeArray && + m_old == ASR::array_physical_typeType::DescriptorArray) { + tmp = LLVM::CreateLoad(*builder, arr_descr->get_pointer_to_data(tmp)); + llvm::Type* target_type = llvm_utils->get_type_from_ttype_t_util(m_type, module.get())->getPointerTo(); + tmp = builder->CreateBitCast(tmp, target_type); + } else { + LCOMPILERS_ASSERT(false); + } + } + + void visit_ArrayPhysicalCast(const ASR::ArrayPhysicalCast_t& x) { + LCOMPILERS_ASSERT(x.m_new != x.m_old); + int64_t ptr_loads_copy = ptr_loads; + ptr_loads = 2 - LLVM::is_llvm_pointer(*ASRUtils::expr_type(x.m_arg)); + this->visit_expr_wrapper(x.m_arg, false); + ptr_loads = ptr_loads_copy; + visit_ArrayPhysicalCastUtil(tmp, x.m_arg, x.m_type, x.m_type, x.m_old, x.m_new); + } + void visit_AssociateBlockCall(const ASR::AssociateBlockCall_t& x) { LCOMPILERS_ASSERT(ASR::is_a(*x.m_m)); ASR::AssociateBlock_t* associate_block = ASR::down_cast(x.m_m); @@ -5306,8 +4472,8 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor ASR::TypeStmtName_t* type_stmt_name = ASR::down_cast(select_type_stmts[i]); ASR::symbol_t* type_sym = ASRUtils::symbol_get_past_external(type_stmt_name->m_sym); if( ASR::is_a(*type_sym) ) { - current_select_type_block_type = getStructType( - ASR::down_cast(type_sym), true); + current_select_type_block_type = llvm_utils->getStructType( + ASR::down_cast(type_sym), module.get(), true); current_select_type_block_der_type = ASR::down_cast(type_sym)->m_name; } else { LCOMPILERS_ASSERT(false); @@ -5329,8 +4495,8 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor ASR::ClassStmt_t* class_stmt = ASR::down_cast(select_type_stmts[i]); ASR::symbol_t* class_sym = ASRUtils::symbol_get_past_external(class_stmt->m_sym); if( ASR::is_a(*class_sym) ) { - current_select_type_block_type = getStructType( - ASR::down_cast(class_sym), true); + current_select_type_block_type = llvm_utils->getStructType( + ASR::down_cast(class_sym), module.get(), true); current_select_type_block_der_type = ASR::down_cast(class_sym)->m_name; } else { LCOMPILERS_ASSERT(false); @@ -5353,8 +4519,8 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor ASR::ttype_t* selector_var_type = ASRUtils::expr_type(x.m_selector); ASR::TypeStmtType_t* type_stmt_type_t = ASR::down_cast(select_type_stmts[i]); ASR::ttype_t* type_stmt_type = type_stmt_type_t->m_type; - current_select_type_block_type = get_type_from_ttype_t_util(type_stmt_type)->getPointerTo(); - llvm::Value* intrinsic_type_id = llvm::ConstantInt::get(getIntType(8), + current_select_type_block_type = llvm_utils->get_type_from_ttype_t_util(type_stmt_type, module.get())->getPointerTo(); + llvm::Value* intrinsic_type_id = llvm::ConstantInt::get(llvm_utils->getIntType(8), llvm::APInt(64, -((int) type_stmt_type->type) - ASRUtils::extract_kind_from_ttype_t(type_stmt_type), true)); llvm::Value* _type_id = nullptr; @@ -5490,10 +4656,10 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } this->visit_expr_wrapper(x.m_left, true); llvm::Value *left = tmp; - left = builder->CreatePtrToInt(left, getIntType(8, false)); + left = builder->CreatePtrToInt(left, llvm_utils->getIntType(8, false)); this->visit_expr_wrapper(x.m_right, true); llvm::Value *right = tmp; - right = builder->CreatePtrToInt(right, getIntType(8, false)); + right = builder->CreatePtrToInt(right, llvm_utils->getIntType(8, false)); switch (x.m_op) { case (ASR::cmpopType::Eq) : { tmp = builder->CreateICmpEQ(left, right); @@ -5863,7 +5029,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor zero = llvm::ConstantInt::get(context, llvm::APInt(init_value_bits, 0)); cond = builder->CreateICmpEQ(left_val, zero); - result = builder->CreateAlloca(getIntType(a_kind), nullptr); + result = builder->CreateAlloca(llvm_utils->getIntType(a_kind), nullptr); } else if (ASRUtils::is_real(*x.m_type)) { int a_kind = down_cast(x.m_type)->m_kind; int init_value_bits = 8*a_kind; @@ -5874,7 +5040,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor zero = llvm::ConstantFP::get(context, llvm::APFloat((double)0)); } - result = builder->CreateAlloca(getFPType(a_kind), nullptr); + result = builder->CreateAlloca(llvm_utils->getFPType(a_kind), nullptr); cond = builder->CreateFCmpUEQ(left_val, zero); } else if (ASRUtils::is_character(*x.m_type)) { zero = llvm::Constant::getNullValue(character_type); @@ -6069,7 +5235,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor llvm::Type *type; int a_kind; a_kind = down_cast(ASRUtils::type_get_past_pointer(x.m_type))->m_kind; - type = getFPType(a_kind); + type = llvm_utils->getFPType(a_kind); llvm::Value *fleft = builder->CreateSIToFP(left_val, type); llvm::Value *fright = builder->CreateSIToFP(right_val, @@ -6084,7 +5250,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor module.get()); } tmp = builder->CreateCall(fn_pow, {fleft, fright}); - type = getIntType(a_kind); + type = llvm_utils->getIntType(a_kind); tmp = builder->CreateFPToSI(tmp, type); break; }; @@ -6152,7 +5318,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor llvm::Type *type; int a_kind; a_kind = down_cast(ASRUtils::type_get_past_pointer(x.m_type))->m_kind; - type = getFPType(a_kind); + type = llvm_utils->getFPType(a_kind); std::string func_name = a_kind == 4 ? "llvm.pow.f32" : "llvm.pow.f64"; llvm::Function *fn_pow = module->getFunction(func_name); if (!fn_pow) { @@ -6185,7 +5351,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor llvm::Type *type; int a_kind; a_kind = down_cast(ASRUtils::type_get_past_pointer(x.m_type))->m_kind; - type = getComplexType(a_kind); + type = llvm_utils->getComplexType(a_kind); if( left_val->getType()->isPointerTy() ) { left_val = CreateLoad(left_val); } @@ -6268,7 +5434,8 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor tmp = builder->CreateNot(tmp); } - void visit_IntegerUnaryMinus(const ASR::IntegerUnaryMinus_t &x) { + template + void handle_SU_IntegerUnaryMinus(const T& x) { if (x.m_value) { this->visit_expr_wrapper(x.m_value, true); return; @@ -6279,6 +5446,14 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor tmp = builder->CreateSub(zero, tmp); } + void visit_IntegerUnaryMinus(const ASR::IntegerUnaryMinus_t &x) { + handle_SU_IntegerUnaryMinus(x); + } + + void visit_UnsignedIntegerUnaryMinus(const ASR::UnsignedIntegerUnaryMinus_t &x) { + handle_SU_IntegerUnaryMinus(x); + } + void visit_RealUnaryMinus(const ASR::RealUnaryMinus_t &x) { if (x.m_value) { this->visit_expr_wrapper(x.m_value, true); @@ -6399,7 +5574,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor llvm::Type* el_type; ASR::ttype_t* x_m_type = ASRUtils::type_get_past_array(x.m_type); if (ASR::is_a(*x_m_type)) { - el_type = getIntType(ASR::down_cast(x_m_type)->m_kind); + el_type = llvm_utils->getIntType(ASR::down_cast(x_m_type)->m_kind); } else if (ASR::is_a(*x_m_type)) { switch (ASR::down_cast(x_m_type)->m_kind) { case (4) : @@ -6579,7 +5754,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor tmp = x_v; return; } - if( arr_descr->is_array(ASRUtils::get_contained_type(x->m_type)) ) { + if( ASRUtils::is_array(x->m_type) ) { tmp = x_v; } else { tmp = x_v; @@ -6598,7 +5773,8 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } ASR::ttype_t *t2_ = ASRUtils::type_get_past_array(x->m_type); switch( t2_->type ) { - case ASR::ttypeType::Pointer: { + case ASR::ttypeType::Pointer: + case ASR::ttypeType::Allocatable: { ASR::ttype_t *t2 = ASRUtils::type_get_past_array( ASRUtils::type_get_past_pointer(x->m_type)); switch (t2->type) { @@ -6775,30 +5951,30 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor switch (x.m_kind) { case (ASR::cast_kindType::IntegerToReal) : { int a_kind = ASRUtils::extract_kind_from_ttype_t(x.m_type); - tmp = builder->CreateSIToFP(tmp, getFPType(a_kind, false)); + tmp = builder->CreateSIToFP(tmp, llvm_utils->getFPType(a_kind, false)); break; } case (ASR::cast_kindType::UnsignedIntegerToReal) : { int a_kind = ASRUtils::extract_kind_from_ttype_t(x.m_type); - tmp = builder->CreateSIToFP(tmp, getFPType(a_kind, false)); + tmp = builder->CreateSIToFP(tmp, llvm_utils->getFPType(a_kind, false)); break; } case (ASR::cast_kindType::LogicalToReal) : { int a_kind = ASRUtils::extract_kind_from_ttype_t(x.m_type); - tmp = builder->CreateUIToFP(tmp, getFPType(a_kind, false)); + tmp = builder->CreateUIToFP(tmp, llvm_utils->getFPType(a_kind, false)); break; } case (ASR::cast_kindType::RealToInteger) : { llvm::Type *target_type; int a_kind = ASRUtils::extract_kind_from_ttype_t(x.m_type); - target_type = getIntType(a_kind); + target_type = llvm_utils->getIntType(a_kind); tmp = builder->CreateFPToSI(tmp, target_type); break; } case (ASR::cast_kindType::RealToUnsignedInteger) : { llvm::Type *target_type; int a_kind = ASRUtils::extract_kind_from_ttype_t(x.m_type); - target_type = getIntType(a_kind); + target_type = llvm_utils->getIntType(a_kind); tmp = builder->CreateFPToSI(tmp, target_type); break; } @@ -6848,7 +6024,8 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor tmp = complex_from_floats(tmp, zero, complex_type); break; } - case (ASR::cast_kindType::IntegerToLogical) : { + case (ASR::cast_kindType::IntegerToLogical) : + case (ASR::cast_kindType::UnsignedIntegerToLogical) : { ASR::ttype_t* curr_type = extract_ttype_t_from_expr(x.m_arg); LCOMPILERS_ASSERT(curr_type != nullptr) int a_kind = ASRUtils::extract_kind_from_ttype_t(curr_type); @@ -6914,7 +6091,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } case (ASR::cast_kindType::LogicalToInteger) : { int a_kind = ASRUtils::extract_kind_from_ttype_t(x.m_type); - tmp = builder->CreateZExt(tmp, getIntType(a_kind)); + tmp = builder->CreateZExt(tmp, llvm_utils->getIntType(a_kind)); break; } case (ASR::cast_kindType::RealToReal) : { @@ -6942,9 +6119,23 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor arg_kind != dest_kind ) { if (dest_kind > arg_kind) { - tmp = builder->CreateSExt(tmp, getIntType(dest_kind)); + tmp = builder->CreateSExt(tmp, llvm_utils->getIntType(dest_kind)); + } else { + tmp = builder->CreateTrunc(tmp, llvm_utils->getIntType(dest_kind)); + } + } + break; + } + case (ASR::cast_kindType::UnsignedIntegerToUnsignedInteger) : { + int arg_kind = -1, dest_kind = -1; + extract_kinds(x, arg_kind, dest_kind); + if( arg_kind > 0 && dest_kind > 0 && + arg_kind != dest_kind ) + { + if (dest_kind > arg_kind) { + tmp = builder->CreateZExt(tmp, llvm_utils->getIntType(dest_kind)); } else { - tmp = builder->CreateTrunc(tmp, getIntType(dest_kind)); + tmp = builder->CreateTrunc(tmp, llvm_utils->getIntType(dest_kind)); } } break; @@ -6957,9 +6148,9 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor arg_kind != dest_kind ) { if (dest_kind > arg_kind) { - tmp = builder->CreateSExt(tmp, getIntType(dest_kind)); + tmp = builder->CreateSExt(tmp, llvm_utils->getIntType(dest_kind)); } else { - tmp = builder->CreateTrunc(tmp, getIntType(dest_kind)); + tmp = builder->CreateTrunc(tmp, llvm_utils->getIntType(dest_kind)); } } break; @@ -6972,15 +6163,15 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor arg_kind != dest_kind ) { if (dest_kind > arg_kind) { - tmp = builder->CreateSExt(tmp, getIntType(dest_kind)); + tmp = builder->CreateSExt(tmp, llvm_utils->getIntType(dest_kind)); } else { - tmp = builder->CreateTrunc(tmp, getIntType(dest_kind)); + tmp = builder->CreateTrunc(tmp, llvm_utils->getIntType(dest_kind)); } } break; } case (ASR::cast_kindType::CPtrToUnsignedInteger) : { - tmp = builder->CreatePtrToInt(tmp, getIntType(8, false)); + tmp = builder->CreatePtrToInt(tmp, llvm_utils->getIntType(8, false)); break; } case (ASR::cast_kindType::UnsignedIntegerToCPtr) : { @@ -7069,7 +6260,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor throw CodeGenError(msg); } llvm::Type *target_type; - target_type = getIntType(dest_kind); + target_type = llvm_utils->getIntType(dest_kind); tmp = builder->CreateFPToSI(tmp, target_type); } else { throw CodeGenError("Negative kinds are not supported."); @@ -7081,7 +6272,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor ASR::ttype_t* arg_type = extract_ttype_t_from_expr(x.m_arg); LCOMPILERS_ASSERT(arg_type != nullptr) int arg_kind = ASRUtils::extract_kind_from_ttype_t(arg_type); - tmp = lfortran_type_to_str(arg, getFPType(arg_kind), "float", arg_kind); + tmp = lfortran_type_to_str(arg, llvm_utils->getFPType(arg_kind), "float", arg_kind); break; } case (ASR::cast_kindType::IntegerToCharacter) : { @@ -7089,7 +6280,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor ASR::ttype_t* arg_type = extract_ttype_t_from_expr(x.m_arg); LCOMPILERS_ASSERT(arg_type != nullptr) int arg_kind = ASRUtils::extract_kind_from_ttype_t(arg_type); - tmp = lfortran_type_to_str(arg, getIntType(arg_kind), "int", arg_kind); + tmp = lfortran_type_to_str(arg, llvm_utils->getIntType(arg_kind), "int", arg_kind); break; } case (ASR::cast_kindType::LogicalToCharacter) : { @@ -7322,14 +6513,14 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor tmp = CreateLoad(arr_descr->get_pointer_to_data(tmp)); } fmt.push_back("%lld"); - llvm::Value* d = builder->CreatePtrToInt(tmp, getIntType(8, false)); + llvm::Value* d = builder->CreatePtrToInt(tmp, llvm_utils->getIntType(8, false)); args.push_back(d); } else if (t->type == ASR::ttypeType::CPtr || (t->type == ASR::ttypeType::Pointer && (ASR::is_a(*v) || ASR::is_a(*v))) ) { fmt.push_back("%lld"); - llvm::Value* d = builder->CreatePtrToInt(tmp, getIntType(8, false)); + llvm::Value* d = builder->CreatePtrToInt(tmp, llvm_utils->getIntType(8, false)); args.push_back(d); } else if (ASRUtils::is_integer(*t)) { switch( a_kind ) { @@ -7447,7 +6638,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor args.push_back(d); } else if (t->type == ASR::ttypeType::CPtr) { fmt.push_back("%lld"); - llvm::Value* d = builder->CreatePtrToInt(tmp, getIntType(8, false)); + llvm::Value* d = builder->CreatePtrToInt(tmp, llvm_utils->getIntType(8, false)); args.push_back(d); } else if (t->type == ASR::ttypeType::Enum) { // TODO: Use recursion to generalise for any underlying type in enum @@ -7592,130 +6783,85 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor if( x.m_args[i].m_value == nullptr ) { LCOMPILERS_ASSERT(orig_arg != nullptr); - llvm::Type* llvm_orig_arg_type = get_type_from_ttype_t_util(orig_arg->m_type); + llvm::Type* llvm_orig_arg_type = llvm_utils->get_type_from_ttype_t_util(orig_arg->m_type, module.get()); llvm::Value* llvm_arg = builder->CreateAlloca(llvm_orig_arg_type); args.push_back(llvm_arg); continue ; } - if (x.m_args[i].m_value->type == ASR::exprType::Var) { - if (is_a(*symbol_get_past_external( - ASR::down_cast(x.m_args[i].m_value)->m_v))) { + if (ASR::is_a(*x.m_args[i].m_value)) { + ASR::symbol_t* var_sym = ASRUtils::symbol_get_past_external( + ASR::down_cast(x.m_args[i].m_value)->m_v); + if (ASR::is_a(*var_sym)) { ASR::Variable_t *arg = EXPR2VAR(x.m_args[i].m_value); uint32_t h = get_hash((ASR::asr_t*)arg); if (llvm_symtab.find(h) != llvm_symtab.end()) { tmp = llvm_symtab[h]; - bool is_data_only_array = false; - bool is_pointer_to_non_pointer = false; - if( orig_arg && - !ASR::is_a(*orig_arg->m_type) && - ASR::is_a(*arg->m_type) ) { - tmp = LLVM::CreateLoad(*builder, tmp); - is_pointer_to_non_pointer = true; - } - ASR::dimension_t* dims_arg = nullptr; - size_t n_arg = ASRUtils::extract_dimensions_from_ttype(arg->m_type, dims_arg); - if( ASRUtils::is_arg_dummy(arg->m_intent) && - !ASRUtils::is_dimension_empty(dims_arg, n_arg) && - n_arg > 0 ) { - is_data_only_array = true; - } - - if( x_abi == ASR::abiType::Source && - arr_descr->is_array(arg->m_type) && - !is_data_only_array ) { - llvm::Type* new_arr_type = arr_arg_type_cache[m_h][orig_arg_name]; - ASR::dimension_t* dims; - size_t n; - n = ASRUtils::extract_dimensions_from_ttype(orig_arg->m_type, dims); - if( !ASRUtils::is_abstract_class_type( ASRUtils::type_get_past_pointer(orig_arg->m_type) ) ) { - tmp = arr_descr->convert_to_argument(tmp, arg->m_type, new_arr_type, - (!ASRUtils::is_dimension_empty(dims, n) && n > 0)); - } - } else if (x_abi == ASR::abiType::Source && ASR::is_a(*arg->m_type)) { + if( !ASRUtils::is_array(arg->m_type) ) { + if (x_abi == ASR::abiType::Source && ASR::is_a(*arg->m_type)) { if (arg->m_intent == intent_local) { // Local variable of type // CPtr is a void**, so we // have to load it tmp = CreateLoad(tmp); } - } else if ( x_abi == ASR::abiType::BindC ) { - if( arr_descr->is_array(ASRUtils::get_contained_type(arg->m_type)) ) { - // TODO: we need a dedicated and robust - // function that determines from ASR only - // if a given array is represented by - // a descriptor or with just a pointer. - // Until then we use the following heuristic: - bool arg_is_using_descriptor = true; - if (LLVMArrUtils::is_explicit_shape(arg)) { - if (arg->m_intent != intent_local) { - arg_is_using_descriptor = false; - } - } - if (arg_is_using_descriptor) { - tmp = CreateLoad(arr_descr->get_pointer_to_data(tmp)); - } - } else { - if (orig_arg->m_abi == ASR::abiType::BindC - && orig_arg->m_value_attr) { - ASR::ttype_t* arg_type = arg->m_type; - if( ASR::is_a(*arg_type) ) { - arg_type = ASR::down_cast(arg_type)->m_type; - } - if (is_a(*arg_type)) { - int c_kind = ASRUtils::extract_kind_from_ttype_t(arg_type); - if (c_kind == 4) { - if (compiler_options.platform == Platform::Windows) { - // tmp is {float, float}* - // type_fx2p is i64* - llvm::Type* type_fx2p = llvm::Type::getInt64PtrTy(context); - // Convert {float,float}* to i64* using bitcast - tmp = builder->CreateBitCast(tmp, type_fx2p); - // Then convert i64* -> i64 - tmp = CreateLoad(tmp); - } else if (compiler_options.platform == Platform::macOS_ARM) { - // tmp is {float, float}* - // type_fx2p is [2 x float]* - llvm::Type* type_fx2p = llvm::ArrayType::get(llvm::Type::getFloatTy(context), 2)->getPointerTo(); - // Convert {float,float}* to [2 x float]* using bitcast - tmp = builder->CreateBitCast(tmp, type_fx2p); - // Then convert [2 x float]* -> [2 x float] - tmp = CreateLoad(tmp); - } else { - // tmp is {float, float}* - // type_fx2p is <2 x float>* - llvm::Type* type_fx2p = FIXED_VECTOR_TYPE::get(llvm::Type::getFloatTy(context), 2)->getPointerTo(); - // Convert {float,float}* to <2 x float>* using bitcast - tmp = builder->CreateBitCast(tmp, type_fx2p); - // Then convert <2 x float>* -> <2 x float> - tmp = CreateLoad(tmp); - } + } else if ( x_abi == ASR::abiType::BindC ) { + if (orig_arg->m_abi == ASR::abiType::BindC && orig_arg->m_value_attr) { + ASR::ttype_t* arg_type = ASRUtils::type_get_past_const(arg->m_type); + if (ASR::is_a(*arg_type)) { + int c_kind = ASRUtils::extract_kind_from_ttype_t(arg_type); + if (c_kind == 4) { + if (compiler_options.platform == Platform::Windows) { + // tmp is {float, float}* + // type_fx2p is i64* + llvm::Type* type_fx2p = llvm::Type::getInt64PtrTy(context); + // Convert {float,float}* to i64* using bitcast + tmp = builder->CreateBitCast(tmp, type_fx2p); + // Then convert i64* -> i64 + tmp = CreateLoad(tmp); + } else if (compiler_options.platform == Platform::macOS_ARM) { + // tmp is {float, float}* + // type_fx2p is [2 x float]* + llvm::Type* type_fx2p = llvm::ArrayType::get(llvm::Type::getFloatTy(context), 2)->getPointerTo(); + // Convert {float,float}* to [2 x float]* using bitcast + tmp = builder->CreateBitCast(tmp, type_fx2p); + // Then convert [2 x float]* -> [2 x float] + tmp = CreateLoad(tmp); } else { - LCOMPILERS_ASSERT(c_kind == 8) - if (compiler_options.platform == Platform::Windows) { - // 128 bit aggregate type is passed by reference - } else { - // Pass by value - tmp = CreateLoad(tmp); - } - } - } else if (is_a(*arg_type)) { - if (arg->m_intent == intent_local) { - // Local variable of type - // CPtr is a void**, so we - // have to load it + // tmp is {float, float}* + // type_fx2p is <2 x float>* + llvm::Type* type_fx2p = FIXED_VECTOR_TYPE::get(llvm::Type::getFloatTy(context), 2)->getPointerTo(); + // Convert {float,float}* to <2 x float>* using bitcast + tmp = builder->CreateBitCast(tmp, type_fx2p); + // Then convert <2 x float>* -> <2 x float> tmp = CreateLoad(tmp); } } else { - if (!arg->m_value_attr) { - // Dereference the pointer argument (unless it is a CPtr) - // to pass by value - // E.g.: - // i32* -> i32 - // {double,double}* -> {double,double} + LCOMPILERS_ASSERT(c_kind == 8) + if (compiler_options.platform == Platform::Windows) { + // 128 bit aggregate type is passed by reference + } else { + // Pass by value tmp = CreateLoad(tmp); } } + } else if (is_a(*arg_type)) { + if (arg->m_intent == intent_local) { + // Local variable of type + // CPtr is a void**, so we + // have to load it + tmp = CreateLoad(tmp); + } + } else { + if (!arg->m_value_attr) { + // Dereference the pointer argument (unless it is a CPtr) + // to pass by value + // E.g.: + // i32* -> i32 + // {double,double}* -> {double,double} + tmp = CreateLoad(tmp); + } } + } if (!orig_arg->m_value_attr && arg->m_value_attr) { llvm::Type *target_type = tmp->getType(); // Create alloca to get a pointer, but do it @@ -7731,19 +6877,17 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor tmp = target; } } - } else if( ASRUtils::get_asr_owner(&(arg->base)) && - ASR::is_a(*ASRUtils::get_asr_owner(&(arg->base))) && - ASRUtils::is_array(arg->m_type) ) { - if( is_pointer_to_non_pointer && orig_arg && - ASRUtils::is_data_only_array(orig_arg->m_type, orig_arg->m_abi) ) { - tmp = arr_descr->get_pointer_to_data(tmp); + } else { + if( orig_arg && + !LLVM::is_llvm_pointer(*orig_arg->m_type) && + LLVM::is_llvm_pointer(*arg->m_type) && + !ASRUtils::is_character(*arg->m_type) ) { tmp = LLVM::CreateLoad(*builder, tmp); } } } else { - if (arg->m_type_declaration - && is_a( - *symbol_get_past_external(arg->m_type_declaration))) { + if ( arg->m_type_declaration && ASR::is_a( + *ASRUtils::symbol_get_past_external(arg->m_type_declaration)) ) { ASR::Function_t* fn = ASR::down_cast( symbol_get_past_external(arg->m_type_declaration)); uint32_t h = get_hash((ASR::asr_t*)fn); @@ -7765,17 +6909,15 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor llvm::IRBuilder<> builder0(context); builder0.SetInsertPoint(&entry_block, entry_block.getFirstInsertionPt()); llvm::AllocaInst *target = builder0.CreateAlloca( - get_type_from_ttype_t_util(arg->m_type), nullptr, "call_arg_value"); + llvm_utils->get_type_from_ttype_t_util(arg->m_type, module.get()), + nullptr, "call_arg_value"); builder->CreateStore(tmp, target); tmp = target; } } } - } else if (is_a(*symbol_get_past_external( - ASR::down_cast(x.m_args[i].m_value)->m_v))) { - ASR::Function_t* fn = ASR::down_cast( - symbol_get_past_external(ASR::down_cast( - x.m_args[i].m_value)->m_v)); + } else if (ASR::is_a(*var_sym)) { + ASR::Function_t* fn = ASR::down_cast(var_sym); uint32_t h = get_hash((ASR::asr_t*)fn); if (ASRUtils::get_FunctionType(fn)->m_deftype == ASR::deftypeType::Implementation) { LCOMPILERS_ASSERT(llvm_symtab_fn.find(h) != llvm_symtab_fn.end()); @@ -7785,6 +6927,8 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor tmp = llvm_symtab_fn_arg[h]; } } + } else if (ASR::is_a(*x.m_args[i].m_value)) { + this->visit_expr_wrapper(x.m_args[i].m_value); } else { ASR::ttype_t* arg_type = expr_type(x.m_args[i].m_value); int64_t ptr_loads_copy = ptr_loads; @@ -7822,29 +6966,29 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor switch (arg_type_->type) { case (ASR::ttypeType::Integer) : { int a_kind = down_cast(arg_type_)->m_kind; - target_type = getIntType(a_kind); + target_type = llvm_utils->getIntType(a_kind); break; } case (ASR::ttypeType::UnsignedInteger) : { int a_kind = down_cast(arg_type_)->m_kind; - target_type = getIntType(a_kind); + target_type = llvm_utils->getIntType(a_kind); break; } case (ASR::ttypeType::Real) : { int a_kind = down_cast(arg_type_)->m_kind; - target_type = getFPType(a_kind); + target_type = llvm_utils->getFPType(a_kind); break; } case (ASR::ttypeType::Complex) : { int a_kind = down_cast(arg_type_)->m_kind; - target_type = getComplexType(a_kind); + target_type = llvm_utils->getComplexType(a_kind); break; } case (ASR::ttypeType::Character) : { ASR::Variable_t *orig_arg = nullptr; if( func_subrout->type == ASR::symbolType::Function ) { ASR::Function_t* func = down_cast(func_subrout); - orig_arg = EXPR2VAR(func->m_args[i]); + orig_arg = ASRUtils::EXPR2VAR(func->m_args[i]); } else { throw CodeGenError("ICE: expected func_subrout->type == ASR::symbolType::Function."); } @@ -7866,17 +7010,19 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor case (ASR::ttypeType::CPtr) : target_type = llvm::Type::getVoidTy(context)->getPointerTo(); break; + case ASR::ttypeType::Allocatable: case (ASR::ttypeType::Pointer) : { - target_type = get_type_from_ttype_t_util(ASRUtils::get_contained_type(arg_type_)); + target_type = llvm_utils->get_type_from_ttype_t_util( + ASRUtils::get_contained_type(arg_type_), module.get()); target_type = target_type->getPointerTo(); break; } case (ASR::ttypeType::List) : { - target_type = get_type_from_ttype_t_util(arg_type_); + target_type = llvm_utils->get_type_from_ttype_t_util(arg_type_, module.get()); break ; } case (ASR::ttypeType::Tuple) : { - target_type = get_type_from_ttype_t_util(arg_type_); + target_type = llvm_utils->get_type_from_ttype_t_util(arg_type_, module.get()); break ; } default : @@ -7972,7 +7118,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor llvm::Value* shifted_signal = builder->CreateShl(signal, num_shifts); llvm::Value* int_var = builder->CreateBitCast(CreateLoad(variable), shifted_signal->getType()); tmp = builder->CreateXor(shifted_signal, int_var); - llvm::Type* variable_type = get_type_from_ttype_t_util(asr_variable->m_type); + llvm::Type* variable_type = llvm_utils->get_type_from_ttype_t_util(asr_variable->m_type, module.get()); builder->CreateStore(builder->CreateBitCast(tmp, variable_type->getPointerTo()), variable); } @@ -8035,10 +7181,10 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor if( ASRUtils::is_abstract_class_type(s_m_args0_type) ) { if( ASRUtils::is_array(s_m_args0_type) ) { - llvm::Type* array_type = get_type_from_ttype_t_util(s_m_args0_type); + llvm::Type* array_type = llvm_utils->get_type_from_ttype_t_util(s_m_args0_type, module.get()); llvm::Value* abstract_array = builder->CreateAlloca(array_type); - llvm::Type* array_data_type = get_el_type( - ASRUtils::type_get_past_array(s_m_args0_type)); + llvm::Type* array_data_type = llvm_utils->get_el_type( + ASRUtils::type_get_past_array(s_m_args0_type), module.get()); llvm::Value* array_data = builder->CreateAlloca(array_data_type); builder->CreateStore(array_data, arr_descr->get_pointer_to_data(abstract_array)); @@ -8052,13 +7198,13 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor polymorphic_data_addr); llvm::Value* type_id_addr = llvm_utils->create_gep(polymorphic_data, 0); builder->CreateStore( - llvm::ConstantInt::get(getIntType(8), + llvm::ConstantInt::get(llvm_utils->getIntType(8), llvm::APInt(64, -((int) ASRUtils::type_get_past_array(arg_type)->type) - ASRUtils::extract_kind_from_ttype_t(arg_type), true)), type_id_addr); return abstract_array; } else { - llvm::Type* _type = get_type_from_ttype_t_util(s_m_args0_type); + llvm::Type* _type = llvm_utils->get_type_from_ttype_t_util(s_m_args0_type, module.get()); llvm::Value* abstract_ = builder->CreateAlloca(_type); llvm::Value* polymorphic_addr = llvm_utils->create_gep(abstract_, 1); builder->CreateStore( @@ -8067,7 +7213,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor llvm::Value* type_id_addr = llvm_utils->create_gep(abstract_, 0); ASR::Struct_t* struct_t = ASR::down_cast(arg_type); ASR::symbol_t* struct_sym = ASRUtils::symbol_get_past_external(struct_t->m_derived_type); - llvm::Value* hash = llvm::ConstantInt::get(getIntType(8), + llvm::Value* hash = llvm::ConstantInt::get(llvm_utils->getIntType(8), llvm::APInt(64, get_class_hash(struct_sym))); builder->CreateStore(hash, type_id_addr); return abstract_; @@ -8080,12 +7226,12 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor create_vtab_for_struct_type(struct_sym, current_scope); } llvm::Value* dt_polymorphic = builder->CreateAlloca( - getClassType(s_m_args0_type, true)); + llvm_utils->getClassType(s_m_args0_type, true)); llvm::Value* hash_ptr = llvm_utils->create_gep(dt_polymorphic, 0); - llvm::Value* hash = llvm::ConstantInt::get(getIntType(8), llvm::APInt(64, get_class_hash(struct_sym))); + llvm::Value* hash = llvm::ConstantInt::get(llvm_utils->getIntType(8), llvm::APInt(64, get_class_hash(struct_sym))); builder->CreateStore(hash, hash_ptr); llvm::Value* class_ptr = llvm_utils->create_gep(dt_polymorphic, 1); - builder->CreateStore(builder->CreateBitCast(dt, getStructType(s_m_args0_type, true)), class_ptr); + builder->CreateStore(builder->CreateBitCast(dt, llvm_utils->getStructType(s_m_args0_type, module.get(), true)), class_ptr); return dt_polymorphic; } return dt; @@ -8246,10 +7392,24 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor void handle_allocated(const ASR::FunctionCall_t& x) { LCOMPILERS_ASSERT(x.n_args == 1); - ASR::call_arg_t arg = x.m_args[0]; - ASR::Variable_t* arg_var = ASRUtils::EXPR2VAR(arg.m_value); - fetch_var(arg_var); - tmp = arr_descr->get_is_allocated_flag(tmp); + ASR::ttype_t* asr_type = ASRUtils::expr_type(x.m_args[0].m_value); + int64_t ptr_loads_copy = ptr_loads; + ptr_loads = 2 - LLVM::is_llvm_pointer(*asr_type); + visit_expr_wrapper(x.m_args[0].m_value, true); + ptr_loads = ptr_loads_copy; + int n_dims = ASRUtils::extract_n_dims_from_ttype(asr_type); + if( n_dims > 0 ) { + llvm::Type* llvm_data_type = llvm_utils->get_type_from_ttype_t_util( + ASRUtils::type_get_past_allocatable( + ASRUtils::type_get_past_pointer( + ASRUtils::type_get_past_array(asr_type))), + module.get(), ASRUtils::expr_abi(x.m_args[0].m_value)); + tmp = arr_descr->get_is_allocated_flag(tmp, llvm_data_type); + } else { + tmp = builder->CreateICmpNE( + builder->CreatePtrToInt(tmp, llvm::Type::getInt64Ty(context)), + llvm::ConstantInt::get(llvm::Type::getInt64Ty(context), llvm::APInt(64, 0)) ); + } } llvm::Value* CreatePointerToStructReturnValue(llvm::FunctionType* fnty, @@ -8315,7 +7475,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor visit_Var(*dt_Var); ptr_loads = ptr_loads_copy; llvm::Value* llvm_dt = tmp; - tmp = builder->CreateAlloca(get_type_from_ttype_t_util(x.m_type)); + tmp = builder->CreateAlloca(llvm_utils->get_type_from_ttype_t_util(x.m_type, module.get())); llvm::BasicBlock *mergeBB = llvm::BasicBlock::Create(context, "ifcont"); for( size_t i = 0; i < vtabs.size(); i++ ) { llvm::Function *fn = builder->GetInsertBlock()->getParent(); @@ -8341,8 +7501,8 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor { std::vector args; ASR::StructType_t* struct_type_t = ASR::down_cast(type_sym); - llvm::Type* target_dt_type = getStructType(struct_type_t, true); - llvm::Type* target_class_dt_type = getClassType(struct_type_t); + llvm::Type* target_dt_type = llvm_utils->getStructType(struct_type_t, module.get(), true); + llvm::Type* target_class_dt_type = llvm_utils->getClassType(struct_type_t); llvm::Value* target_dt = builder->CreateAlloca(target_class_dt_type); llvm::Value* target_dt_hash_ptr = llvm_utils->create_gep(target_dt, 0); builder->CreateStore(vptr_int_hash, target_dt_hash_ptr); @@ -8580,22 +7740,95 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor visit_expr_wrapper(x.m_value, true); return ; } + + int output_kind = ASRUtils::extract_kind_from_ttype_t(x.m_type); int dim_kind = 4; int64_t ptr_loads_copy = ptr_loads; ptr_loads = 2 - // Sync: instead of 2 - , should this be ptr_loads_copy - - (ASRUtils::expr_type(x.m_v)->type == - ASR::ttypeType::Pointer); + LLVM::is_llvm_pointer(*ASRUtils::expr_type(x.m_v)); visit_expr_wrapper(x.m_v); ptr_loads = ptr_loads_copy; llvm::Value* llvm_arg = tmp; + + llvm::Value* llvm_dim = nullptr; if( x.m_dim ) { visit_expr_wrapper(x.m_dim, true); dim_kind = ASRUtils::extract_kind_from_ttype_t(ASRUtils::expr_type(x.m_dim)); llvm_dim = tmp; } - tmp = arr_descr->get_array_size(llvm_arg, llvm_dim, output_kind, dim_kind); + + + ASR::ttype_t* x_mv_type = ASRUtils::expr_type(x.m_v); + ASR::array_physical_typeType physical_type = ASRUtils::extract_physical_type(x_mv_type); + switch( physical_type ) { + case ASR::array_physical_typeType::DescriptorArray: { + tmp = arr_descr->get_array_size(llvm_arg, llvm_dim, output_kind, dim_kind); + break; + } + case ASR::array_physical_typeType::PointerToDataArray: + case ASR::array_physical_typeType::FixedSizeArray: { + llvm::Type* target_type = llvm_utils->get_type_from_ttype_t_util( + ASRUtils::type_get_past_allocatable( + ASRUtils::type_get_past_pointer(x.m_type)), module.get()); + + + ASR::dimension_t* m_dims = nullptr; + int n_dims = ASRUtils::extract_dimensions_from_ttype(x_mv_type, m_dims); + if( llvm_dim ) { + llvm::BasicBlock &entry_block = builder->GetInsertBlock()->getParent()->getEntryBlock(); + llvm::IRBuilder<> builder0(context); + builder0.SetInsertPoint(&entry_block, entry_block.getFirstInsertionPt()); + llvm::AllocaInst *target = builder0.CreateAlloca( + target_type, nullptr, "array_size"); + llvm::BasicBlock *mergeBB = llvm::BasicBlock::Create(context, "ifcont"); + for( int i = 0; i < n_dims; i++ ) { + llvm::Function *fn = builder->GetInsertBlock()->getParent(); + + + llvm::BasicBlock *thenBB = llvm::BasicBlock::Create(context, "then", fn); + llvm::BasicBlock *elseBB = llvm::BasicBlock::Create(context, "else"); + + + llvm::Value* cond = builder->CreateICmpEQ(llvm_dim, + llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), llvm::APInt(32, i + 1))); + builder->CreateCondBr(cond, thenBB, elseBB); + builder->SetInsertPoint(thenBB); + { + this->visit_expr_wrapper(m_dims[i].m_length, true); + builder->CreateStore(tmp, target); + } + builder->CreateBr(mergeBB); + + + start_new_block(elseBB); + } + start_new_block(mergeBB); + tmp = LLVM::CreateLoad(*builder, target); + } else { + int kind = ASRUtils::extract_kind_from_ttype_t(x.m_type); + if( physical_type == ASR::array_physical_typeType::FixedSizeArray ) { + int64_t size = ASRUtils::get_fixed_size_of_array(m_dims, n_dims); + tmp = llvm::ConstantInt::get(target_type, llvm::APInt(8 * kind, size)); + } else { + llvm::Value* llvm_size = llvm::ConstantInt::get(target_type, llvm::APInt(8 * kind, 1)); + int ptr_loads_copy = ptr_loads; + ptr_loads = 2; + for( int i = 0; i < n_dims; i++ ) { + visit_expr_wrapper(m_dims[i].m_length, true); + llvm_size = builder->CreateMul(tmp, llvm_size); + } + ptr_loads = ptr_loads_copy; + tmp = llvm_size; + } + } + break; + } + default: { + LCOMPILERS_ASSERT(false); + } + } } void visit_ArrayBound(const ASR::ArrayBound_t& x) { @@ -8614,26 +7847,88 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor tmp = llvm::ConstantInt::get(context, llvm::APInt(kind * 8, bound_value)); return ; } + int64_t ptr_loads_copy = ptr_loads; ptr_loads = 2 - // Sync: instead of 2 - , should this be ptr_loads_copy - - (ASRUtils::expr_type(x.m_v)->type == - ASR::ttypeType::Pointer); + (LLVM::is_llvm_pointer(*ASRUtils::expr_type(x.m_v))); visit_expr_wrapper(x.m_v); ptr_loads = ptr_loads_copy; llvm::Value* llvm_arg1 = tmp; - llvm::Value* dim_des_val = arr_descr->get_pointer_to_dimension_descriptor_array(llvm_arg1); visit_expr_wrapper(x.m_dim, true); llvm::Value* dim_val = tmp; - llvm::Value* const_1 = llvm::ConstantInt::get(context, llvm::APInt(32, 1)); - dim_val = builder->CreateSub(dim_val, const_1); - llvm::Value* dim_struct = arr_descr->get_pointer_to_dimension_descriptor(dim_des_val, dim_val); - llvm::Value* res = nullptr; - if( x.m_bound == ASR::arrayboundType::LBound ) { - res = arr_descr->get_lower_bound(dim_struct); - } else if( x.m_bound == ASR::arrayboundType::UBound ) { - res = arr_descr->get_upper_bound(dim_struct); - } - tmp = res; + + + ASR::ttype_t* x_mv_type = ASRUtils::expr_type(x.m_v); + ASR::array_physical_typeType physical_type = ASRUtils::extract_physical_type(x_mv_type); + switch( physical_type ) { + case ASR::array_physical_typeType::DescriptorArray: { + llvm::Value* dim_des_val = arr_descr->get_pointer_to_dimension_descriptor_array(llvm_arg1); + llvm::Value* const_1 = llvm::ConstantInt::get(context, llvm::APInt(32, 1)); + dim_val = builder->CreateSub(dim_val, const_1); + llvm::Value* dim_struct = arr_descr->get_pointer_to_dimension_descriptor(dim_des_val, dim_val); + llvm::Value* res = nullptr; + if( x.m_bound == ASR::arrayboundType::LBound ) { + res = arr_descr->get_lower_bound(dim_struct); + } else if( x.m_bound == ASR::arrayboundType::UBound ) { + res = arr_descr->get_upper_bound(dim_struct); + } + tmp = res; + break; + } + case ASR::array_physical_typeType::FixedSizeArray: + case ASR::array_physical_typeType::PointerToDataArray: { + llvm::BasicBlock &entry_block = builder->GetInsertBlock()->getParent()->getEntryBlock(); + llvm::IRBuilder<> builder0(context); + builder0.SetInsertPoint(&entry_block, entry_block.getFirstInsertionPt()); + llvm::Type* target_type = llvm_utils->get_type_from_ttype_t_util( + ASRUtils::type_get_past_allocatable( + ASRUtils::type_get_past_pointer(x.m_type)), module.get()); + llvm::AllocaInst *target = builder0.CreateAlloca( + target_type, nullptr, "array_bound"); + llvm::BasicBlock *mergeBB = llvm::BasicBlock::Create(context, "ifcont"); + ASR::dimension_t* m_dims = nullptr; + int n_dims = ASRUtils::extract_dimensions_from_ttype(x_mv_type, m_dims); + for( int i = 0; i < n_dims; i++ ) { + llvm::Function *fn = builder->GetInsertBlock()->getParent(); + + + llvm::BasicBlock *thenBB = llvm::BasicBlock::Create(context, "then", fn); + llvm::BasicBlock *elseBB = llvm::BasicBlock::Create(context, "else"); + + + llvm::Value* cond = builder->CreateICmpEQ(dim_val, + llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), llvm::APInt(32, i + 1))); + builder->CreateCondBr(cond, thenBB, elseBB); + builder->SetInsertPoint(thenBB); + { + if( x.m_bound == ASR::arrayboundType::LBound ) { + this->visit_expr_wrapper(m_dims[i].m_start, true); + builder->CreateStore(tmp, target); + } else if( x.m_bound == ASR::arrayboundType::UBound ) { + llvm::Value *lbound = nullptr, *length = nullptr; + this->visit_expr_wrapper(m_dims[i].m_start, true); + lbound = tmp; + this->visit_expr_wrapper(m_dims[i].m_length, true); + length = tmp; + builder->CreateStore( + builder->CreateSub(builder->CreateAdd(length, lbound), + llvm::ConstantInt::get(context, llvm::APInt(32, 1))), + target); + } + } + builder->CreateBr(mergeBB); + + + start_new_block(elseBB); + } + start_new_block(mergeBB); + tmp = LLVM::CreateLoad(*builder, target); + break; + } + default: { + LCOMPILERS_ASSERT(false); + } + } } }; diff --git a/src/libasr/codegen/asr_to_wasm.cpp b/src/libasr/codegen/asr_to_wasm.cpp index b6ce115c047..2c2159f34a5 100644 --- a/src/libasr/codegen/asr_to_wasm.cpp +++ b/src/libasr/codegen/asr_to_wasm.cpp @@ -2423,6 +2423,9 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { } for (int i = (int)vars_passed_by_refs.size() - 1; i >= 0; i--) { ASR::expr_t* return_expr = vars_passed_by_refs[i]; + if( ASR::is_a(*return_expr) ) { + return_expr = ASR::down_cast(return_expr)->m_arg; + } if (ASR::is_a(*return_expr)) { ASR::Variable_t* return_var = ASRUtils::EXPR2VAR(return_expr); emit_var_set(return_var); @@ -2448,6 +2451,10 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { arg_kind = ASRUtils::extract_kind_from_ttype_t(curr_type); } + void visit_ArrayPhysicalCast(const ASR::ArrayPhysicalCast_t& x) { + this->visit_expr(*x.m_arg); + } + void visit_Cast(const ASR::Cast_t &x) { if (x.m_value) { this->visit_expr(*x.m_value); diff --git a/src/libasr/codegen/asr_to_x86.cpp b/src/libasr/codegen/asr_to_x86.cpp index e3002e5062c..7755f11c484 100644 --- a/src/libasr/codegen/asr_to_x86.cpp +++ b/src/libasr/codegen/asr_to_x86.cpp @@ -6,8 +6,8 @@ #include #include #include -#include -#include +#include +#include #include #include @@ -577,7 +577,7 @@ Result asr_to_x86(ASR::TranslationUnit_t &asr, Allocator &al, { auto t1 = std::chrono::high_resolution_clock::now(); - pass_wrap_global_stmts_into_function(al, asr, pass_options); + pass_wrap_global_stmts(al, asr, pass_options); auto t2 = std::chrono::high_resolution_clock::now(); time_pass_global = std::chrono::duration_cast(t2 - t1).count(); } diff --git a/src/libasr/codegen/c_utils.h b/src/libasr/codegen/c_utils.h index 84dbed81e27..4ac7fb7e949 100644 --- a/src/libasr/codegen/c_utils.h +++ b/src/libasr/codegen/c_utils.h @@ -842,14 +842,14 @@ class CCPPDSUtils { + struct_type_str + "* src, " + struct_type_str + "* dest)"; func_decls += "inline " + signature + ";\n"; - generated_code += indent + signature + " {\n"; + std::string tmp_generated = indent + signature + " {\n"; for(size_t i=0; i < struct_type_t->n_members; i++) { std::string mem_name = std::string(struct_type_t->m_members[i]); ASR::symbol_t* member = struct_type_t->m_symtab->get_symbol(mem_name); ASR::ttype_t* member_type_asr = ASRUtils::symbol_type(member); if( CUtils::is_non_primitive_DT(member_type_asr) || ASR::is_a(*member_type_asr) ) { - generated_code += indent + tab + get_deepcopy(member_type_asr, "&(src->" + mem_name + ")", + tmp_generated += indent + tab + get_deepcopy(member_type_asr, "&(src->" + mem_name + ")", "&(dest->" + mem_name + ")") + ";\n"; } else if( ASRUtils::is_array(member_type_asr) ) { ASR::dimension_t* m_dims = nullptr; @@ -857,17 +857,18 @@ class CCPPDSUtils { if( ASRUtils::is_fixed_size_array(m_dims, n_dims) ) { std::string array_size = std::to_string(ASRUtils::get_fixed_size_of_array(m_dims, n_dims)); array_size += "*sizeof(" + CUtils::get_c_type_from_ttype_t(member_type_asr) + ")"; - generated_code += indent + tab + "memcpy(dest->" + mem_name + ", src->" + mem_name + + tmp_generated += indent + tab + "memcpy(dest->" + mem_name + ", src->" + mem_name + ", " + array_size + ");\n"; } else { - generated_code += indent + tab + get_deepcopy(member_type_asr, "src->" + mem_name, + tmp_generated += indent + tab + get_deepcopy(member_type_asr, "src->" + mem_name, "dest->" + mem_name) + ";\n"; } } else { - generated_code += indent + tab + "dest->" + mem_name + " = " + " src->" + mem_name + ";\n"; + tmp_generated += indent + tab + "dest->" + mem_name + " = " + " src->" + mem_name + ";\n"; } } - generated_code += indent + "}\n\n"; + tmp_generated += indent + "}\n\n"; + generated_code += tmp_generated; } void list_deepcopy(std::string list_struct_type, diff --git a/src/libasr/codegen/llvm_array_utils.cpp b/src/libasr/codegen/llvm_array_utils.cpp index eae2ab02633..bd6d57fb845 100644 --- a/src/libasr/codegen/llvm_array_utils.cpp +++ b/src/libasr/codegen/llvm_array_utils.cpp @@ -187,30 +187,6 @@ namespace LCompilers { return dim_des->getPointerTo(); } - llvm::Type* SimpleCMODescriptor::get_malloc_array_type - (ASR::ttype_t* m_type_, llvm::Type* el_type, bool get_pointer) { - std::string array_key = ASRUtils::get_type_code(m_type_, false, false); - if( tkr2array.find(array_key) != tkr2array.end() ) { - if( get_pointer ) { - return tkr2array[array_key].first->getPointerTo(); - } - return tkr2array[array_key].first; - } - llvm::Type* dim_des_array = create_dimension_descriptor_array_type(); - std::vector array_type_vec = { - el_type->getPointerTo(), - llvm::Type::getInt32Ty(context), - dim_des_array, - llvm::Type::getInt1Ty(context), - llvm::Type::getInt32Ty(context)}; - llvm::StructType* new_array_type = llvm::StructType::create(context, array_type_vec, "array"); - tkr2array[array_key] = std::make_pair(new_array_type, el_type); - if( get_pointer ) { - return tkr2array[array_key].first->getPointerTo(); - } - return (llvm::Type*) tkr2array[array_key].first; - } - llvm::Type* SimpleCMODescriptor::get_dimension_descriptor_type (bool get_pointer) { if( !get_pointer ) { @@ -308,30 +284,29 @@ namespace LCompilers { LCOMPILERS_ASSERT(false); } + llvm::Value* source_offset_val = LLVM::CreateLoad(*builder, llvm_utils->create_gep(source, 1)); llvm::Value* dest_offset = llvm_utils->create_gep(destination, 1); builder->CreateStore(source_offset_val, dest_offset); + llvm::Value* source_dim_des_val = LLVM::CreateLoad(*builder, llvm_utils->create_gep(source, 2)); llvm::Value* dest_dim_des_ptr = llvm_utils->create_gep(destination, 2); builder->CreateStore(source_dim_des_val, dest_dim_des_ptr); - llvm::Value* source_allocated_flag = this->get_is_allocated_flag(source); - llvm::Value* destination_allocated_flag_ptr = llvm_utils->create_gep(destination, 3); - builder->CreateStore(source_allocated_flag, destination_allocated_flag_ptr); llvm::Value* source_rank = this->get_rank(source, false); this->set_rank(destination, source_rank); }; void SimpleCMODescriptor::fill_malloc_array_details( - llvm::Value* arr, llvm::Type* llvm_data_type, int n_dims, - std::vector>& llvm_dims, - llvm::Module* module) { + llvm::Value* arr, llvm::Type* llvm_data_type, int n_dims, + std::vector>& llvm_dims, + llvm::Module* module) { + arr = LLVM::CreateLoad(*builder, arr); llvm::Value* offset_val = llvm_utils->create_gep(arr, 1); builder->CreateStore(llvm::ConstantInt::get(context, llvm::APInt(32, 0)), offset_val); - set_is_allocated_flag(arr, 1); llvm::Value* dim_des_val = LLVM::CreateLoad(*builder, llvm_utils->create_gep(arr, 2)); llvm::Value* prod = llvm::ConstantInt::get(context, llvm::APInt(32, 1)); for( int r = 0; r < n_dims; r++ ) { @@ -378,6 +353,7 @@ namespace LCompilers { llvm::Value* target_data = get_pointer_to_data(target); builder->CreateStore(value_desc_data, target_data); + std::vector section_first_indices; for( int i = 0; i < value_rank; i++ ) { if( ds[i] != nullptr ) { @@ -392,6 +368,7 @@ namespace LCompilers { value_desc, section_first_indices, value_rank, false); builder->CreateStore(target_offset, get_offset(target, false)); + llvm::Value* value_dim_des_array = get_pointer_to_dimension_descriptor_array(value_desc); llvm::Value* target_dim_des_array = get_pointer_to_dimension_descriptor_array(target); int j = 0; @@ -417,7 +394,6 @@ namespace LCompilers { } } LCOMPILERS_ASSERT(j == target_rank); - set_is_allocated_flag(target, get_is_allocated_flag(value_desc)); builder->CreateStore( llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), llvm::APInt(32, target_rank)), @@ -470,8 +446,6 @@ namespace LCompilers { r += 2; } LCOMPILERS_ASSERT(j == target_rank); - set_is_allocated_flag(target, - llvm::ConstantInt::get(llvm::Type::getInt1Ty(context), llvm::APInt(1, 1))); builder->CreateStore( llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), llvm::APInt(32, target_rank)), @@ -571,7 +545,7 @@ namespace LCompilers { // bool check_for_bounds = is_explicit_shape(v); bool check_for_bounds = false; llvm::Value* idx = nullptr; - if( data_only ) { + if( data_only || is_fixed_size ) { LCOMPILERS_ASSERT(llvm_diminfo); idx = cmo_convertor_single_element_data_only(llvm_diminfo, m_args, n_args, check_for_bounds); if( is_fixed_size ) { @@ -593,19 +567,22 @@ namespace LCompilers { return tmp; } - llvm::Value* SimpleCMODescriptor::get_is_allocated_flag(llvm::Value* array) { - return LLVM::CreateLoad(*builder, llvm_utils->create_gep(array, 3)); - } - - void SimpleCMODescriptor::set_is_allocated_flag(llvm::Value* array, bool status) { - llvm::Value* is_allocated_flag = llvm_utils->create_gep(array, 3); - builder->CreateStore(llvm::ConstantInt::get(context, llvm::APInt(1, (uint64_t) status)), - is_allocated_flag); + llvm::Value* SimpleCMODescriptor::get_is_allocated_flag(llvm::Value* array, + llvm::Type* llvm_data_type) { + return builder->CreateICmpNE( + builder->CreatePtrToInt(LLVM::CreateLoad(*builder, get_pointer_to_data(array)), + llvm::Type::getInt64Ty(context)), + builder->CreatePtrToInt(llvm::ConstantPointerNull::get(llvm_data_type->getPointerTo()), + llvm::Type::getInt64Ty(context)) + ); } - void SimpleCMODescriptor::set_is_allocated_flag(llvm::Value* array, llvm::Value* status) { - llvm::Value* is_allocated_flag = llvm_utils->create_gep(array, 3); - builder->CreateStore(status, is_allocated_flag); + void SimpleCMODescriptor::reset_is_allocated_flag(llvm::Value* array, + llvm::Type* llvm_data_type) { + builder->CreateStore( + llvm::ConstantPointerNull::get(llvm_data_type->getPointerTo()), + get_pointer_to_data(array) + ); } llvm::Value* SimpleCMODescriptor::get_array_size(llvm::Value* array, llvm::Value* dim, int kind, int dim_kind) { @@ -792,14 +769,12 @@ namespace LCompilers { // end llvm_utils->start_new_block(loopend); - llvm::Value* src_is_allocated_ptr = this->get_is_allocated_flag(src); - builder->CreateStore(src_is_allocated_ptr, llvm_utils->create_gep(src, 3)); + builder->CreateStore(n_dims, this->get_rank(dest, true)); } void SimpleCMODescriptor::copy_array_data_only(llvm::Value* src, llvm::Value* dest, - llvm::Module* module, ASR::ttype_t* asr_data_type, llvm::Value* num_elements) { - llvm::Type* llvm_data_type = tkr2array[ASRUtils::get_type_code(asr_data_type, false, false)].second; + llvm::Module* module, llvm::Type* llvm_data_type, llvm::Value* num_elements) { llvm::DataLayout data_layout(module); uint64_t size = data_layout.getTypeAllocSize(llvm_data_type); llvm::Value* llvm_size = llvm::ConstantInt::get(context, llvm::APInt(32, size)); diff --git a/src/libasr/codegen/llvm_array_utils.h b/src/libasr/codegen/llvm_array_utils.h index aa528d3b47f..582a8d1abe7 100644 --- a/src/libasr/codegen/llvm_array_utils.h +++ b/src/libasr/codegen/llvm_array_utils.h @@ -118,17 +118,6 @@ namespace LCompilers { llvm::Type* el_type, bool get_pointer=false) = 0; - /* - * Same as get_array_type but for allocatable - * arrays. It doesn't require dimensions for - * creating array llvm::Type*. - */ - virtual - llvm::Type* get_malloc_array_type( - ASR::ttype_t* m_type_, - llvm::Type* el_type, - bool get_pointer=false) = 0; - /* * Creates an array of dimension descriptors * whose each element describes structure @@ -276,13 +265,11 @@ namespace LCompilers { bool polymorphic=false, llvm::Type* polymorphic_type=nullptr) = 0; virtual - llvm::Value* get_is_allocated_flag(llvm::Value* array) = 0; + llvm::Value* get_is_allocated_flag(llvm::Value* array, llvm::Type* llvm_data_type) = 0; virtual - void set_is_allocated_flag(llvm::Value* array, bool status) = 0; + void reset_is_allocated_flag(llvm::Value* array, llvm::Type* llvm_data_type) = 0; - virtual - void set_is_allocated_flag(llvm::Value* array, llvm::Value* status) = 0; virtual llvm::Value* reshape(llvm::Value* array, llvm::Type* llvm_data_type, @@ -296,7 +283,7 @@ namespace LCompilers { virtual void copy_array_data_only(llvm::Value* src, llvm::Value* dest, - llvm::Module* module, ASR::ttype_t* asr_data_type, + llvm::Module* module, llvm::Type* llvm_data_type, llvm::Value* num_elements) = 0; virtual @@ -353,12 +340,6 @@ namespace LCompilers { llvm::Type* el_type, bool get_pointer=false); - virtual - llvm::Type* get_malloc_array_type( - ASR::ttype_t* m_type_, - llvm::Type* el_type, - bool get_pointer=false); - virtual llvm::Type* create_dimension_descriptor_array_type(); @@ -444,13 +425,10 @@ namespace LCompilers { bool polymorphic=false, llvm::Type* polymorphic_type=nullptr); virtual - llvm::Value* get_is_allocated_flag(llvm::Value* array); - - virtual - void set_is_allocated_flag(llvm::Value* array, bool status); + llvm::Value* get_is_allocated_flag(llvm::Value* array, llvm::Type* llvm_data_type); virtual - void set_is_allocated_flag(llvm::Value* array, llvm::Value* status); + void reset_is_allocated_flag(llvm::Value* array, llvm::Type* llvm_data_type); virtual llvm::Value* reshape(llvm::Value* array, llvm::Type* llvm_data_type, @@ -464,7 +442,7 @@ namespace LCompilers { virtual void copy_array_data_only(llvm::Value* src, llvm::Value* dest, - llvm::Module* module, ASR::ttype_t* asr_data_type, + llvm::Module* module, llvm::Type* llvm_data_type, llvm::Value* num_elements); virtual diff --git a/src/libasr/codegen/llvm_utils.cpp b/src/libasr/codegen/llvm_utils.cpp index f90649826fa..fe84cc186af 100644 --- a/src/libasr/codegen/llvm_utils.cpp +++ b/src/libasr/codegen/llvm_utils.cpp @@ -107,17 +107,1181 @@ namespace LCompilers { } // namespace LLVM LLVMUtils::LLVMUtils(llvm::LLVMContext& context, - llvm::IRBuilder<>* _builder): - context(context), - builder(std::move(_builder)), - str_cmp_itr(nullptr), - are_iterators_set(false) { + llvm::IRBuilder<>* _builder, std::string& der_type_name_, + std::map& name2dertype_, + std::map& name2dercontext_, + std::vector& struct_type_stack_, + std::map& dertype2parent_, + std::map>& name2memidx_, + CompilerOptions &compiler_options_, + std::unordered_map>& arr_arg_type_cache_, + std::map>& fname2arg_type_): + context(context), builder(std::move(_builder)), str_cmp_itr(nullptr), + are_iterators_set(false), der_type_name(der_type_name_), + name2dertype(name2dertype_), name2dercontext(name2dercontext_), + struct_type_stack(struct_type_stack_), dertype2parent(dertype2parent_), + name2memidx(name2memidx_), arr_arg_type_cache(arr_arg_type_cache_), fname2arg_type(fname2arg_type_), + dict_api_lp(nullptr), dict_api_sc(nullptr), compiler_options(compiler_options_) { + std::vector els_4 = { + llvm::Type::getFloatTy(context), + llvm::Type::getFloatTy(context)}; + std::vector els_8 = { + llvm::Type::getDoubleTy(context), + llvm::Type::getDoubleTy(context)}; + std::vector els_4_ptr = { + llvm::Type::getFloatPtrTy(context), + llvm::Type::getFloatPtrTy(context)}; + std::vector els_8_ptr = { + llvm::Type::getDoublePtrTy(context), + llvm::Type::getDoublePtrTy(context)}; + complex_type_4 = llvm::StructType::create(context, els_4, "complex_4"); + complex_type_8 = llvm::StructType::create(context, els_8, "complex_8"); + complex_type_4_ptr = llvm::StructType::create(context, els_4_ptr, "complex_4_ptr"); + complex_type_8_ptr = llvm::StructType::create(context, els_8_ptr, "complex_8_ptr"); + character_type = llvm::Type::getInt8PtrTy(context); } void LLVMUtils::set_module(llvm::Module* module_) { module = module_; } + llvm::Type* LLVMUtils::getMemberType(ASR::ttype_t* mem_type, ASR::Variable_t* member, + llvm::Module* module) { + llvm::Type* llvm_mem_type = nullptr; + switch( mem_type->type ) { + case ASR::ttypeType::Integer: { + int a_kind = ASR::down_cast(mem_type)->m_kind; + llvm_mem_type = getIntType(a_kind); + break; + } + case ASR::ttypeType::Real: { + int a_kind = ASR::down_cast(mem_type)->m_kind; + llvm_mem_type = getFPType(a_kind); + break; + } + case ASR::ttypeType::Struct: { + llvm_mem_type = getStructType(mem_type, module); + break; + } + case ASR::ttypeType::Enum: { + llvm_mem_type = llvm::Type::getInt32Ty(context); + break ; + } + case ASR::ttypeType::Union: { + llvm_mem_type = getUnionType(mem_type, module); + break; + } + case ASR::ttypeType::Allocatable: { + ASR::Allocatable_t* ptr_type = ASR::down_cast(mem_type); + llvm_mem_type = getMemberType(ptr_type->m_type, member, module)->getPointerTo(); + break; + } + case ASR::ttypeType::Pointer: { + ASR::Pointer_t* ptr_type = ASR::down_cast(mem_type); + llvm_mem_type = getMemberType(ptr_type->m_type, member, module)->getPointerTo(); + break; + } + case ASR::ttypeType::Complex: { + int a_kind = ASR::down_cast(mem_type)->m_kind; + llvm_mem_type = getComplexType(a_kind); + break; + } + case ASR::ttypeType::Character: { + llvm_mem_type = character_type; + break; + } + case ASR::ttypeType::CPtr: { + llvm_mem_type = llvm::Type::getVoidTy(context)->getPointerTo(); + break; + } + default: + throw CodeGenError("Cannot identify the type of member, '" + + std::string(member->m_name) + + "' in derived type, '" + der_type_name + "'.", + member->base.base.loc); + } + return llvm_mem_type; + } + + void LLVMUtils::createStructContext(ASR::StructType_t* der_type) { + std::string der_type_name = std::string(der_type->m_name); + if (name2dercontext.find(der_type_name) == name2dercontext.end() ) { + llvm::StructType* der_type_llvm = llvm::StructType::create(context, + {}, + der_type_name, + der_type->m_is_packed); + name2dercontext[der_type_name] = der_type_llvm; + if( der_type->m_parent != nullptr ) { + ASR::StructType_t *par_der_type = ASR::down_cast( + ASRUtils::symbol_get_past_external(der_type->m_parent)); + createStructContext(par_der_type); + } + for( size_t i = 0; i < der_type->n_members; i++ ) { + std::string member_name = der_type->m_members[i]; + ASR::symbol_t* sym = der_type->m_symtab->get_symbol(member_name); + if (ASR::is_a(*sym)) { + ASR::StructType_t *d_type = ASR::down_cast(sym); + createStructContext(d_type); + } + } + } + } + + llvm::Type* LLVMUtils::getStructType(ASR::StructType_t* der_type, llvm::Module* module, bool is_pointer) { + std::string der_type_name = std::string(der_type->m_name); + createStructContext(der_type); + if (std::find(struct_type_stack.begin(), struct_type_stack.end(), + der_type_name) != struct_type_stack.end()) { + LCOMPILERS_ASSERT(name2dercontext.find(der_type_name) != name2dercontext.end()); + return name2dercontext[der_type_name]; + } + struct_type_stack.push_back(der_type_name); + llvm::StructType** der_type_llvm; + if (name2dertype.find(der_type_name) != name2dertype.end() ) { + der_type_llvm = &name2dertype[der_type_name]; + } else { + der_type_llvm = &name2dercontext[der_type_name]; + std::vector member_types; + int member_idx = 0; + if( der_type->m_parent != nullptr ) { + ASR::StructType_t *par_der_type = ASR::down_cast( + ASRUtils::symbol_get_past_external(der_type->m_parent)); + llvm::Type* par_llvm = getStructType(par_der_type, module); + member_types.push_back(par_llvm); + dertype2parent[der_type_name] = std::string(par_der_type->m_name); + member_idx += 1; + } + for( size_t i = 0; i < der_type->n_members; i++ ) { + std::string member_name = der_type->m_members[i]; + ASR::Variable_t* member = ASR::down_cast(der_type->m_symtab->get_symbol(member_name)); + llvm::Type* llvm_mem_type = get_type_from_ttype_t_util(member->m_type, module, member->m_abi); + member_types.push_back(llvm_mem_type); + name2memidx[der_type_name][std::string(member->m_name)] = member_idx; + member_idx++; + } + (*der_type_llvm)->setBody(member_types); + name2dertype[der_type_name] = *der_type_llvm; + } + struct_type_stack.pop_back(); + if ( is_pointer ) { + return (*der_type_llvm)->getPointerTo(); + } + return (llvm::Type*) *der_type_llvm; + } + + llvm::Type* LLVMUtils::getStructType(ASR::ttype_t* _type, llvm::Module* module, bool is_pointer) { + ASR::StructType_t* der_type; + if( ASR::is_a(*_type) ) { + ASR::Struct_t* der = ASR::down_cast(_type); + ASR::symbol_t* der_sym = ASRUtils::symbol_get_past_external(der->m_derived_type); + der_type = ASR::down_cast(der_sym); + } else if( ASR::is_a(*_type) ) { + ASR::Class_t* der = ASR::down_cast(_type); + ASR::symbol_t* der_sym = ASRUtils::symbol_get_past_external(der->m_class_type); + der_type = ASR::down_cast(der_sym); + } else { + LCOMPILERS_ASSERT(false); + return nullptr; // silence a warning + } + llvm::Type* type = getStructType(der_type, module, is_pointer); + LCOMPILERS_ASSERT(type != nullptr); + return type; + } + + llvm::Type* LLVMUtils::getUnionType(ASR::UnionType_t* union_type, + llvm::Module* module, bool is_pointer) { + std::string union_type_name = std::string(union_type->m_name); + llvm::StructType* union_type_llvm = nullptr; + if( name2dertype.find(union_type_name) != name2dertype.end() ) { + union_type_llvm = name2dertype[union_type_name]; + } else { + const std::map& scope = union_type->m_symtab->get_scope(); + llvm::DataLayout data_layout(module); + llvm::Type* max_sized_type = nullptr; + size_t max_type_size = 0; + for( auto itr = scope.begin(); itr != scope.end(); itr++ ) { + ASR::Variable_t* member = ASR::down_cast(ASRUtils::symbol_get_past_external(itr->second)); + llvm::Type* llvm_mem_type = getMemberType(member->m_type, member, module); + size_t type_size = data_layout.getTypeAllocSize(llvm_mem_type); + if( max_type_size < type_size ) { + max_sized_type = llvm_mem_type; + type_size = max_type_size; + } + } + union_type_llvm = llvm::StructType::create(context, {max_sized_type}, union_type_name); + name2dertype[union_type_name] = union_type_llvm; + } + if( is_pointer ) { + return union_type_llvm->getPointerTo(); + } + return (llvm::Type*) union_type_llvm; + } + + llvm::Type* LLVMUtils::getUnionType(ASR::ttype_t* _type, llvm::Module* module, bool is_pointer) { + ASR::Union_t* union_ = ASR::down_cast(_type); + ASR::symbol_t* union_sym = ASRUtils::symbol_get_past_external(union_->m_union_type); + ASR::UnionType_t* union_type = ASR::down_cast(union_sym); + return getUnionType(union_type, module, is_pointer); + } + + llvm::Type* LLVMUtils::getClassType(ASR::ClassType_t* der_type, bool is_pointer) { + const std::map& scope = der_type->m_symtab->get_scope(); + std::vector member_types; + int member_idx = 0; + for( auto itr = scope.begin(); itr != scope.end(); itr++ ) { + if (!ASR::is_a(*itr->second) && + !ASR::is_a(*itr->second) && + !ASR::is_a(*itr->second)) { + ASR::Variable_t* member = ASR::down_cast(itr->second); + llvm::Type* mem_type = nullptr; + switch( member->m_type->type ) { + case ASR::ttypeType::Integer: { + int a_kind = ASR::down_cast(member->m_type)->m_kind; + mem_type = getIntType(a_kind); + break; + } + case ASR::ttypeType::Real: { + int a_kind = ASR::down_cast(member->m_type)->m_kind; + mem_type = getFPType(a_kind); + break; + } + case ASR::ttypeType::Class: { + mem_type = getClassType(member->m_type); + break; + } + case ASR::ttypeType::Complex: { + int a_kind = ASR::down_cast(member->m_type)->m_kind; + mem_type = getComplexType(a_kind); + break; + } + default: + throw CodeGenError("Cannot identify the type of member, '" + + std::string(member->m_name) + + "' in derived type, '" + der_type_name + "'.", + member->base.base.loc); + } + member_types.push_back(mem_type); + name2memidx[der_type_name][std::string(member->m_name)] = member_idx; + member_idx++; + } + } + llvm::StructType* der_type_llvm = llvm::StructType::create(context, member_types, der_type_name); + name2dertype[der_type_name] = der_type_llvm; + if( is_pointer ) { + return der_type_llvm->getPointerTo(); + } + return (llvm::Type*) der_type_llvm; + } + + llvm::Type* LLVMUtils::getClassType(ASR::StructType_t* der_type, bool is_pointer) { + std::string der_type_name = std::string(der_type->m_name) + std::string("_polymorphic"); + llvm::StructType* der_type_llvm = nullptr; + if( name2dertype.find(der_type_name) != name2dertype.end() ) { + der_type_llvm = name2dertype[der_type_name]; + } + LCOMPILERS_ASSERT(der_type_llvm != nullptr); + if( is_pointer ) { + return der_type_llvm->getPointerTo(); + } + return (llvm::Type*) der_type_llvm; + } + + llvm::Type* LLVMUtils::getClassType(ASR::ttype_t* _type, bool is_pointer) { + ASR::Class_t* der = ASR::down_cast(_type); + ASR::symbol_t* der_sym = ASRUtils::symbol_get_past_external(der->m_class_type); + std::string der_sym_name = ASRUtils::symbol_name(der_sym); + std::string der_type_name = der_sym_name + std::string("_polymorphic"); + llvm::StructType* der_type_llvm; + if( name2dertype.find(der_type_name) != name2dertype.end() ) { + der_type_llvm = name2dertype[der_type_name]; + } else { + std::vector member_types; + member_types.push_back(getIntType(8)); + if( der_sym_name == "~abstract_type" ) { + member_types.push_back(llvm::Type::getVoidTy(context)->getPointerTo()); + } else if( ASR::is_a(*der_sym) ) { + ASR::ClassType_t* class_type_t = ASR::down_cast(der_sym); + member_types.push_back(getClassType(class_type_t, is_pointer)); + } else if( ASR::is_a(*der_sym) ) { + ASR::StructType_t* struct_type_t = ASR::down_cast(der_sym); + member_types.push_back(getStructType(struct_type_t, module, is_pointer)); + } + der_type_llvm = llvm::StructType::create(context, member_types, der_type_name); + name2dertype[der_type_name] = der_type_llvm; + } + + return (llvm::Type*) der_type_llvm; + } + + llvm::Type* LLVMUtils::getFPType(int a_kind, bool get_pointer) { + llvm::Type* type_ptr = nullptr; + if( get_pointer ) { + switch(a_kind) + { + case 4: + type_ptr = llvm::Type::getFloatPtrTy(context); + break; + case 8: + type_ptr = llvm::Type::getDoublePtrTy(context); + break; + default: + throw CodeGenError("Only 32 and 64 bits real kinds are supported."); + } + } else { + switch(a_kind) + { + case 4: + type_ptr = llvm::Type::getFloatTy(context); + break; + case 8: + type_ptr = llvm::Type::getDoubleTy(context); + break; + default: + throw CodeGenError("Only 32 and 64 bits real kinds are supported."); + } + } + return type_ptr; + } + + llvm::Type* LLVMUtils::getComplexType(int a_kind, bool get_pointer) { + llvm::Type* type = nullptr; + switch(a_kind) + { + case 4: + type = complex_type_4; + break; + case 8: + type = complex_type_8; + break; + default: + throw CodeGenError("Only 32 and 64 bits complex kinds are supported."); + } + if( type != nullptr ) { + if( get_pointer ) { + return type->getPointerTo(); + } else { + return type; + } + } + return nullptr; + } + + llvm::Type* LLVMUtils::get_el_type(ASR::ttype_t* m_type_, llvm::Module* module) { + int a_kind = ASRUtils::extract_kind_from_ttype_t(m_type_); + llvm::Type* el_type = nullptr; + if (ASR::is_a(*m_type_)) { + ASR::ttype_t *t2 = ASR::down_cast(m_type_)->m_type; + switch(t2->type) { + case ASR::ttypeType::Integer: { + el_type = getIntType(a_kind, true); + break; + } + case ASR::ttypeType::UnsignedInteger: { + el_type = getIntType(a_kind, true); + break; + } + case ASR::ttypeType::Real: { + el_type = getFPType(a_kind, true); + break; + } + case ASR::ttypeType::Complex: { + el_type = getComplexType(a_kind, true); + break; + } + case ASR::ttypeType::Logical: { + el_type = llvm::Type::getInt1Ty(context); + break; + } + case ASR::ttypeType::Struct: { + el_type = getStructType(m_type_, module); + break; + } + case ASR::ttypeType::Union: { + el_type = getUnionType(m_type_, module); + break; + } + case ASR::ttypeType::Character: { + el_type = character_type; + break; + } + default: + LCOMPILERS_ASSERT(false); + break; + } + } else { + switch(m_type_->type) { + case ASR::ttypeType::Integer: { + el_type = getIntType(a_kind); + break; + } + case ASR::ttypeType::UnsignedInteger: { + el_type = getIntType(a_kind); + break; + } + case ASR::ttypeType::Real: { + el_type = getFPType(a_kind); + break; + } + case ASR::ttypeType::Complex: { + el_type = getComplexType(a_kind); + break; + } + case ASR::ttypeType::Logical: { + el_type = llvm::Type::getInt1Ty(context); + break; + } + case ASR::ttypeType::Struct: { + el_type = getStructType(m_type_, module); + break; + } + case ASR::ttypeType::Character: { + el_type = character_type; + break; + } + case ASR::ttypeType::Class: { + el_type = getClassType(m_type_); + break; + } + default: + LCOMPILERS_ASSERT(false); + break; + } + } + return el_type; + } + + int32_t get_type_size(ASR::ttype_t* asr_type, llvm::Type* llvm_type, + int32_t a_kind, llvm::Module* module) { + if( LLVM::is_llvm_struct(asr_type) || + ASR::is_a(*asr_type) || + ASR::is_a(*asr_type) ) { + llvm::DataLayout data_layout(module); + return data_layout.getTypeAllocSize(llvm_type); + } + return a_kind; + } + + llvm::Type* LLVMUtils::get_dict_type(ASR::ttype_t* asr_type, llvm::Module* module) { + ASR::Dict_t* asr_dict = ASR::down_cast(asr_type); + bool is_local_array_type = false, is_local_malloc_array_type = false; + bool is_local_list = false; + ASR::dimension_t* local_m_dims = nullptr; + int local_n_dims = 0; + int local_a_kind = -1; + ASR::storage_typeType local_m_storage = ASR::storage_typeType::Default; + llvm::Type* key_llvm_type = get_type_from_ttype_t(asr_dict->m_key_type, nullptr, local_m_storage, + is_local_array_type, is_local_malloc_array_type, + is_local_list, local_m_dims, local_n_dims, + local_a_kind, module); + int32_t key_type_size = get_type_size(asr_dict->m_key_type, key_llvm_type, local_a_kind, module); + llvm::Type* value_llvm_type = get_type_from_ttype_t(asr_dict->m_value_type, nullptr, local_m_storage, + is_local_array_type, is_local_malloc_array_type, + is_local_list, local_m_dims, local_n_dims, + local_a_kind, module); + int32_t value_type_size = get_type_size(asr_dict->m_value_type, value_llvm_type, local_a_kind, module); + std::string key_type_code = ASRUtils::get_type_code(asr_dict->m_key_type); + std::string value_type_code = ASRUtils::get_type_code(asr_dict->m_value_type); + set_dict_api(asr_dict); + return dict_api->get_dict_type(key_type_code, value_type_code, key_type_size, + value_type_size, key_llvm_type, value_llvm_type); + } + + llvm::Type* LLVMUtils::get_set_type(ASR::ttype_t* asr_type, llvm::Module* module) { + ASR::Set_t* asr_set = ASR::down_cast(asr_type); + bool is_local_array_type = false, is_local_malloc_array_type = false; + bool is_local_list = false; + ASR::dimension_t* local_m_dims = nullptr; + int local_n_dims = 0; + int local_a_kind = -1; + ASR::storage_typeType local_m_storage = ASR::storage_typeType::Default; + llvm::Type* el_llvm_type = get_type_from_ttype_t(asr_set->m_type, nullptr, local_m_storage, + is_local_array_type, is_local_malloc_array_type, + is_local_list, local_m_dims, local_n_dims, + local_a_kind, module); + int32_t el_type_size = get_type_size(asr_set->m_type, el_llvm_type, local_a_kind, module); + std::string el_type_code = ASRUtils::get_type_code(asr_set->m_type); + return set_api->get_set_type(el_type_code, el_type_size, + el_llvm_type); + } + + llvm::Type* LLVMUtils::get_arg_type_from_ttype_t(ASR::ttype_t* asr_type, + ASR::symbol_t *type_declaration, ASR::abiType m_abi, ASR::abiType arg_m_abi, + ASR::storage_typeType m_storage, bool arg_m_value_attr, int& n_dims, + int& a_kind, bool& is_array_type, ASR::intentType arg_intent, llvm::Module* module, + bool get_pointer) { + llvm::Type* type = nullptr; + + #define handle_llvm_pointers2() bool is_pointer_ = ASR::is_a(*t2) || \ + (ASR::is_a(*t2) && arg_m_abi != ASR::abiType::BindC); \ + type = get_arg_type_from_ttype_t(t2, nullptr, m_abi, arg_m_abi, \ + m_storage, arg_m_value_attr, n_dims, a_kind, \ + is_array_type, arg_intent, module, get_pointer); \ + if( !is_pointer_ ) { \ + type = type->getPointerTo(); \ + } \ + + switch (asr_type->type) { + case ASR::ttypeType::Array: { + ASR::Array_t* v_type = ASR::down_cast(asr_type); + switch( v_type->m_physical_type ) { + case ASR::array_physical_typeType::DescriptorArray: { + is_array_type = true; + llvm::Type* el_type = get_el_type(v_type->m_type, module); + type = arr_api->get_array_type(asr_type, el_type, get_pointer); + break; + } + case ASR::array_physical_typeType::PointerToDataArray: { + type = nullptr; + if( ASR::is_a(*v_type->m_type) ) { + ASR::Complex_t* complex_t = ASR::down_cast(v_type->m_type); + type = getComplexType(complex_t->m_kind, true); + } + + + if( type == nullptr ) { + type = get_type_from_ttype_t_util(v_type->m_type, module, arg_m_abi)->getPointerTo(); + } + } + if( type != nullptr ) { + } + if( type != nullptr ) { + break; + } + case ASR::array_physical_typeType::FixedSizeArray: { + type = llvm::ArrayType::get(get_el_type(v_type->m_type, module), + ASRUtils::get_fixed_size_of_array( + v_type->m_dims, v_type->n_dims))->getPointerTo(); + break; + } + default: { + LCOMPILERS_ASSERT(false); + } + } + break; + } + case (ASR::ttypeType::Integer) : { + ASR::Integer_t* v_type = ASR::down_cast(asr_type); + a_kind = v_type->m_kind; + if (arg_m_abi == ASR::abiType::BindC + && arg_m_value_attr) { + type = getIntType(a_kind, false); + } else { + type = getIntType(a_kind, true); + } + break; + } + case (ASR::ttypeType::UnsignedInteger) : { + ASR::UnsignedInteger_t* v_type = ASR::down_cast(asr_type); + a_kind = v_type->m_kind; + if (arg_m_abi == ASR::abiType::BindC + && arg_m_value_attr) { + type = getIntType(a_kind, false); + } else { + type = getIntType(a_kind, true); + } + break; + } + case (ASR::ttypeType::Pointer) : { + ASR::ttype_t *t2 = ASRUtils::type_get_past_pointer(asr_type); + handle_llvm_pointers2() + break; + } + case (ASR::ttypeType::Allocatable) : { + ASR::ttype_t *t2 = ASRUtils::type_get_past_allocatable(asr_type); + handle_llvm_pointers2() + break; + } + case (ASR::ttypeType::Const) : { + ASR::ttype_t *t2 = ASRUtils::get_contained_type(asr_type); + type = get_arg_type_from_ttype_t(t2, nullptr, m_abi, arg_m_abi, + m_storage, arg_m_value_attr, n_dims, a_kind, + is_array_type, arg_intent, module, get_pointer); + break; + } + case (ASR::ttypeType::Real) : { + ASR::Real_t* v_type = ASR::down_cast(asr_type); + a_kind = v_type->m_kind; + if (arg_m_abi == ASR::abiType::BindC + && arg_m_value_attr) { + type = getFPType(a_kind, false); + } else { + type = getFPType(a_kind, true); + } + break; + } + case (ASR::ttypeType::Complex) : { + ASR::Complex_t* v_type = ASR::down_cast(asr_type); + a_kind = v_type->m_kind; + if (m_abi != ASR::abiType::BindC) { + type = getComplexType(a_kind, true); + } else { + if (arg_m_abi == ASR::abiType::BindC + && arg_m_value_attr) { + if (a_kind == 4) { + if (compiler_options.platform == Platform::Windows) { + // type_fx2 is i64 + llvm::Type* type_fx2 = llvm::Type::getInt64Ty(context); + type = type_fx2; + } else if (compiler_options.platform == Platform::macOS_ARM) { + // type_fx2 is [2 x float] + llvm::Type* type_fx2 = llvm::ArrayType::get(llvm::Type::getFloatTy(context), 2); + type = type_fx2; + } else { + // type_fx2 is <2 x float> + llvm::Type* type_fx2 = FIXED_VECTOR_TYPE::get(llvm::Type::getFloatTy(context), 2); + type = type_fx2; + } + } else { + LCOMPILERS_ASSERT(a_kind == 8) + if (compiler_options.platform == Platform::Windows) { + // 128 bit aggregate type is passed by reference + type = getComplexType(a_kind, true); + } else { + // Pass by value + type = getComplexType(a_kind, false); + } + } + } else { + type = getComplexType(a_kind, true); + } + } + break; + } + case (ASR::ttypeType::Character) : { + ASR::Character_t* v_type = ASR::down_cast(asr_type); + a_kind = v_type->m_kind; + if (arg_m_abi == ASR::abiType::BindC) { + type = character_type; + } else { + type = character_type->getPointerTo(); + } + break; + } + case (ASR::ttypeType::Logical) : { + ASR::Logical_t* v_type = ASR::down_cast(asr_type); + a_kind = v_type->m_kind; + if (arg_m_abi == ASR::abiType::BindC + && arg_m_value_attr) { + type = llvm::Type::getInt1Ty(context); + } else { + type = llvm::Type::getInt1PtrTy(context); + } + break; + } + case (ASR::ttypeType::Struct) : { + type = getStructType(asr_type, module, true); + break; + } + case (ASR::ttypeType::Class) : { + type = getClassType(asr_type, true)->getPointerTo(); + break; + } + case (ASR::ttypeType::CPtr) : { + type = llvm::Type::getVoidTy(context)->getPointerTo(); + break; + } + case (ASR::ttypeType::Tuple) : { + type = get_type_from_ttype_t_util(asr_type, module)->getPointerTo(); + break; + } + case (ASR::ttypeType::List) : { + bool is_array_type = false, is_malloc_array_type = false; + bool is_list = true; + ASR::dimension_t *m_dims = nullptr; + ASR::List_t* asr_list = ASR::down_cast(asr_type); + llvm::Type* el_llvm_type = get_type_from_ttype_t(asr_list->m_type, nullptr, m_storage, + is_array_type, + is_malloc_array_type, + is_list, m_dims, n_dims, + a_kind, module, m_abi); + int32_t type_size = -1; + if( LLVM::is_llvm_struct(asr_list->m_type) || + ASR::is_a(*asr_list->m_type) || + ASR::is_a(*asr_list->m_type) ) { + llvm::DataLayout data_layout(module); + type_size = data_layout.getTypeAllocSize(el_llvm_type); + } else { + type_size = a_kind; + } + std::string el_type_code = ASRUtils::get_type_code(asr_list->m_type); + type = list_api->get_list_type(el_llvm_type, el_type_code, type_size)->getPointerTo(); + break; + } + case ASR::ttypeType::Enum: { + if (arg_m_abi == ASR::abiType::BindC + && arg_m_value_attr) { + type = llvm::Type::getInt32Ty(context); + } else { + type = llvm::Type::getInt32PtrTy(context); + } + break ; + } + case (ASR::ttypeType::Dict): { + type = get_dict_type(asr_type, module); + break; + } + case (ASR::ttypeType::Set): { + type = get_set_type(asr_type, module); + break; + } + case ASR::ttypeType::FunctionType: { + ASR::Function_t* fn = ASR::down_cast( + ASRUtils::symbol_get_past_external(type_declaration)); + type = get_function_type(*fn, module)->getPointerTo(); + break ; + } + default : + LCOMPILERS_ASSERT(false); + } + return type; + } + + void LLVMUtils::set_dict_api(ASR::Dict_t* dict_type) { + if( ASR::is_a(*dict_type->m_key_type) ) { + dict_api = dict_api_sc; + } else { + dict_api = dict_api_lp; + } + } + + std::vector LLVMUtils::convert_args(const ASR::Function_t& x, llvm::Module* module) { + std::vector args; + for (size_t i=0; i(*ASRUtils::symbol_get_past_external( + ASR::down_cast(x.m_args[i])->m_v))) { + ASR::Variable_t *arg = ASRUtils::EXPR2VAR(x.m_args[i]); + LCOMPILERS_ASSERT(ASRUtils::is_arg_dummy(arg->m_intent)); + // We pass all arguments as pointers for now, + // except bind(C) value arguments that are passed by value + llvm::Type *type = nullptr, *type_original = nullptr; + int n_dims = 0, a_kind = 4; + bool is_array_type = false; + type_original = get_arg_type_from_ttype_t(arg->m_type, + arg->m_type_declaration, + ASRUtils::get_FunctionType(x)->m_abi, + arg->m_abi, arg->m_storage, arg->m_value_attr, + n_dims, a_kind, is_array_type, arg->m_intent, + module, false); + if( is_array_type ) { + type = type_original->getPointerTo(); + } else { + type = type_original; + } + if( arg->m_intent == ASRUtils::intent_out && + ASR::is_a(*arg->m_type) ) { + type = type->getPointerTo(); + } + std::uint32_t m_h; + std::string m_name = std::string(x.m_name); + if( x.class_type == ASR::symbolType::Function ) { + ASR::Function_t* _func = (ASR::Function_t*)(&(x.base)); + m_h = get_hash((ASR::asr_t*)_func); + } + if( is_array_type && arg->m_type->type != ASR::ttypeType::Pointer ) { + if( ASRUtils::get_FunctionType(x)->m_abi == ASR::abiType::Source ) { + llvm::Type* orig_type = type_original; + type = arr_api->get_argument_type(orig_type, m_h, arg->m_name, arr_arg_type_cache); + is_array_type = false; + } else if( ASRUtils::get_FunctionType(x)->m_abi == ASR::abiType::Intrinsic && + fname2arg_type.find(m_name) != fname2arg_type.end()) { + type = fname2arg_type[m_name].second; + is_array_type = false; + } + } + args.push_back(type); + } else if (ASR::is_a(*ASRUtils::symbol_get_past_external( + ASR::down_cast(x.m_args[i])->m_v))) { + /* This is likely a procedure passed as an argument. For the + type, we need to pass in a function pointer with the + correct call signature. */ + ASR::Function_t* fn = ASR::down_cast( + ASRUtils::symbol_get_past_external(ASR::down_cast( + x.m_args[i])->m_v)); + llvm::Type* type = get_function_type(*fn, module)->getPointerTo(); + args.push_back(type); + } else { + throw CodeGenError("Argument type not implemented"); + } + } + return args; + } + + llvm::FunctionType* LLVMUtils::get_function_type(const ASR::Function_t &x, llvm::Module* module) { + llvm::Type *return_type; + if (x.m_return_var) { + ASR::ttype_t *return_var_type0 = ASRUtils::EXPR2VAR(x.m_return_var)->m_type; + ASR::ttypeType return_var_type = return_var_type0->type; + switch (return_var_type) { + case (ASR::ttypeType::Integer) : { + int a_kind = ASR::down_cast(return_var_type0)->m_kind; + return_type = getIntType(a_kind); + break; + } + case (ASR::ttypeType::UnsignedInteger) : { + int a_kind = ASR::down_cast(return_var_type0)->m_kind; + return_type = getIntType(a_kind); + break; + } + case (ASR::ttypeType::Real) : { + int a_kind = ASR::down_cast(return_var_type0)->m_kind; + return_type = getFPType(a_kind); + break; + } + case (ASR::ttypeType::Complex) : { + int a_kind = ASR::down_cast(return_var_type0)->m_kind; + if (a_kind == 4) { + if (ASRUtils::get_FunctionType(x)->m_abi == ASR::abiType::BindC) { + if (compiler_options.platform == Platform::Windows) { + // i64 + return_type = llvm::Type::getInt64Ty(context); + } else if (compiler_options.platform == Platform::macOS_ARM) { + // {float, float} + return_type = getComplexType(a_kind); + } else { + // <2 x float> + return_type = FIXED_VECTOR_TYPE::get(llvm::Type::getFloatTy(context), 2); + } + } else { + return_type = getComplexType(a_kind); + } + } else { + LCOMPILERS_ASSERT(a_kind == 8) + if (ASRUtils::get_FunctionType(x)->m_abi == ASR::abiType::BindC) { + if (compiler_options.platform == Platform::Windows) { + // pass as subroutine + return_type = getComplexType(a_kind, true); + std::vector args = convert_args(x, module); + args.insert(args.begin(), return_type); + llvm::FunctionType *function_type = llvm::FunctionType::get( + llvm::Type::getVoidTy(context), args, false); + return function_type; + } else { + return_type = getComplexType(a_kind); + } + } else { + return_type = getComplexType(a_kind); + } + } + break; + } + case (ASR::ttypeType::Character) : + return_type = character_type; + break; + case (ASR::ttypeType::Logical) : + return_type = llvm::Type::getInt1Ty(context); + break; + case (ASR::ttypeType::CPtr) : + return_type = llvm::Type::getVoidTy(context)->getPointerTo(); + break; + case (ASR::ttypeType::Const) : { + return_type = get_type_from_ttype_t_util(ASRUtils::get_contained_type(return_var_type0), module); + break; + } + case (ASR::ttypeType::Pointer) : { + return_type = get_type_from_ttype_t_util(ASRUtils::get_contained_type(return_var_type0), module)->getPointerTo(); + break; + } + case (ASR::ttypeType::Allocatable) : { + // TODO: Do getPointerTo as well. + return_type = get_type_from_ttype_t_util(ASRUtils::get_contained_type(return_var_type0), module); + break; + } + case (ASR::ttypeType::Struct) : + throw CodeGenError("Struct return type not implemented yet"); + break; + case (ASR::ttypeType::Tuple) : { + ASR::Tuple_t* asr_tuple = ASR::down_cast(return_var_type0); + std::string type_code = ASRUtils::get_type_code(asr_tuple->m_type, + asr_tuple->n_type); + std::vector llvm_el_types; + for( size_t i = 0; i < asr_tuple->n_type; i++ ) { + bool is_local_array_type = false, is_local_malloc_array_type = false; + bool is_local_list = false; + ASR::dimension_t* local_m_dims = nullptr; + int local_n_dims = 0; + int local_a_kind = -1; + ASR::storage_typeType local_m_storage = ASR::storage_typeType::Default; + llvm_el_types.push_back(get_type_from_ttype_t( + asr_tuple->m_type[i], nullptr, local_m_storage, + is_local_array_type, is_local_malloc_array_type, + is_local_list, local_m_dims, local_n_dims, local_a_kind, module)); + } + return_type = tuple_api->get_tuple_type(type_code, llvm_el_types); + break; + } + case (ASR::ttypeType::List) : { + bool is_array_type = false, is_malloc_array_type = false; + bool is_list = true; + ASR::dimension_t *m_dims = nullptr; + ASR::storage_typeType m_storage = ASR::storage_typeType::Default; + int n_dims = 0, a_kind = -1; + ASR::List_t* asr_list = ASR::down_cast(return_var_type0); + llvm::Type* el_llvm_type = get_type_from_ttype_t(asr_list->m_type, nullptr, m_storage, + is_array_type, is_malloc_array_type, is_list, m_dims, n_dims, a_kind, module); + int32_t type_size = -1; + if( LLVM::is_llvm_struct(asr_list->m_type) || + ASR::is_a(*asr_list->m_type) || + ASR::is_a(*asr_list->m_type) ) { + llvm::DataLayout data_layout(module); + type_size = data_layout.getTypeAllocSize(el_llvm_type); + } else { + type_size = a_kind; + } + std::string el_type_code = ASRUtils::get_type_code(asr_list->m_type); + return_type = list_api->get_list_type(el_llvm_type, el_type_code, type_size); + break; + } + case (ASR::ttypeType::Dict) : { + ASR::Dict_t* asr_dict = ASR::down_cast(return_var_type0); + std::string key_type_code = ASRUtils::get_type_code(asr_dict->m_key_type); + std::string value_type_code = ASRUtils::get_type_code(asr_dict->m_value_type); + + bool is_local_array_type = false, is_local_malloc_array_type = false; + bool is_local_list = false; + ASR::dimension_t* local_m_dims = nullptr; + ASR::storage_typeType local_m_storage = ASR::storage_typeType::Default; + int local_n_dims = 0, local_a_kind = -1; + + llvm::Type* key_llvm_type = get_type_from_ttype_t(asr_dict->m_key_type, + nullptr, local_m_storage, is_local_array_type, is_local_malloc_array_type, + is_local_list, local_m_dims, local_n_dims, local_a_kind, module); + llvm::Type* value_llvm_type = get_type_from_ttype_t(asr_dict->m_value_type, + nullptr, local_m_storage,is_local_array_type, is_local_malloc_array_type, + is_local_list, local_m_dims, local_n_dims, local_a_kind, module); + int32_t key_type_size = get_type_size(asr_dict->m_key_type, key_llvm_type, local_a_kind, module); + int32_t value_type_size = get_type_size(asr_dict->m_value_type, value_llvm_type, local_a_kind, module); + + set_dict_api(asr_dict); + + return_type = dict_api->get_dict_type(key_type_code, value_type_code, key_type_size,value_type_size, key_llvm_type, value_llvm_type); + break; + } + case (ASR::ttypeType::Set) : { + ASR::Set_t* asr_set = ASR::down_cast(return_var_type0); + std::string el_type_code = ASRUtils::get_type_code(asr_set->m_type); + + bool is_local_array_type = false, is_local_malloc_array_type = false; + bool is_local_list = false; + ASR::dimension_t* local_m_dims = nullptr; + ASR::storage_typeType local_m_storage = ASR::storage_typeType::Default; + int local_n_dims = 0, local_a_kind = -1; + + llvm::Type* el_llvm_type = get_type_from_ttype_t(asr_set->m_type, + nullptr, local_m_storage, is_local_array_type, is_local_malloc_array_type, + is_local_list, local_m_dims, local_n_dims, local_a_kind, module); + int32_t el_type_size = get_type_size(asr_set->m_type, el_llvm_type, local_a_kind, module); + + return_type = set_api->get_set_type(el_type_code, el_type_size, el_llvm_type); + break; + } + default : + throw CodeGenError("Type not implemented " + std::to_string(return_var_type)); + } + } else { + return_type = llvm::Type::getVoidTy(context); + } + std::vector args = convert_args(x, module); + llvm::FunctionType *function_type = llvm::FunctionType::get( + return_type, args, false); + return function_type; + } + + llvm::Type* LLVMUtils::get_type_from_ttype_t(ASR::ttype_t* asr_type, + ASR::symbol_t *type_declaration, ASR::storage_typeType m_storage, + bool& is_array_type, bool& is_malloc_array_type, bool& is_list, + ASR::dimension_t*& m_dims, int& n_dims, int& a_kind, llvm::Module* module, + ASR::abiType m_abi, bool is_pointer) { + llvm::Type* llvm_type = nullptr; + + #define handle_llvm_pointers1() if (n_dims == 0 && ASR::is_a(*t2)) { \ + llvm_type = character_type; \ + } else { \ + bool is_pointer_ = (ASR::is_a(*t2) || \ + (ASR::is_a(*t2) && m_abi != ASR::abiType::BindC) ); \ + llvm_type = get_type_from_ttype_t(t2, nullptr, m_storage, is_array_type, \ + is_malloc_array_type, is_list, m_dims, \ + n_dims, a_kind, module, m_abi, is_pointer_); \ + if( !is_pointer_ ) { \ + llvm_type = llvm_type->getPointerTo(); \ + } \ + } \ + + switch (asr_type->type) { + case ASR::ttypeType::Array: { + ASR::Array_t* v_type = ASR::down_cast(asr_type); + m_dims = v_type->m_dims; + n_dims = v_type->n_dims; + a_kind = ASRUtils::extract_kind_from_ttype_t(v_type->m_type); + switch( v_type->m_physical_type ) { + case ASR::array_physical_typeType::DescriptorArray: { + is_array_type = true; + llvm::Type* el_type = get_el_type(v_type->m_type, module); + llvm_type = arr_api->get_array_type(asr_type, el_type); + break; + } + case ASR::array_physical_typeType::PointerToDataArray: { + llvm_type = get_el_type(v_type->m_type, module)->getPointerTo(); + break; + } + case ASR::array_physical_typeType::FixedSizeArray: { + llvm_type = llvm::ArrayType::get(get_el_type(v_type->m_type, module), + ASRUtils::get_fixed_size_of_array( + v_type->m_dims, v_type->n_dims)); + break; + } + default: { + LCOMPILERS_ASSERT(false); + } + } + break ; + } + case (ASR::ttypeType::Integer) : { + ASR::Integer_t* v_type = ASR::down_cast(asr_type); + a_kind = v_type->m_kind; + llvm_type = getIntType(a_kind); + break; + } + case (ASR::ttypeType::UnsignedInteger) : { + ASR::UnsignedInteger_t* v_type = ASR::down_cast(asr_type); + a_kind = v_type->m_kind; + // LLVM does not distinguish signed and unsigned integer types + // Only integer operations can be signed/unsigned + llvm_type = getIntType(a_kind); + break; + } + case (ASR::ttypeType::Real) : { + ASR::Real_t* v_type = ASR::down_cast(asr_type); + a_kind = v_type->m_kind; + llvm_type = getFPType(a_kind); + break; + } + case (ASR::ttypeType::Complex) : { + ASR::Complex_t* v_type = ASR::down_cast(asr_type); + a_kind = v_type->m_kind; + llvm_type = getComplexType(a_kind); + break; + } + case (ASR::ttypeType::Character) : { + ASR::Character_t* v_type = ASR::down_cast(asr_type); + a_kind = v_type->m_kind; + llvm_type = character_type; + break; + } + case (ASR::ttypeType::Logical) : { + ASR::Logical_t* v_type = ASR::down_cast(asr_type); + a_kind = v_type->m_kind; + llvm_type = llvm::Type::getInt1Ty(context); + break; + } + case (ASR::ttypeType::Struct) : { + llvm_type = getStructType(asr_type, module, false); + break; + } + case (ASR::ttypeType::Class) : { + llvm_type = getClassType(asr_type, is_pointer); + break; + } + case (ASR::ttypeType::Union) : { + llvm_type = getUnionType(asr_type, module, false); + break; + } + case (ASR::ttypeType::Pointer) : { + ASR::ttype_t *t2 = ASR::down_cast(asr_type)->m_type; + handle_llvm_pointers1() + break; + } + case (ASR::ttypeType::Allocatable) : { + ASR::ttype_t *t2 = ASR::down_cast(asr_type)->m_type; + is_malloc_array_type = ASRUtils::is_array(t2); + handle_llvm_pointers1() + break; + } + case (ASR::ttypeType::List) : { + is_list = true; + ASR::List_t* asr_list = ASR::down_cast(asr_type); + llvm::Type* el_llvm_type = get_type_from_ttype_t(asr_list->m_type, nullptr, m_storage, + is_array_type, is_malloc_array_type, + is_list, m_dims, n_dims, + a_kind, module, m_abi); + std::string el_type_code = ASRUtils::get_type_code(asr_list->m_type); + int32_t type_size = -1; + if( LLVM::is_llvm_struct(asr_list->m_type) || + ASR::is_a(*asr_list->m_type) || + ASR::is_a(*asr_list->m_type) ) { + llvm::DataLayout data_layout(module); + type_size = data_layout.getTypeAllocSize(el_llvm_type); + } else { + type_size = a_kind; + } + llvm_type = list_api->get_list_type(el_llvm_type, el_type_code, type_size); + break; + } + case (ASR::ttypeType::Dict): { + llvm_type = get_dict_type(asr_type, module); + break; + } + case (ASR::ttypeType::Set): { + llvm_type = get_set_type(asr_type, module); + break; + } + case (ASR::ttypeType::Tuple) : { + ASR::Tuple_t* asr_tuple = ASR::down_cast(asr_type); + std::string type_code = ASRUtils::get_type_code(asr_tuple->m_type, + asr_tuple->n_type); + std::vector llvm_el_types; + for( size_t i = 0; i < asr_tuple->n_type; i++ ) { + bool is_local_array_type = false, is_local_malloc_array_type = false; + bool is_local_list = false; + ASR::dimension_t* local_m_dims = nullptr; + int local_n_dims = 0; + int local_a_kind = -1; + ASR::storage_typeType local_m_storage = ASR::storage_typeType::Default; + llvm_el_types.push_back(get_type_from_ttype_t(asr_tuple->m_type[i], nullptr, local_m_storage, + is_local_array_type, is_local_malloc_array_type, + is_local_list, local_m_dims, local_n_dims, local_a_kind, module, m_abi)); + } + llvm_type = tuple_api->get_tuple_type(type_code, llvm_el_types); + break; + } + case (ASR::ttypeType::CPtr) : { + llvm_type = llvm::Type::getVoidTy(context)->getPointerTo(); + break; + } + case (ASR::ttypeType::Enum) : { + llvm_type = llvm::Type::getInt32Ty(context); + break ; + } + case (ASR::ttypeType::Const) : { + llvm_type = get_type_from_ttype_t(ASRUtils::get_contained_type(asr_type), + nullptr, m_storage, is_array_type, is_malloc_array_type, is_list, + m_dims, n_dims, a_kind, module, m_abi); + break; + } + case (ASR::ttypeType::FunctionType) : { + ASR::Function_t* fn = ASR::down_cast( + ASRUtils::symbol_get_past_external(type_declaration)); + llvm_type = get_function_type(*fn, module)->getPointerTo(); + break; + } + default : + throw CodeGenError("Support for type " + ASRUtils::type_to_str(asr_type) + + " not yet implemented."); + } + return llvm_type; + } + + llvm::Type* LLVMUtils::get_type_from_ttype_t_util(ASR::ttype_t* asr_type, + llvm::Module* module, ASR::abiType asr_abi) { + ASR::storage_typeType m_storage_local = ASR::storage_typeType::Default; + bool is_array_type_local, is_malloc_array_type_local; + bool is_list_local; + ASR::dimension_t* m_dims_local; + int n_dims_local, a_kind_local; + return get_type_from_ttype_t(asr_type, nullptr, m_storage_local, is_array_type_local, + is_malloc_array_type_local, is_list_local, + m_dims_local, n_dims_local, a_kind_local, module, asr_abi); + } + llvm::Value* LLVMUtils::create_gep(llvm::Value* ds, int idx) { std::vector idx_vec = { llvm::ConstantInt::get(context, llvm::APInt(32, 0)), @@ -310,6 +1474,153 @@ namespace LCompilers { } } + llvm::Value* LLVMUtils::is_ineq_by_value(llvm::Value* left, llvm::Value* right, + llvm::Module& module, ASR::ttype_t* asr_type, + int8_t overload_id, ASR::ttype_t* int32_type) { + /** + * overloads: + * 0 < + * 1 <= + * 2 > + * 3 >= + */ + llvm::CmpInst::Predicate pred; + + switch( asr_type->type ) { + case ASR::ttypeType::Integer: + case ASR::ttypeType::Logical: { + switch( overload_id ) { + case 0: { + pred = llvm::CmpInst::Predicate::ICMP_SLT; + break; + } + case 1: { + pred = llvm::CmpInst::Predicate::ICMP_SLE; + break; + } + case 2: { + pred = llvm::CmpInst::Predicate::ICMP_SGT; + break; + } + case 3: { + pred = llvm::CmpInst::Predicate::ICMP_SGE; + break; + } + default: { + // can exit with error + } + } + return builder->CreateCmp(pred, left, right); + } + case ASR::ttypeType::Real: { + switch( overload_id ) { + case 0: { + pred = llvm::CmpInst::Predicate::FCMP_OLT; + break; + } + case 1: { + pred = llvm::CmpInst::Predicate::FCMP_OLE; + break; + } + case 2: { + pred = llvm::CmpInst::Predicate::FCMP_OGT; + break; + } + case 3: { + pred = llvm::CmpInst::Predicate::FCMP_OGE; + break; + } + default: { + // can exit with error + } + } + return builder->CreateCmp(pred, left, right); + } + case ASR::ttypeType::Character: { + if( !are_iterators_set ) { + str_cmp_itr = builder->CreateAlloca(llvm::Type::getInt32Ty(context), nullptr); + } + llvm::Value* null_char = llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), + llvm::APInt(8, '\0')); + llvm::Value* idx = str_cmp_itr; + LLVM::CreateStore(*builder, + llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), llvm::APInt(32, 0)), + idx); + llvm::BasicBlock *loophead = llvm::BasicBlock::Create(context, "loop.head"); + llvm::BasicBlock *loopbody = llvm::BasicBlock::Create(context, "loop.body"); + llvm::BasicBlock *loopend = llvm::BasicBlock::Create(context, "loop.end"); + + // head + start_new_block(loophead); + { + llvm::Value* i = LLVM::CreateLoad(*builder, idx); + llvm::Value* l = LLVM::CreateLoad(*builder, create_ptr_gep(left, i)); + llvm::Value* r = LLVM::CreateLoad(*builder, create_ptr_gep(right, i)); + llvm::Value *cond = builder->CreateAnd( + builder->CreateICmpNE(l, null_char), + builder->CreateICmpNE(r, null_char) + ); + switch( overload_id ) { + case 0: { + pred = llvm::CmpInst::Predicate::ICMP_ULT; + break; + } + case 1: { + pred = llvm::CmpInst::Predicate::ICMP_ULE; + break; + } + case 2: { + pred = llvm::CmpInst::Predicate::ICMP_UGT; + break; + } + case 3: { + pred = llvm::CmpInst::Predicate::ICMP_UGE; + break; + } + default: { + // can exit with error + } + } + cond = builder->CreateAnd(cond, builder->CreateCmp(pred, l, r)); + builder->CreateCondBr(cond, loopbody, loopend); + } + + // body + start_new_block(loopbody); + { + llvm::Value* i = LLVM::CreateLoad(*builder, idx); + i = builder->CreateAdd(i, llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), + llvm::APInt(32, 1))); + LLVM::CreateStore(*builder, i, idx); + } + + builder->CreateBr(loophead); + + // end + start_new_block(loopend); + llvm::Value* i = LLVM::CreateLoad(*builder, idx); + llvm::Value* l = LLVM::CreateLoad(*builder, create_ptr_gep(left, i)); + llvm::Value* r = LLVM::CreateLoad(*builder, create_ptr_gep(right, i)); + return builder->CreateICmpULT(l, r); + } + case ASR::ttypeType::Tuple: { + ASR::Tuple_t* tuple_type = ASR::down_cast(asr_type); + return tuple_api->check_tuple_inequality(left, right, tuple_type, context, + builder, module, overload_id); + } + case ASR::ttypeType::List: { + ASR::List_t* list_type = ASR::down_cast(asr_type); + return list_api->check_list_inequality(left, right, list_type->m_type, + context, builder, module, + overload_id, int32_type); + } + default: { + throw LCompilersException("LLVMUtils::is_equal_by_value isn't implemented for " + + ASRUtils::type_to_str_python(asr_type)); + } + } + } + void LLVMUtils::deepcopy(llvm::Value* src, llvm::Value* dest, ASR::ttype_t* asr_type, llvm::Module* module, std::map>& name2memidx) { @@ -320,7 +1631,32 @@ namespace LCompilers { case ASR::ttypeType::Logical: case ASR::ttypeType::Complex: { if( ASRUtils::is_array(asr_type) ) { - arr_api->copy_array(src, dest, module, asr_type, false, false); + ASR::array_physical_typeType physical_type = ASRUtils::extract_physical_type(asr_type); + switch( physical_type ) { + case ASR::array_physical_typeType::DescriptorArray: { + arr_api->copy_array(src, dest, module, asr_type, false, false); + break; + } + case ASR::array_physical_typeType::FixedSizeArray: { + src = create_gep(src, 0); + dest = create_gep(dest, 0); + ASR::dimension_t* asr_dims = nullptr; + size_t asr_n_dims = ASRUtils::extract_dimensions_from_ttype(asr_type, asr_dims); + int64_t size = ASRUtils::get_fixed_size_of_array(asr_dims, asr_n_dims); + llvm::Type* llvm_data_type = get_type_from_ttype_t_util(ASRUtils::type_get_past_array( + ASRUtils::type_get_past_allocatable(ASRUtils::type_get_past_pointer(asr_type))), module); + llvm::DataLayout data_layout(module); + uint64_t data_size = data_layout.getTypeAllocSize(llvm_data_type); + llvm::Value* llvm_size = llvm::ConstantInt::get(context, llvm::APInt(32, size)); + llvm_size = builder->CreateMul(llvm_size, + llvm::ConstantInt::get(context, llvm::APInt(32, data_size))); + builder->CreateMemCpy(dest, llvm::MaybeAlign(), src, llvm::MaybeAlign(), llvm_size); + break; + } + default: { + LCOMPILERS_ASSERT(false); + } + } } else { LLVM::CreateStore(*builder, src, dest); } @@ -3109,6 +4445,101 @@ namespace LCompilers { return LLVM::CreateLoad(*builder, is_equal); } + llvm::Value* LLVMList::check_list_inequality(llvm::Value* l1, llvm::Value* l2, + ASR::ttype_t* item_type, + llvm::LLVMContext& context, + llvm::IRBuilder<>* builder, + llvm::Module& module, int8_t overload_id, + ASR::ttype_t* int32_type) { + /** + * Equivalent in C++ + * + * equality_holds = 1; + * inequality_holds = 0; + * i = 0; + * + * while( i < a_len && i < b_len && equality_holds ) { + * equality_holds &= (a[i] == b[i]); + * inequality_holds |= (a[i] op b[i]); + * i++; + * } + * + * if( (i == a_len || i == b_len) && equality_holds ) { + * inequality_holds = a_len op b_len; + * } + * + */ + + llvm::AllocaInst *equality_holds = builder->CreateAlloca( + llvm::Type::getInt1Ty(context), nullptr); + LLVM::CreateStore(*builder, llvm::ConstantInt::get(context, llvm::APInt(1, 1)), + equality_holds); + llvm::AllocaInst *inequality_holds = builder->CreateAlloca( + llvm::Type::getInt1Ty(context), nullptr); + LLVM::CreateStore(*builder, llvm::ConstantInt::get(context, llvm::APInt(1, 0)), + inequality_holds); + + llvm::Value *a_len = llvm_utils->list_api->len(l1); + llvm::Value *b_len = llvm_utils->list_api->len(l2); + llvm::AllocaInst *idx = builder->CreateAlloca(llvm::Type::getInt32Ty(context), nullptr); + LLVM::CreateStore(*builder, llvm::ConstantInt::get( + context, llvm::APInt(32, 0)), idx); + llvm::BasicBlock *loophead = llvm::BasicBlock::Create(context, "loop.head"); + llvm::BasicBlock *loopbody = llvm::BasicBlock::Create(context, "loop.body"); + llvm::BasicBlock *loopend = llvm::BasicBlock::Create(context, "loop.end"); + + // head + llvm_utils->start_new_block(loophead); + { + llvm::Value* i = LLVM::CreateLoad(*builder, idx); + llvm::Value* cnd = builder->CreateICmpSLT(i, a_len); + cnd = builder->CreateAnd(cnd, builder->CreateICmpSLT(i, b_len)); + cnd = builder->CreateAnd(cnd, LLVM::CreateLoad(*builder, equality_holds)); + builder->CreateCondBr(cnd, loopbody, loopend); + } + + // body + llvm_utils->start_new_block(loopbody); + { + llvm::Value* i = LLVM::CreateLoad(*builder, idx); + llvm::Value* left_arg = llvm_utils->list_api->read_item(l1, i, + false, module, LLVM::is_llvm_struct(item_type)); + llvm::Value* right_arg = llvm_utils->list_api->read_item(l2, i, + false, module, LLVM::is_llvm_struct(item_type)); + llvm::Value* res = llvm_utils->is_ineq_by_value(left_arg, right_arg, module, + item_type, overload_id); + res = builder->CreateOr(LLVM::CreateLoad(*builder, inequality_holds), res); + LLVM::CreateStore(*builder, res, inequality_holds); + res = llvm_utils->is_equal_by_value(left_arg, right_arg, module, + item_type); + res = builder->CreateAnd(LLVM::CreateLoad(*builder, equality_holds), res); + LLVM::CreateStore(*builder, res, equality_holds); + i = builder->CreateAdd(i, llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), + llvm::APInt(32, 1))); + LLVM::CreateStore(*builder, i, idx); + } + + builder->CreateBr(loophead); + + // end + llvm_utils->start_new_block(loopend); + + llvm::Value* cond = builder->CreateICmpEQ(LLVM::CreateLoad(*builder, idx), + a_len); + cond = builder->CreateOr(cond, builder->CreateICmpEQ( + LLVM::CreateLoad(*builder, idx), b_len)); + cond = builder->CreateAnd(cond, LLVM::CreateLoad(*builder, equality_holds)); + llvm_utils->create_if_else(cond, [&]() { + LLVM::CreateStore(*builder, llvm_utils->is_ineq_by_value(a_len, b_len, + module, int32_type, overload_id), inequality_holds); + }, []() { + // LLVM::CreateStore(*builder, llvm::ConstantInt::get( + // context, llvm::APInt(1, 0)), inequality_holds); + }); + + return LLVM::CreateLoad(*builder, inequality_holds); + } + void LLVMList::list_repeat_copy(llvm::Value* repeat_list, llvm::Value* init_list, llvm::Value* num_times, llvm::Value* init_list_len, llvm::Module* module) { @@ -3254,6 +4685,58 @@ namespace LCompilers { return is_equal; } + llvm::Value* LLVMTuple::check_tuple_inequality(llvm::Value* t1, llvm::Value* t2, + ASR::Tuple_t* tuple_type, + llvm::LLVMContext& context, + llvm::IRBuilder<>* builder, + llvm::Module& module, int8_t overload_id) { + /** + * Equivalent in C++ + * + * equality_holds = 1; + * inequality_holds = 0; + * i = 0; + * + * // owing to compile-time access of indices, + * // loop is unrolled into multiple if statements + * while( i < a_len && equality_holds ) { + * inequality_holds |= (a[i] op b[i]); + * equality_holds &= (a[i] == b[i]); + * i++; + * } + * + * return inequality_holds; + * + */ + + llvm::AllocaInst *equality_holds = builder->CreateAlloca( + llvm::Type::getInt1Ty(context), nullptr); + LLVM::CreateStore(*builder, llvm::ConstantInt::get(context, llvm::APInt(1, 1)), + equality_holds); + llvm::AllocaInst *inequality_holds = builder->CreateAlloca( + llvm::Type::getInt1Ty(context), nullptr); + LLVM::CreateStore(*builder, llvm::ConstantInt::get(context, llvm::APInt(1, 0)), + inequality_holds); + + for( size_t i = 0; i < tuple_type->n_type; i++ ) { + llvm_utils->create_if_else(LLVM::CreateLoad(*builder, equality_holds), [&]() { + llvm::Value* t1i = llvm_utils->tuple_api->read_item(t1, i, LLVM::is_llvm_struct( + tuple_type->m_type[i])); + llvm::Value* t2i = llvm_utils->tuple_api->read_item(t2, i, LLVM::is_llvm_struct( + tuple_type->m_type[i])); + llvm::Value* res = llvm_utils->is_ineq_by_value(t1i, t2i, module, + tuple_type->m_type[i], overload_id); + res = builder->CreateOr(LLVM::CreateLoad(*builder, inequality_holds), res); + LLVM::CreateStore(*builder, res, inequality_holds); + res = llvm_utils->is_equal_by_value(t1i, t2i, module, tuple_type->m_type[i]); + res = builder->CreateAnd(LLVM::CreateLoad(*builder, equality_holds), res); + LLVM::CreateStore(*builder, res, equality_holds); + }, [](){}); + } + + return LLVM::CreateLoad(*builder, inequality_holds); + } + void LLVMTuple::concat(llvm::Value* t1, llvm::Value* t2, ASR::Tuple_t* tuple_type_1, ASR::Tuple_t* tuple_type_2, llvm::Value* concat_tuple, ASR::Tuple_t* concat_tuple_type, llvm::Module& module, diff --git a/src/libasr/codegen/llvm_utils.h b/src/libasr/codegen/llvm_utils.h index b48c8e08bce..72a42e1ba77 100644 --- a/src/libasr/codegen/llvm_utils.h +++ b/src/libasr/codegen/llvm_utils.h @@ -8,10 +8,58 @@ #include #include +#include #include +#if LLVM_VERSION_MAJOR >= 11 +# define FIXED_VECTOR_TYPE llvm::FixedVectorType +#else +# define FIXED_VECTOR_TYPE llvm::VectorType +#endif + namespace LCompilers { + // Platform dependent fast unique hash: + static inline uint64_t get_hash(ASR::asr_t *node) + { + return (uint64_t)node; + } + + namespace { + + // This exception is used to abort the visitor pattern when an error occurs. + // This is only used locally in this file, not propagated outside. An error + // must be already present in ASRToLLVMVisitor::diag before throwing this + // exception. This is checked with an assert when the CodeGenAbort is + // caught. + class CodeGenAbort + { + }; + + // Local exception that is only used in this file to exit the visitor + // pattern and caught later (not propagated outside). It accepts an error + // message that is then appended at the end of ASRToLLVMVisitor::diag. The + // `diag` can already contain other errors or warnings. This is a + // convenience class. One can also report the error into `diag` directly and + // call `CodeGenAbort` instead. + class CodeGenError + { + public: + diag::Diagnostic d; + public: + CodeGenError(const std::string &msg) + : d{diag::Diagnostic(msg, diag::Level::Error, diag::Stage::CodeGen)} + { } + + CodeGenError(const std::string &msg, const Location &loc) + : d{diag::Diagnostic(msg, diag::Level::Error, diag::Stage::CodeGen, { + diag::Label("", {loc}) + })} + { } + }; + + } + namespace LLVMArrUtils { class Descriptor; } @@ -98,6 +146,10 @@ namespace LCompilers { ASR::is_a(*asr_type)|| ASR::is_a(*asr_type); } + static inline bool is_llvm_pointer(const ASR::ttype_t& asr_type) { + return ( ASR::is_a(asr_type) || + ASR::is_a(asr_type) ); + } } class LLVMList; @@ -123,9 +175,34 @@ namespace LCompilers { LLVMSetInterface* set_api; LLVMArrUtils::Descriptor* arr_api; llvm::Module* module; + std::string& der_type_name; + std::map& name2dertype; + std::map& name2dercontext; + std::vector& struct_type_stack; + std::map& dertype2parent; + std::map>& name2memidx; + std::unordered_map>& arr_arg_type_cache; + std::map>& fname2arg_type; + + LLVMDictInterface* dict_api_lp; + LLVMDictInterface* dict_api_sc; + + CompilerOptions &compiler_options; + + llvm::StructType *complex_type_4, *complex_type_8; + llvm::StructType *complex_type_4_ptr, *complex_type_8_ptr; + llvm::PointerType *character_type; LLVMUtils(llvm::LLVMContext& context, - llvm::IRBuilder<>* _builder); + llvm::IRBuilder<>* _builder, std::string& der_type_name_, + std::map& name2dertype_, + std::map& name2dercontext_, + std::vector& struct_type_stack_, + std::map& dertype2parent_, + std::map>& name2memidx_, + CompilerOptions &compiler_options_, + std::unordered_map>& arr_arg_type_cache_, + std::map>& fname2arg_type_); llvm::Value* create_gep(llvm::Value* ds, int idx); @@ -145,12 +222,68 @@ namespace LCompilers { llvm::Value* is_equal_by_value(llvm::Value* left, llvm::Value* right, llvm::Module& module, ASR::ttype_t* asr_type); + llvm::Value* is_ineq_by_value(llvm::Value* left, llvm::Value* right, + llvm::Module& module, ASR::ttype_t* asr_type, + int8_t overload_id, ASR::ttype_t* int32_type=nullptr); + void set_iterators(); void reset_iterators(); void set_module(llvm::Module* module_); + llvm::Type* getMemberType(ASR::ttype_t* mem_type, + ASR::Variable_t* member, llvm::Module* module); + + void createStructContext(ASR::StructType_t* der_type); + + llvm::Type* getStructType(ASR::StructType_t* der_type, llvm::Module* module, bool is_pointer=false); + + llvm::Type* getStructType(ASR::ttype_t* _type, llvm::Module* module, bool is_pointer=false); + + llvm::Type* getUnionType(ASR::UnionType_t* union_type, + llvm::Module* module, bool is_pointer=false); + + llvm::Type* getUnionType(ASR::ttype_t* _type, + llvm::Module* module, bool is_pointer=false); + + llvm::Type* getClassType(ASR::ClassType_t* der_type, bool is_pointer=false); + + llvm::Type* getClassType(ASR::StructType_t* der_type, bool is_pointer=false); + + llvm::Type* getClassType(ASR::ttype_t* _type, bool is_pointer=false); + + llvm::Type* getFPType(int a_kind, bool get_pointer=false); + + llvm::Type* getComplexType(int a_kind, bool get_pointer=false); + + llvm::Type* get_el_type(ASR::ttype_t* m_type_, llvm::Module* module); + + llvm::Type* get_dict_type(ASR::ttype_t* asr_type, llvm::Module* module); + + llvm::Type* get_set_type(ASR::ttype_t* asr_type, llvm::Module* module); + + llvm::FunctionType* get_function_type(const ASR::Function_t &x, llvm::Module* module); + + std::vector convert_args(const ASR::Function_t &x, llvm::Module* module); + + llvm::Type* get_type_from_ttype_t(ASR::ttype_t* asr_type, + ASR::symbol_t *type_declaration, ASR::storage_typeType m_storage, + bool& is_array_type, bool& is_malloc_array_type, bool& is_list, + ASR::dimension_t*& m_dims, int& n_dims, int& a_kind, llvm::Module* module, + ASR::abiType m_abi=ASR::abiType::Source, bool is_pointer=false); + + llvm::Type* get_type_from_ttype_t_util(ASR::ttype_t* asr_type, + llvm::Module* module, ASR::abiType asr_abi=ASR::abiType::Source); + + llvm::Type* get_arg_type_from_ttype_t(ASR::ttype_t* asr_type, + ASR::symbol_t *type_declaration, ASR::abiType m_abi, ASR::abiType arg_m_abi, + ASR::storage_typeType m_storage, bool arg_m_value_attr, int& n_dims, + int& a_kind, bool& is_array_type, ASR::intentType arg_intent, llvm::Module* module, + bool get_pointer=true); + + void set_dict_api(ASR::Dict_t* dict_type); + void deepcopy(llvm::Value* src, llvm::Value* dest, ASR::ttype_t* asr_type, llvm::Module* module, std::map>& name2memidx); @@ -288,6 +421,11 @@ namespace LCompilers { llvm::Value* check_list_equality(llvm::Value* l1, llvm::Value* l2, ASR::ttype_t *item_type, llvm::LLVMContext& context, llvm::IRBuilder<>* builder, llvm::Module& module); + llvm::Value* check_list_inequality(llvm::Value* l1, llvm::Value* l2, + ASR::ttype_t *item_type, llvm::LLVMContext& context, + llvm::IRBuilder<>* builder, llvm::Module& module, + int8_t overload_id, ASR::ttype_t* int32_type=nullptr); + void list_repeat_copy(llvm::Value* repeat_list, llvm::Value* init_list, llvm::Value* num_times, llvm::Value* init_list_len, llvm::Module* module); @@ -329,6 +467,10 @@ namespace LCompilers { ASR::Tuple_t* tuple_type, llvm::LLVMContext& context, llvm::IRBuilder<>* builder, llvm::Module& module); + llvm::Value* check_tuple_inequality(llvm::Value* t1, llvm::Value* t2, + ASR::Tuple_t* tuple_type, llvm::LLVMContext& context, + llvm::IRBuilder<>* builder, llvm::Module& module, int8_t overload_id); + void concat(llvm::Value* t1, llvm::Value* t2, ASR::Tuple_t* tuple_type_1, ASR::Tuple_t* tuple_type_2, llvm::Value* concat_tuple, ASR::Tuple_t* concat_tuple_type, llvm::Module& module, diff --git a/src/libasr/gen_pass.py b/src/libasr/gen_pass.py new file mode 100644 index 00000000000..560ea4d71d4 --- /dev/null +++ b/src/libasr/gen_pass.py @@ -0,0 +1,59 @@ +passes = [ + "replace_arr_slice", + "replace_array_op", + "replace_class_constructor", + "dead_code_removal", + "replace_div_to_mul", + "replace_do_loops", + "replace_flip_sign", + "replace_fma", + "replace_for_all", + "wrap_global_stmts", + "wrap_global_stmts_program", + "wrap_global_symbols", + "replace_implied_do_loops", + "replace_init_expr", + "inline_function_calls", + "replace_intrinsic_function", + "loop_unroll", + "loop_vectorise", + "nested_vars", + "replace_param_to_const", + "array_by_data", + "compare", + "list_expr", + "replace_print_arr", + "replace_print_list_tuple", + "replace_print_struct_type", + "replace_select_case", + "replace_sign_from_value", + "create_subroutine_from_function", + "transform_optional_argument_functions", + "unused_functions", + "update_array_dim_intrinsic_calls", + "replace_where", +] + + + +for name in passes: + print(f"Processing: {name}") + name_up = name.upper() + header = rf"""#ifndef LIBASR_PASS_{name_up}_H +#define LIBASR_PASS_{name_up}_H + +#include +#include + +namespace LCompilers {{ + + void pass_{name}(Allocator &al, ASR::TranslationUnit_t &unit, + const PassOptions &pass_options); + +}} // namespace LCompilers + +#endif // LIBASR_PASS_{name_up}_H +""" + header_filename = f"pass/{name}.h" + f = open(header_filename, "w") + f.write(header) diff --git a/src/libasr/pass/arr_slice.cpp b/src/libasr/pass/arr_slice.cpp index 8d25bb25923..0c0edc59fca 100644 --- a/src/libasr/pass/arr_slice.cpp +++ b/src/libasr/pass/arr_slice.cpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/libasr/pass/arr_slice.h b/src/libasr/pass/arr_slice.h deleted file mode 100644 index a2ab04bd186..00000000000 --- a/src/libasr/pass/arr_slice.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef LFORTRAN_PASS_ARR_SLICE_H -#define LFORTRAN_PASS_ARR_SLICE_H - -#include -#include - -namespace LCompilers { - - void pass_replace_arr_slice(Allocator &al, ASR::TranslationUnit_t &unit, - const LCompilers::PassOptions& pass_options); - -} // namespace LCompilers - -#endif // LFORTRAN_PASS_ARR_SLICE_H diff --git a/src/libasr/pass/array_by_data.h b/src/libasr/pass/array_by_data.h new file mode 100644 index 00000000000..b62ff7a44c1 --- /dev/null +++ b/src/libasr/pass/array_by_data.h @@ -0,0 +1,14 @@ +#ifndef LIBASR_PASS_ARRAY_BY_DATA_H +#define LIBASR_PASS_ARRAY_BY_DATA_H + +#include +#include + +namespace LCompilers { + + void pass_array_by_data(Allocator &al, ASR::TranslationUnit_t &unit, + const PassOptions &pass_options); + +} // namespace LCompilers + +#endif // LIBASR_PASS_ARRAY_BY_DATA_H diff --git a/src/libasr/pass/array_op.cpp b/src/libasr/pass/array_op.cpp index 4dae651196d..5b64fc12963 100644 --- a/src/libasr/pass/array_op.cpp +++ b/src/libasr/pass/array_op.cpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include #include @@ -409,10 +409,8 @@ class ReplaceArrayOp: public ASR::BaseExprReplacer { case ASR::exprType::IntegerCompare: { ASR::ttype_t* logical_type_t = ASRUtils::TYPE( ASR::make_Logical_t(al, loc, 4)); - if( result_dims.size() > 0 ) { - logical_type_t = ASRUtils::make_Array_t_util(al, loc, - logical_type_t, result_dims.p, result_dims.size()); - } + logical_type_t = ASRUtils::make_Array_t_util(al, loc, + logical_type_t, result_dims.p, result_dims.size()); return logical_type_t; } default: { @@ -486,12 +484,14 @@ class ReplaceArrayOp: public ASR::BaseExprReplacer { result_counter, "_array_section_pointer_", loc, x_m_type, al, current_scope); result_counter += 1; - pass_result.push_back(al, ASRUtils::STMT(ASR::make_Associate_t( + pass_result.push_back(al, ASRUtils::STMT(ASRUtils::make_Associate_t_util( al, loc, array_section_pointer, *current_expr))); *current_expr = array_section_pointer; } - #define allocate_result_var(op_arg, op_dims_arg, op_n_dims_arg) bool is_dimension_empty = false; \ + #define allocate_result_var(op_arg, op_dims_arg, op_n_dims_arg) if( ASR::is_a(*ASRUtils::expr_type(result_var)) || \ + ASR::is_a(*ASRUtils::expr_type(result_var)) ) { \ + bool is_dimension_empty = false; \ for( int i = 0; i < op_n_dims_arg; i++ ) { \ if( op_dims_arg->m_length == nullptr ) { \ is_dimension_empty = true; \ @@ -531,6 +531,7 @@ class ReplaceArrayOp: public ASR::BaseExprReplacer { } \ pass_result.push_back(al, ASRUtils::STMT(ASR::make_Allocate_t(al, \ loc, alloc_args.p, alloc_args.size(), nullptr, nullptr, nullptr))); \ + } template void replace_ArrayOpCommon(T* x, std::string res_prefix) { @@ -978,7 +979,7 @@ class ReplaceArrayOp: public ASR::BaseExprReplacer { Vec empty_dim; empty_dim.reserve(al, 1); ASR::ttype_t* dim_less_type = ASRUtils::duplicate_type(al, x->m_type, &empty_dim); - ASR::expr_t* op_el_wise = ASRUtils::EXPR(ASR::make_IntrinsicFunction_t(al, loc, + ASR::expr_t* op_el_wise = ASRUtils::EXPR(ASRUtils::make_IntrinsicFunction_t_util(al, loc, x->m_intrinsic_id, ref_args.p, ref_args.size(), x->m_overload_id, dim_less_type, nullptr)); ASR::expr_t* res = PassUtils::create_array_ref(result_var, idx_vars, al); @@ -1031,6 +1032,7 @@ class ReplaceArrayOp: public ASR::BaseExprReplacer { ASR::Variable_t *v = ASR::down_cast(v_sym); is_allocatable = ASR::is_a(*v->m_type); if( is_allocatable ) { + result_var_type = ASRUtils::duplicate_type_with_empty_dims(al, result_var_type); result_var_type = ASRUtils::TYPE(ASR::make_Allocatable_t( al, loc, ASRUtils::type_get_past_allocatable(result_var_type))); } @@ -1050,6 +1052,7 @@ class ReplaceArrayOp: public ASR::BaseExprReplacer { op_n_dims = ASRUtils::extract_dimensions_from_ttype( ASRUtils::expr_type(*current_expr), op_dims); } + Vec s_args; s_args.reserve(al, x->n_args + 1); for( size_t i = 0; i < x->n_args; i++ ) { @@ -1059,10 +1062,12 @@ class ReplaceArrayOp: public ASR::BaseExprReplacer { result_arg.loc = result_var->base.loc; result_arg.m_value = *current_expr; s_args.push_back(al, result_arg); - ASR::stmt_t* subrout_call = ASRUtils::STMT(ASR::make_SubroutineCall_t(al, loc, + ASR::stmt_t* subrout_call = ASRUtils::STMT(ASRUtils::make_SubroutineCall_t_util(al, loc, x->m_name, nullptr, s_args.p, s_args.size(), nullptr)); pass_result.push_back(al, subrout_call); - if (is_allocatable && result_var != *current_expr) { + + if (is_allocatable && result_var != *current_expr && + ASRUtils::is_allocatable(result_var)) { Vec vec_alloc; vec_alloc.reserve(al, 1); ASR::alloc_arg_t alloc_arg; @@ -1165,7 +1170,7 @@ class ReplaceArrayOp: public ASR::BaseExprReplacer { empty_dim.reserve(al, 1); ASR::ttype_t* dim_less_type = ASRUtils::duplicate_type(al, x->m_type, &empty_dim); ASR::expr_t* op_el_wise = nullptr; - op_el_wise = ASRUtils::EXPR(ASR::make_FunctionCall_t(al, loc, + op_el_wise = ASRUtils::EXPR(ASRUtils::make_FunctionCall_t_util(al, loc, x->m_name, x->m_original_name, ref_args.p, ref_args.size(), dim_less_type, nullptr, x->m_dt)); ASR::expr_t* res = PassUtils::create_array_ref(result_var, idx_vars, al); diff --git a/src/libasr/pass/array_op.h b/src/libasr/pass/array_op.h deleted file mode 100644 index 33d13bf1aa6..00000000000 --- a/src/libasr/pass/array_op.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef LFORTRAN_PASS_ARRAY_OP_H -#define LFORTRAN_PASS_ARRAY_OP_H - -#include -#include - -namespace LCompilers { - - void pass_replace_array_op(Allocator &al, ASR::TranslationUnit_t &unit, - const LCompilers::PassOptions& pass_options); - -} // namespace LCompilers - -#endif // LFORTRAN_PASS_ARRAY_OP_H diff --git a/src/libasr/pass/class_constructor.cpp b/src/libasr/pass/class_constructor.cpp index cf779eba623..da410efae6b 100644 --- a/src/libasr/pass/class_constructor.cpp +++ b/src/libasr/pass/class_constructor.cpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/libasr/pass/class_constructor.h b/src/libasr/pass/class_constructor.h deleted file mode 100644 index d46b286d0d5..00000000000 --- a/src/libasr/pass/class_constructor.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef LFORTRAN_PASS_CLASS_CONSTRUCTOR_H -#define LFORTRAN_PASS_CLASS_CONSTRUCTOR_H - -#include -#include - -namespace LCompilers { - - void pass_replace_class_constructor(Allocator &al, ASR::TranslationUnit_t &unit, - const LCompilers::PassOptions& pass_options); - -} // namespace LCompilers - -#endif // LFORTRAN_PASS_CLASS_CONSTRUCTOR_H diff --git a/src/libasr/pass/pass_compare.h b/src/libasr/pass/compare.h similarity index 78% rename from src/libasr/pass/pass_compare.h rename to src/libasr/pass/compare.h index 0e2508be6b0..05216a1b07a 100644 --- a/src/libasr/pass/pass_compare.h +++ b/src/libasr/pass/compare.h @@ -7,7 +7,7 @@ namespace LCompilers { void pass_compare(Allocator &al, ASR::TranslationUnit_t &unit, - const LCompilers::PassOptions& /*pass_options*/); + const PassOptions &pass_options); } // namespace LCompilers diff --git a/src/libasr/pass/create_subroutine_from_function.h b/src/libasr/pass/create_subroutine_from_function.h new file mode 100644 index 00000000000..62de377baf5 --- /dev/null +++ b/src/libasr/pass/create_subroutine_from_function.h @@ -0,0 +1,14 @@ +#ifndef LIBASR_PASS_CREATE_SUBROUTINE_FROM_FUNCTION_H +#define LIBASR_PASS_CREATE_SUBROUTINE_FROM_FUNCTION_H + +#include +#include + +namespace LCompilers { + + void pass_create_subroutine_from_function(Allocator &al, ASR::TranslationUnit_t &unit, + const PassOptions &pass_options); + +} // namespace LCompilers + +#endif // LIBASR_PASS_CREATE_SUBROUTINE_FROM_FUNCTION_H diff --git a/src/libasr/pass/dead_code_removal.h b/src/libasr/pass/dead_code_removal.h index 10c0100fe67..e6d4b83019c 100644 --- a/src/libasr/pass/dead_code_removal.h +++ b/src/libasr/pass/dead_code_removal.h @@ -7,8 +7,8 @@ namespace LCompilers { void pass_dead_code_removal(Allocator &al, ASR::TranslationUnit_t &unit, - const LCompilers::PassOptions& pass_options); + const PassOptions &pass_options); } // namespace LCompilers -#endif +#endif // LIBASR_PASS_DEAD_CODE_REMOVAL_H diff --git a/src/libasr/pass/div_to_mul.cpp b/src/libasr/pass/div_to_mul.cpp index 9efe17b6498..b476d89caf4 100644 --- a/src/libasr/pass/div_to_mul.cpp +++ b/src/libasr/pass/div_to_mul.cpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/libasr/pass/div_to_mul.h b/src/libasr/pass/div_to_mul.h deleted file mode 100644 index 0b2f1205f5c..00000000000 --- a/src/libasr/pass/div_to_mul.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef LIBASR_PASS_DIV_TO_MUL_H -#define LIBASR_PASS_DIV_TO_MUL_H - -#include -#include - -namespace LCompilers { - - void pass_replace_div_to_mul(Allocator &al, ASR::TranslationUnit_t &unit, - const LCompilers::PassOptions& pass_options); - -} // namespace LCompilers - -#endif // LIBASR_PASS_DIV_TO_MUL_H diff --git a/src/libasr/pass/do_loops.cpp b/src/libasr/pass/do_loops.cpp index 82dc96408e0..cb8857fa71c 100644 --- a/src/libasr/pass/do_loops.cpp +++ b/src/libasr/pass/do_loops.cpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/libasr/pass/do_loops.h b/src/libasr/pass/do_loops.h deleted file mode 100644 index 7806cb91224..00000000000 --- a/src/libasr/pass/do_loops.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef LFORTRAN_PASS_DO_LOOPS_H -#define LFORTRAN_PASS_DO_LOOPS_H - -#include -#include - -namespace LCompilers { - - void pass_replace_do_loops(Allocator &al, ASR::TranslationUnit_t &unit, - const LCompilers::PassOptions& pass_options); - -} // namespace LCompilers - -#endif // LFORTRAN_PASS_DO_LOOPS_H diff --git a/src/libasr/pass/flip_sign.cpp b/src/libasr/pass/flip_sign.cpp index 6e6d909b89c..64d901e2c86 100644 --- a/src/libasr/pass/flip_sign.cpp +++ b/src/libasr/pass/flip_sign.cpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/libasr/pass/flip_sign.h b/src/libasr/pass/flip_sign.h deleted file mode 100644 index 37b7c5507a9..00000000000 --- a/src/libasr/pass/flip_sign.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef LIBASR_PASS_FLIP_SIGN_H -#define LIBASR_PASS_FLIP_SIGN_H - -#include -#include - -namespace LCompilers { - - void pass_replace_flip_sign(Allocator &al, ASR::TranslationUnit_t &unit, - const LCompilers::PassOptions& pass_options); - -} // namespace LCompilers - -#endif // LIBASR_PASS_FLIP_SIGN_H diff --git a/src/libasr/pass/fma.cpp b/src/libasr/pass/fma.cpp index 45ad29f0793..ded6561ba5a 100644 --- a/src/libasr/pass/fma.cpp +++ b/src/libasr/pass/fma.cpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/libasr/pass/for_all.cpp b/src/libasr/pass/for_all.cpp index 2f2ec3628e2..6db553fb9f5 100644 --- a/src/libasr/pass/for_all.cpp +++ b/src/libasr/pass/for_all.cpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include namespace LCompilers { @@ -43,7 +43,7 @@ class ForAllVisitor : public ASR::StatementWalkVisitor } }; -void pass_replace_forall(Allocator &al, ASR::TranslationUnit_t &unit, +void pass_replace_for_all(Allocator &al, ASR::TranslationUnit_t &unit, const LCompilers::PassOptions& /*pass_options*/) { ForAllVisitor v(al); v.visit_TranslationUnit(unit); diff --git a/src/libasr/pass/for_all.h b/src/libasr/pass/for_all.h deleted file mode 100644 index 47fa99587fd..00000000000 --- a/src/libasr/pass/for_all.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef LFORTRAN_PASS_FOR_ALL -#define LFORTRAN_PASS_FOR_ALL - -#include -#include - -namespace LCompilers { - - void pass_replace_forall(Allocator &al, ASR::TranslationUnit_t &unit, - const LCompilers::PassOptions& pass_options); - -} // namespace LCompilers - -#endif // LFORTRAN_PASS_FOR_ALL diff --git a/src/libasr/pass/global_stmts.cpp b/src/libasr/pass/global_stmts.cpp index 1198571a002..a7db8b6ffc5 100644 --- a/src/libasr/pass/global_stmts.cpp +++ b/src/libasr/pass/global_stmts.cpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include @@ -18,7 +18,7 @@ using ASRUtils::EXPR; * statements and expressions into a function. * */ -void pass_wrap_global_stmts_into_function(Allocator &al, +void pass_wrap_global_stmts(Allocator &al, ASR::TranslationUnit_t &unit, const LCompilers::PassOptions& pass_options) { if (unit.n_items == 0) { return ; diff --git a/src/libasr/pass/global_stmts.h b/src/libasr/pass/global_stmts.h deleted file mode 100644 index ac3bfbbeaa8..00000000000 --- a/src/libasr/pass/global_stmts.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef LFORTRAN_PASS_GLOBAL_STMTS_H -#define LFORTRAN_PASS_GLOBAL_STMTS_H - -#include -#include - -namespace LCompilers { - - void pass_wrap_global_stmts_into_function(Allocator &al, ASR::TranslationUnit_t &unit, - const LCompilers::PassOptions& pass_options); - -} // namespace LCompilers - -#endif // LFORTRAN_PASS_GLOBAL_STMTS_H diff --git a/src/libasr/pass/global_stmts_program.cpp b/src/libasr/pass/global_stmts_program.cpp index 3c63dde9625..54c485f78ea 100644 --- a/src/libasr/pass/global_stmts_program.cpp +++ b/src/libasr/pass/global_stmts_program.cpp @@ -3,8 +3,8 @@ #include #include #include -#include -#include +#include +#include namespace LCompilers { @@ -18,7 +18,7 @@ using ASRUtils::EXPR; * statements and expressions into a program. * */ -void pass_wrap_global_stmts_into_program(Allocator &al, +void pass_wrap_global_stmts_program(Allocator &al, ASR::TranslationUnit_t &unit, const LCompilers::PassOptions& pass_options) { std::string program_fn_name = pass_options.run_fun; SymbolTable *current_scope = al.make_new(unit.m_global_scope); @@ -28,8 +28,8 @@ void pass_wrap_global_stmts_into_program(Allocator &al, SetChar prog_dep; prog_dep.reserve(al, 1); bool call_main_program = unit.n_items > 0; - pass_wrap_global_stmts_into_function(al, unit, pass_options); - pass_wrap_global_syms_into_module(al, unit, pass_options); + pass_wrap_global_stmts(al, unit, pass_options); + pass_wrap_global_symbols(al, unit, pass_options); if( call_main_program && !pass_options.disable_main ) { // Call `_lpython_main_program` function ASR::Module_t *mod = ASR::down_cast( @@ -46,7 +46,7 @@ void pass_wrap_global_stmts_into_program(Allocator &al, fn_s, mod->m_name, nullptr, 0, s2c(al, program_fn_name), ASR::accessType::Public)); current_scope->add_symbol(program_fn_name, fn_s); - ASR::asr_t *stmt = ASR::make_SubroutineCall_t( + ASR::asr_t *stmt = ASRUtils::make_SubroutineCall_t_util( al, unit.base.base.loc, fn_s, nullptr, nullptr, 0, diff --git a/src/libasr/pass/global_stmts_program.h b/src/libasr/pass/global_stmts_program.h deleted file mode 100644 index cc45d0ade14..00000000000 --- a/src/libasr/pass/global_stmts_program.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef LIBASR_PASS_GLOBAL_STMTS_PROGRAM_H -#define LIBASR_PASS_GLOBAL_STMTS_PROGRAM_H - -#include -#include - -namespace LCompilers { - - void pass_wrap_global_stmts_into_program(Allocator &al, ASR::TranslationUnit_t &unit, - const LCompilers::PassOptions& pass_options); - -} // namespace LCompilers - -#endif // LIBASR_PASS_GLOBAL_STMTS_PROGRAM_H diff --git a/src/libasr/pass/global_symbols.cpp b/src/libasr/pass/global_symbols.cpp index 011c749b2d9..b53449b2cde 100644 --- a/src/libasr/pass/global_symbols.cpp +++ b/src/libasr/pass/global_symbols.cpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include @@ -14,7 +14,7 @@ namespace LCompilers { * and wraps all global symbols into a module */ -void pass_wrap_global_syms_into_module(Allocator &al, +void pass_wrap_global_symbols(Allocator &al, ASR::TranslationUnit_t &unit, const LCompilers::PassOptions &/*pass_options*/) { if( unit.m_global_scope->get_scope().size() == 0 ) { diff --git a/src/libasr/pass/global_symbols.h b/src/libasr/pass/global_symbols.h deleted file mode 100644 index 0f74a5550ff..00000000000 --- a/src/libasr/pass/global_symbols.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef LFORTRAN_PASS_GLOBAL_SYMBOLS_H -#define LFORTRAN_PASS_GLOBAL_SYMBOLS_H - -#include -#include - -namespace LCompilers { - - void pass_wrap_global_syms_into_module(Allocator &al, - ASR::TranslationUnit_t &unit, - const LCompilers::PassOptions& pass_options); - -} // namespace LCompilers - -#endif // LFORTRAN_PASS_GLOBAL_SYMBOLS_H diff --git a/src/libasr/pass/implied_do_loops.cpp b/src/libasr/pass/implied_do_loops.cpp index 21669fc43fb..b718e74bb91 100644 --- a/src/libasr/pass/implied_do_loops.cpp +++ b/src/libasr/pass/implied_do_loops.cpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include #include @@ -231,6 +231,14 @@ class ReplaceArrayConstant: public ASR::BaseExprReplacer { result_var = result_var_copy; } + void replace_ArrayPhysicalCast(ASR::ArrayPhysicalCast_t* x) { + ASR::BaseExprReplacer::replace_ArrayPhysicalCast(x); + x->m_old = ASRUtils::extract_physical_type(ASRUtils::expr_type(x->m_arg)); + if( x->m_old == x->m_new ) { + *current_expr = x->m_arg; + } + } + }; class ArrayConstantVisitor : public ASR::CallReplacerOnExpressionsVisitor diff --git a/src/libasr/pass/implied_do_loops.h b/src/libasr/pass/implied_do_loops.h deleted file mode 100644 index 0c611a363bf..00000000000 --- a/src/libasr/pass/implied_do_loops.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef LFORTRAN_PASS_IMPLIED_DO_LOOPS_H -#define LFORTRAN_PASS_IMPLIED_DO_LOOPS_H - -#include -#include - -namespace LCompilers { - - void pass_replace_implied_do_loops(Allocator &al, ASR::TranslationUnit_t &unit, - const LCompilers::PassOptions& pass_options); - -} // namespace LCompilers - -#endif // LFORTRAN_PASS_IMPLIED_DO_LOOPS_H diff --git a/src/libasr/pass/init_expr.cpp b/src/libasr/pass/init_expr.cpp index da36d7a87a2..f31cde1565d 100644 --- a/src/libasr/pass/init_expr.cpp +++ b/src/libasr/pass/init_expr.cpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include #include @@ -136,7 +136,7 @@ class InitExprVisitor : public ASR::CallReplacerOnExpressionsVisitor(*x.m_symbolic_value) || ASR::is_a(*x.m_symbolic_value))) || (ASR::is_a(*asr_owner) && - ASR::is_a(*x.m_symbolic_value)) ) { + ASR::is_a(*x.m_symbolic_value))) { return ; } diff --git a/src/libasr/pass/init_expr.h b/src/libasr/pass/init_expr.h deleted file mode 100644 index 37f226a25ef..00000000000 --- a/src/libasr/pass/init_expr.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef LFORTRAN_PASS_INIT_EXPR_H -#define LFORTRAN_PASS_INIT_EXPR_H - -#include -#include - -namespace LCompilers { - - void pass_replace_init_expr(Allocator &al, ASR::TranslationUnit_t &unit, - const LCompilers::PassOptions& pass_options); - -} // namespace LCompilers - -#endif // LFORTRAN_PASS_INIT_EXPR_H diff --git a/src/libasr/pass/inline_function_calls.cpp b/src/libasr/pass/inline_function_calls.cpp index fa484c65cc0..d8c647940ae 100644 --- a/src/libasr/pass/inline_function_calls.cpp +++ b/src/libasr/pass/inline_function_calls.cpp @@ -263,7 +263,8 @@ class InlineFunctionCallVisitor : public PassUtils::PassVisitorbase.loc, arg_name, al, current_scope, ASRUtils::expr_type(func_margs_i)); + call_arg_var = PassUtils::create_auxiliary_variable(func_margs_i->base.loc, arg_name, al, current_scope, + ASRUtils::duplicate_type(al, ASRUtils::expr_type(func_margs_i))); return_var = call_arg_var; } if( assign_stmt ) { @@ -285,6 +286,10 @@ class InlineFunctionCallVisitor : public PassUtils::PassVisitorbase.base.loc); continue; } + if( !ASR::is_a(*itr.second) ) { + arg2value.clear(); + return ; + } ASR::Variable_t* func_var = ASR::down_cast(itr.second); std::string func_var_name = itr.first; if( arg2value.find(func_var_name) == arg2value.end() ) { diff --git a/src/libasr/pass/inline_function_calls.h b/src/libasr/pass/inline_function_calls.h index 89319356f1b..81bb1bb2c85 100644 --- a/src/libasr/pass/inline_function_calls.h +++ b/src/libasr/pass/inline_function_calls.h @@ -7,8 +7,8 @@ namespace LCompilers { void pass_inline_function_calls(Allocator &al, ASR::TranslationUnit_t &unit, - const LCompilers::PassOptions& pass_options); + const PassOptions &pass_options); } // namespace LCompilers -#endif // LIBASR_PASS_FMA_H +#endif // LIBASR_PASS_INLINE_FUNCTION_CALLS_H diff --git a/src/libasr/pass/instantiate_template.cpp b/src/libasr/pass/instantiate_template.cpp index 5110019c8a2..a72a278c785 100644 --- a/src/libasr/pass/instantiate_template.cpp +++ b/src/libasr/pass/instantiate_template.cpp @@ -175,7 +175,7 @@ class FunctionInstantiator : public ASR::BaseExprStmtDuplicatorm_type); - return ASR::make_ArrayItem_t(al, x->base.base.loc, m_v, args.p, x->n_args, + return ASRUtils::make_ArrayItem_t_util(al, x->base.base.loc, m_v, args.p, x->n_args, ASRUtils::type_get_past_allocatable(type), x->m_storage_format, m_value); } @@ -256,7 +256,7 @@ class FunctionInstantiator : public ASR::BaseExprStmtDuplicator(nested_generic_func); } dependencies.push_back(al, ASRUtils::symbol_name(name)); - return ASR::make_FunctionCall_t(al, x->base.base.loc, name, x->m_original_name, + return ASRUtils::make_FunctionCall_t_util(al, x->base.base.loc, name, x->m_original_name, args.p, args.size(), type, value, dt); } @@ -283,7 +283,7 @@ class FunctionInstantiator : public ASR::BaseExprStmtDuplicator(nested_generic_func); } dependencies.push_back(al, ASRUtils::symbol_name(name)); - return ASR::make_SubroutineCall_t(al, x->base.base.loc, name /* change this */, + return ASRUtils::make_SubroutineCall_t_util(al, x->base.base.loc, name /* change this */, x->m_original_name, args.p, args.size(), dt); } @@ -430,7 +430,7 @@ class FunctionInstantiator : public ASR::BaseExprStmtDuplicator subs, +ASR::symbol_t* pass_instantiate_template(Allocator &al, std::map subs, std::map rt_subs, SymbolTable *current_scope, std::string new_func_name, ASR::symbol_t *sym) { ASR::symbol_t* sym2 = ASRUtils::symbol_get_past_external(sym); diff --git a/src/libasr/pass/instantiate_template.h b/src/libasr/pass/instantiate_template.h index 0e4ae25b3c3..092c2be0460 100644 --- a/src/libasr/pass/instantiate_template.h +++ b/src/libasr/pass/instantiate_template.h @@ -1,18 +1,15 @@ -#ifndef LFORTRAN_PASS_TEMPLATE_VISITOR_H -#define LFORTRAN_PASS_TEMPLATE_VISITOR_H +#ifndef LIBASR_PASS_INSTANTIATE_TEMPLATE_H +#define LIBASR_PASS_INSTANTIATE_TEMPLATE_H #include +#include namespace LCompilers { - /** - * @brief Instantiate a generic function into a function that does not - * contain any type parameters and restrictions. No type checking - * is executed here - */ - ASR::symbol_t* pass_instantiate_generic_function(Allocator &al, + ASR::symbol_t* pass_instantiate_template(Allocator &al, std::map subs, std::map rt_subs, SymbolTable *current_scope, std::string new_func_name, ASR::symbol_t *sym); + } // namespace LCompilers -#endif // LFORTRAN_PASS_TEMPLATE_VISITOR_H +#endif // LIBASR_PASS_INSTANTIATE_TEMPLATE_H diff --git a/src/libasr/pass/intrinsic_function.cpp b/src/libasr/pass/intrinsic_function.cpp index e6c0c6b7137..2efc656ad08 100644 --- a/src/libasr/pass/intrinsic_function.cpp +++ b/src/libasr/pass/intrinsic_function.cpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include #include @@ -71,9 +71,15 @@ class ReplaceIntrinsicFunction: public ASR::BaseExprReplacern_args; i++ ) { arg_types.push_back(al, ASRUtils::expr_type(x->m_args[i])); } - *current_expr = instantiate_function(al, x->base.base.loc, + ASR::expr_t* current_expr_ = instantiate_function(al, x->base.base.loc, global_scope, arg_types, new_args, x->m_overload_id, x->m_value); - ASR::expr_t* func_call = *current_expr; + ASR::expr_t* func_call = current_expr_; + if( ASR::is_a(*(*current_expr)) ) { + ASR::ArrayPhysicalCast_t* array_physical_cast_t = ASR::down_cast(*current_expr); + array_physical_cast_t->m_arg = current_expr_; + } else { + *current_expr = current_expr_; + } LCOMPILERS_ASSERT(ASR::is_a(*func_call)); ASR::FunctionCall_t* function_call_t = ASR::down_cast(func_call); ASR::symbol_t* function_call_t_symbol = ASRUtils::symbol_get_past_external(function_call_t->m_name); @@ -253,11 +259,11 @@ class ReplaceFunctionCallReturningArray: public ASR::BaseExprReplacerbase.loc; new_arg.m_value = result_var_; new_args.push_back(al, new_arg); - pass_result.push_back(al, ASRUtils::STMT(ASR::make_SubroutineCall_t( + pass_result.push_back(al, ASRUtils::STMT(ASRUtils::make_SubroutineCall_t_util( al, x->base.base.loc, x->m_name, x->m_original_name, new_args.p, new_args.size(), x->m_dt))); - *current_expr = result_var_; + *current_expr = new_args.p[new_args.size() - 1].m_value; } }; @@ -310,6 +316,15 @@ class ReplaceFunctionCallReturningArrayVisitor : public ASR::CallReplacerOnExpre pass_result.n = 0; } + void visit_Assignment(const ASR::Assignment_t& x) { + ASR::CallReplacerOnExpressionsVisitor< + ReplaceFunctionCallReturningArrayVisitor>::visit_Assignment(x); + ASR::Assignment_t& xx = const_cast(x); + if( ASR::is_a(*x.m_value) ) { + xx.m_value = ASR::down_cast(x.m_value)->m_arg; + } + } + }; void pass_replace_intrinsic_function(Allocator &al, ASR::TranslationUnit_t &unit, diff --git a/src/libasr/pass/intrinsic_function.h b/src/libasr/pass/intrinsic_function.h deleted file mode 100644 index 414eb335e40..00000000000 --- a/src/libasr/pass/intrinsic_function.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef LIBASR_PASS_INTRINSIC_FUNCTION_H -#define LIBASR_PASS_INTRINSIC_FUNCTION_H - -#include -#include - -namespace LCompilers { - - void pass_replace_intrinsic_function(Allocator &al, ASR::TranslationUnit_t &unit, - const PassOptions& pass_options); - -} // namespace LCompilers - -#endif // LIBASR_PASS_INTRINSIC_FUNCTION_H diff --git a/src/libasr/pass/intrinsic_function_registry.h b/src/libasr/pass/intrinsic_function_registry.h index daa0ab8a459..cff08d2e699 100644 --- a/src/libasr/pass/intrinsic_function_registry.h +++ b/src/libasr/pass/intrinsic_function_registry.h @@ -74,6 +74,11 @@ enum class IntrinsicFunctions : int64_t { SymbolicInteger, SymbolicDiff, SymbolicExpand, + SymbolicSin, + SymbolicCos, + SymbolicLog, + SymbolicExp, + SymbolicAbs, Sum, // ... }; @@ -318,7 +323,7 @@ class ASRBuilder { ASR::expr_t* Call(ASR::symbol_t* s, Vec& args, ASR::ttype_t* return_type) { - return ASRUtils::EXPR(ASR::make_FunctionCall_t(al, loc, + return ASRUtils::EXPR(ASRUtils::make_FunctionCall_t_util(al, loc, s, s, args.p, args.size(), return_type, nullptr, nullptr)); } @@ -326,13 +331,13 @@ class ASRBuilder { ASR::ttype_t* return_type) { Vec args_; args_.reserve(al, 2); visit_expr_list(al, args, args_); - return ASRUtils::EXPR(ASR::make_FunctionCall_t(al, loc, + return ASRUtils::EXPR(ASRUtils::make_FunctionCall_t_util(al, loc, s, s, args_.p, args_.size(), return_type, nullptr, nullptr)); } ASR::expr_t* Call(ASR::symbol_t* s, Vec& args, ASR::ttype_t* return_type, ASR::expr_t* value) { - return ASRUtils::EXPR(ASR::make_FunctionCall_t(al, loc, + return ASRUtils::EXPR(ASRUtils::make_FunctionCall_t_util(al, loc, s, s, args.p, args.size(), return_type, value, nullptr)); } @@ -2169,45 +2174,52 @@ namespace SymbolicInteger { } } // namespace SymbolicInteger -namespace SymbolicExpand { - - static inline void verify_args(const ASR::IntrinsicFunction_t& x, diag::Diagnostics& diagnostics) { - const Location& loc = x.base.base.loc; - ASRUtils::require_impl(x.n_args == 1, - "SymbolicExpand must have exactly 1 input argument", - loc, diagnostics); - - ASR::ttype_t* input_type = ASRUtils::expr_type(x.m_args[0]); - ASRUtils::require_impl(ASR::is_a(*input_type), - "SymbolicExpand expects an argument of type SymbolicExpression", - x.base.base.loc, diagnostics); - } - - static inline ASR::expr_t *eval_SymbolicExpand(Allocator &/*al*/, - const Location &/*loc*/, Vec& /*args*/) { - // TODO - return nullptr; - } - - static inline ASR::asr_t* create_SymbolicExpand(Allocator& al, const Location& loc, - Vec& args, - const std::function err) { - if (args.size() != 1) { - err("Intrinsic expand function accepts exactly 1 argument", loc); - } - - ASR::ttype_t* argtype = ASRUtils::expr_type(args[0]); - if(!ASR::is_a(*argtype)) { - err("Argument of SymbolicExpand function must be of type SymbolicExpression", - args[0]->base.loc); - } - - ASR::ttype_t *to_type = ASRUtils::TYPE(ASR::make_SymbolicExpression_t(al, loc)); - return UnaryIntrinsicFunction::create_UnaryFunction(al, loc, args, eval_SymbolicExpand, - static_cast(ASRUtils::IntrinsicFunctions::SymbolicExpand), 0, to_type); - } +#define create_symbolic_unary_macro(X) \ +namespace X { \ + \ + static inline void verify_args(const ASR::IntrinsicFunction_t& x, \ + diag::Diagnostics& diagnostics) { \ + const Location& loc = x.base.base.loc; \ + ASRUtils::require_impl(x.n_args == 1, \ + #X " must have exactly 1 input argument", loc, diagnostics); \ + \ + ASR::ttype_t* input_type = ASRUtils::expr_type(x.m_args[0]); \ + ASRUtils::require_impl(ASR::is_a(*input_type), \ + #X " expects an argument of type SymbolicExpression", loc, diagnostics); \ + } \ + \ + static inline ASR::expr_t* eval_##X(Allocator &/*al*/, const Location &/*loc*/, \ + Vec &/*args*/) { \ + /*TODO*/ \ + return nullptr; \ + } \ + \ + static inline ASR::asr_t* create_##X(Allocator& al, const Location& loc, \ + Vec& args, \ + const std::function err) { \ + if (args.size() != 1) { \ + err("Intrinsic " #X " function accepts exactly 1 argument", loc); \ + } \ + \ + ASR::ttype_t* argtype = ASRUtils::expr_type(args[0]); \ + if (!ASR::is_a(*argtype)) { \ + err("Argument of " #X " function must be of type SymbolicExpression", \ + args[0]->base.loc); \ + } \ + \ + ASR::ttype_t *to_type = ASRUtils::TYPE(ASR::make_SymbolicExpression_t(al, loc)); \ + return UnaryIntrinsicFunction::create_UnaryFunction(al, loc, args, eval_##X, \ + static_cast(ASRUtils::IntrinsicFunctions::X), 0, to_type); \ + } \ + \ +} // namespace X -} // namespace SymbolicExpand +create_symbolic_unary_macro(SymbolicSin) +create_symbolic_unary_macro(SymbolicCos) +create_symbolic_unary_macro(SymbolicLog) +create_symbolic_unary_macro(SymbolicExp) +create_symbolic_unary_macro(SymbolicAbs) +create_symbolic_unary_macro(SymbolicExpand) namespace IntrinsicFunctionRegistry { @@ -2275,6 +2287,16 @@ namespace IntrinsicFunctionRegistry { {nullptr, &SymbolicDiff::verify_args}}, {static_cast(ASRUtils::IntrinsicFunctions::SymbolicExpand), {nullptr, &SymbolicExpand::verify_args}}, + {static_cast(ASRUtils::IntrinsicFunctions::SymbolicSin), + {nullptr, &SymbolicSin::verify_args}}, + {static_cast(ASRUtils::IntrinsicFunctions::SymbolicCos), + {nullptr, &SymbolicCos::verify_args}}, + {static_cast(ASRUtils::IntrinsicFunctions::SymbolicLog), + {nullptr, &SymbolicLog::verify_args}}, + {static_cast(ASRUtils::IntrinsicFunctions::SymbolicExp), + {nullptr, &SymbolicExp::verify_args}}, + {static_cast(ASRUtils::IntrinsicFunctions::SymbolicAbs), + {nullptr, &SymbolicAbs::verify_args}}, }; static const std::map& intrinsic_function_id_to_name = { @@ -2333,6 +2355,16 @@ namespace IntrinsicFunctionRegistry { "SymbolicDiff"}, {static_cast(ASRUtils::IntrinsicFunctions::SymbolicExpand), "SymbolicExpand"}, + {static_cast(ASRUtils::IntrinsicFunctions::SymbolicSin), + "SymbolicSin"}, + {static_cast(ASRUtils::IntrinsicFunctions::SymbolicCos), + "SymbolicCos"}, + {static_cast(ASRUtils::IntrinsicFunctions::SymbolicLog), + "SymbolicLog"}, + {static_cast(ASRUtils::IntrinsicFunctions::SymbolicExp), + "SymbolicExp"}, + {static_cast(ASRUtils::IntrinsicFunctions::SymbolicAbs), + "SymbolicAbs"}, {static_cast(ASRUtils::IntrinsicFunctions::Any), "any"}, {static_cast(ASRUtils::IntrinsicFunctions::Sum), @@ -2372,6 +2404,11 @@ namespace IntrinsicFunctionRegistry { {"SymbolicInteger", {&SymbolicInteger::create_SymbolicInteger, &SymbolicInteger::eval_SymbolicInteger}}, {"diff", {&SymbolicDiff::create_SymbolicDiff, &SymbolicDiff::eval_SymbolicDiff}}, {"expand", {&SymbolicExpand::create_SymbolicExpand, &SymbolicExpand::eval_SymbolicExpand}}, + {"SymbolicSin", {&SymbolicSin::create_SymbolicSin, &SymbolicSin::eval_SymbolicSin}}, + {"SymbolicCos", {&SymbolicCos::create_SymbolicCos, &SymbolicCos::eval_SymbolicCos}}, + {"SymbolicLog", {&SymbolicLog::create_SymbolicLog, &SymbolicLog::eval_SymbolicLog}}, + {"SymbolicExp", {&SymbolicExp::create_SymbolicExp, &SymbolicExp::eval_SymbolicExp}}, + {"SymbolicAbs", {&SymbolicAbs::create_SymbolicAbs, &SymbolicAbs::eval_SymbolicAbs}}, }; static inline bool is_intrinsic_function(const std::string& name) { @@ -2488,6 +2525,11 @@ inline std::string get_intrinsic_name(int x) { INTRINSIC_NAME_CASE(SymbolicInteger) INTRINSIC_NAME_CASE(SymbolicDiff) INTRINSIC_NAME_CASE(SymbolicExpand) + INTRINSIC_NAME_CASE(SymbolicSin) + INTRINSIC_NAME_CASE(SymbolicCos) + INTRINSIC_NAME_CASE(SymbolicLog) + INTRINSIC_NAME_CASE(SymbolicExp) + INTRINSIC_NAME_CASE(SymbolicAbs) INTRINSIC_NAME_CASE(Sum) default : { throw LCompilersException("pickle: intrinsic_id not implemented"); diff --git a/src/libasr/pass/pass_list_expr.h b/src/libasr/pass/list_expr.h similarity index 78% rename from src/libasr/pass/pass_list_expr.h rename to src/libasr/pass/list_expr.h index 9ee5f380c69..f12c7f318be 100644 --- a/src/libasr/pass/pass_list_expr.h +++ b/src/libasr/pass/list_expr.h @@ -7,7 +7,7 @@ namespace LCompilers { void pass_list_expr(Allocator &al, ASR::TranslationUnit_t &unit, - const LCompilers::PassOptions& /*pass_options*/); + const PassOptions &pass_options); } // namespace LCompilers diff --git a/src/libasr/pass/loop_unroll.cpp b/src/libasr/pass/loop_unroll.cpp index 852d038d574..58523e4ddfb 100644 --- a/src/libasr/pass/loop_unroll.cpp +++ b/src/libasr/pass/loop_unroll.cpp @@ -21,17 +21,14 @@ class LoopUnrollVisitor : public PassUtils::PassVisitor { private: - std::string rl_path; - int64_t unroll_factor; ASRUtils::ExprStmtDuplicator node_duplicator; public: - LoopUnrollVisitor(Allocator &al_, const std::string& rl_path_, - size_t unroll_factor_) : - PassVisitor(al_, nullptr), rl_path(rl_path_), + LoopUnrollVisitor(Allocator &al_, size_t unroll_factor_) : + PassVisitor(al_, nullptr), unroll_factor(unroll_factor_), node_duplicator(al_) { pass_result.reserve(al, 1); @@ -107,9 +104,7 @@ class LoopUnrollVisitor : public PassUtils::PassVisitor void pass_loop_unroll(Allocator &al, ASR::TranslationUnit_t &unit, const LCompilers::PassOptions& pass_options) { - std::string rl_path = pass_options.runtime_library_dir; - int64_t unroll_factor = pass_options.unroll_factor; - LoopUnrollVisitor v(al, rl_path, unroll_factor); + LoopUnrollVisitor v(al, pass_options.unroll_factor); v.visit_TranslationUnit(unit); } diff --git a/src/libasr/pass/loop_unroll.h b/src/libasr/pass/loop_unroll.h index 37eddf13554..efa6b77bfaa 100644 --- a/src/libasr/pass/loop_unroll.h +++ b/src/libasr/pass/loop_unroll.h @@ -7,7 +7,7 @@ namespace LCompilers { void pass_loop_unroll(Allocator &al, ASR::TranslationUnit_t &unit, - const LCompilers::PassOptions& pass_options); + const PassOptions &pass_options); } // namespace LCompilers diff --git a/src/libasr/pass/loop_vectorise.h b/src/libasr/pass/loop_vectorise.h index 23914460683..d509aa22ceb 100644 --- a/src/libasr/pass/loop_vectorise.h +++ b/src/libasr/pass/loop_vectorise.h @@ -7,7 +7,7 @@ namespace LCompilers { void pass_loop_vectorise(Allocator &al, ASR::TranslationUnit_t &unit, - const LCompilers::PassOptions& pass_options); + const PassOptions &pass_options); } // namespace LCompilers diff --git a/src/libasr/pass/nested_vars.cpp b/src/libasr/pass/nested_vars.cpp index 1f25985964a..02e814269c1 100644 --- a/src/libasr/pass/nested_vars.cpp +++ b/src/libasr/pass/nested_vars.cpp @@ -212,6 +212,11 @@ class ReplacerNestedVars: public ASR::BaseExprReplacer { } } } + + void replace_ArrayPhysicalCast(ASR::ArrayPhysicalCast_t* x) { + ASR::BaseExprReplacer::replace_ArrayPhysicalCast(x); + x->m_old = ASRUtils::extract_physical_type(ASRUtils::expr_type(x->m_arg)); + } }; class ReplaceNestedVisitor: public ASR::CallReplacerOnExpressionsVisitor { @@ -397,6 +402,8 @@ class ReplaceNestedVisitor: public ASR::CallReplacerOnExpressionsVisitor(x); + ASRUtils::Call_t_body(al, xx.m_name, xx.m_args, xx.n_args, x.m_dt); } void visit_SubroutineCall(const ASR::SubroutineCall_t &x) { @@ -414,6 +421,9 @@ class ReplaceNestedVisitor: public ASR::CallReplacerOnExpressionsVisitor(x); + ASRUtils::Call_t_body(al, xx.m_name, xx.m_args, xx.n_args, x.m_dt); } }; @@ -495,7 +505,7 @@ class AssignNestedVars: public PassUtils::PassVisitor { ASR::expr_t *val = ASRUtils::EXPR(ASR::make_Var_t(al, t->base.loc, sym_)); if( ASRUtils::is_array(ASRUtils::symbol_type(sym)) || ASR::is_a(*ASRUtils::symbol_type(sym)) ) { - ASR::stmt_t *associate = ASRUtils::STMT(ASR::make_Associate_t(al, t->base.loc, + ASR::stmt_t *associate = ASRUtils::STMT(ASRUtils::make_Associate_t_util(al, t->base.loc, target, val)); body.push_back(al, associate); } else { diff --git a/src/libasr/pass/nested_vars.h b/src/libasr/pass/nested_vars.h index 9998e4d1303..baa7c0c8fd0 100644 --- a/src/libasr/pass/nested_vars.h +++ b/src/libasr/pass/nested_vars.h @@ -1,13 +1,14 @@ -#ifndef LFORTRAN_PASS_NESTED_VARS_H -#define LFORTRAN_PASS_NESTED_VARS_H +#ifndef LIBASR_PASS_NESTED_VARS_H +#define LIBASR_PASS_NESTED_VARS_H #include +#include namespace LCompilers { - void pass_nested_vars(Allocator &al, ASR::TranslationUnit_t &unit, - const LCompilers::PassOptions& pass_options); + void pass_nested_vars(Allocator &al, ASR::TranslationUnit_t &unit, + const PassOptions &pass_options); } // namespace LCompilers -#endif // LFORTRAN_PASS_NESTED_VARS_H +#endif // LIBASR_PASS_NESTED_VARS_H diff --git a/src/libasr/pass/param_to_const.cpp b/src/libasr/pass/param_to_const.cpp index 37df2ea7016..3a792475257 100644 --- a/src/libasr/pass/param_to_const.cpp +++ b/src/libasr/pass/param_to_const.cpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include namespace LCompilers { diff --git a/src/libasr/pass/param_to_const.h b/src/libasr/pass/param_to_const.h deleted file mode 100644 index 8b2c70ac567..00000000000 --- a/src/libasr/pass/param_to_const.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef LFORTRAN_PASS_PARAM_TO_CONST_H -#define LFORTRAN_PASS_PARAM_TO_CONST_H - -#include -#include - -namespace LCompilers { - - void pass_replace_param_to_const(Allocator &al, ASR::TranslationUnit_t &unit, - const LCompilers::PassOptions& pass_options - ); - -} // namespace LCompilers - -#endif // LFORTRAN_PASS_PARAM_TO_CONST_H diff --git a/src/libasr/pass/pass_array_by_data.cpp b/src/libasr/pass/pass_array_by_data.cpp index 864291af655..0518fcbbd6e 100644 --- a/src/libasr/pass/pass_array_by_data.cpp +++ b/src/libasr/pass/pass_array_by_data.cpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include #include @@ -196,6 +196,9 @@ class PassArrayByDataProcedureVisitor : public PassUtils::PassVisitorm_function_signature = ASRUtils::TYPE(ASRUtils::make_FunctionType_t_util( + al, func_type->base.base.loc, new_args.p, new_args.size(), x->m_return_var, func_type)); x->m_args = new_args.p; x->n_args = new_args.size(); } @@ -260,69 +263,85 @@ class PassArrayByDataProcedureVisitor : public PassUtils::PassVisitor { +#define edit_symbol_reference(attr) ASR::symbol_t* x_sym = xx.m_##attr; \ + SymbolTable* x_sym_symtab = ASRUtils::symbol_parent_symtab(x_sym); \ + if( x_sym_symtab->get_counter() != current_scope->get_counter() && \ + !ASRUtils::is_parent(x_sym_symtab, current_scope) ) { \ + std::string x_sym_name = std::string(ASRUtils::symbol_name(x_sym)); \ + xx.m_##attr = current_scope->resolve_symbol(x_sym_name); \ + LCOMPILERS_ASSERT(xx.m_##attr != nullptr); \ + } \ + +#define edit_symbol_pointer(attr) ASR::symbol_t* x_sym = x->m_##attr; \ + SymbolTable* x_sym_symtab = ASRUtils::symbol_parent_symtab(x_sym); \ + if( x_sym_symtab->get_counter() != current_scope->get_counter() && \ + !ASRUtils::is_parent(x_sym_symtab, current_scope) ) { \ + std::string x_sym_name = std::string(ASRUtils::symbol_name(x_sym)); \ + x->m_##attr = current_scope->resolve_symbol(x_sym_name); \ + LCOMPILERS_ASSERT(x->m_##attr != nullptr); \ + } \ + +class EditProcedureReplacer: public ASR::BaseExprReplacer { public: PassArrayByDataProcedureVisitor& v; + SymbolTable* current_scope; - EditProcedureVisitor(PassArrayByDataProcedureVisitor& v_): - v(v_) {} - - void visit_Function(const ASR::Function_t &x) { - ASR::Function_t& xx = const_cast(x); - SymbolTable* current_scope_copy = current_scope; - current_scope = x.m_symtab; - for (auto &a : x.m_symtab->get_scope()) { - this->visit_symbol(*a.second); + EditProcedureReplacer(PassArrayByDataProcedureVisitor& v_): + v(v_), current_scope(nullptr) {} + + void replace_Var(ASR::Var_t* x) { + ASR::symbol_t* x_sym_ = x->m_v; + if ( v.proc2newproc.find(x_sym_) != v.proc2newproc.end() ) { + x->m_v = v.proc2newproc[x_sym_].first; + return ; } - visit_ttype(*x.m_function_signature); + edit_symbol_pointer(v) + } - for (size_t i=0; i::replace_ArrayPhysicalCast(x); + x->m_old = ASRUtils::extract_physical_type(ASRUtils::expr_type(x->m_arg)); + if( x->m_old == x->m_new) { + *current_expr = x->m_arg; } - transform_stmts(xx.m_body, xx.n_body); - if (x.m_return_var) - visit_expr(*x.m_return_var); - current_scope = current_scope_copy; } - #define edit_symbol(attr) ASR::symbol_t* x_sym = xx.m_##attr; \ - SymbolTable* x_sym_symtab = ASRUtils::symbol_parent_symtab(x_sym); \ - if( x_sym_symtab->get_counter() != current_scope->get_counter() && \ - !ASRUtils::is_parent(x_sym_symtab, current_scope) ) { \ - std::string x_sym_name = std::string(ASRUtils::symbol_name(x_sym)); \ - xx.m_##attr = current_scope->resolve_symbol(x_sym_name); \ - LCOMPILERS_ASSERT(xx.m_##attr != nullptr); \ - } \ - - void visit_Var(const ASR::Var_t& x) { - ASR::Var_t& xx = const_cast(x); - ASR::symbol_t* x_sym_ = xx.m_v; - if ( v.proc2newproc.find(x_sym_) != v.proc2newproc.end() ) { - xx.m_v = v.proc2newproc[x_sym_].first; - return ; - } + void replace_FunctionCall(ASR::FunctionCall_t* x) { + edit_symbol_pointer(name) + ASR::BaseExprReplacer::replace_FunctionCall(x); + } + +}; + +class EditProcedureVisitor: public ASR::CallReplacerOnExpressionsVisitor { - edit_symbol(v) + public: + + PassArrayByDataProcedureVisitor& v; + EditProcedureReplacer replacer; + + EditProcedureVisitor(PassArrayByDataProcedureVisitor& v_): + v(v_), replacer(v) {} + + void call_replacer() { + replacer.current_expr = current_expr; + replacer.current_scope = current_scope; + replacer.replace_expr(*current_expr); } void visit_BlockCall(const ASR::BlockCall_t& x) { ASR::BlockCall_t& xx = const_cast(x); - edit_symbol(m) - } - - void visit_FunctionCall(const ASR::FunctionCall_t& x) { - ASR::FunctionCall_t& xx = const_cast(x); - edit_symbol(name) - ASR::ASRPassBaseWalkVisitor::visit_FunctionCall(x); + edit_symbol_reference(m) + ASR::CallReplacerOnExpressionsVisitor::visit_BlockCall(x); } void visit_SubroutineCall(const ASR::SubroutineCall_t& x) { ASR::SubroutineCall_t& xx = const_cast(x); - edit_symbol(name) - ASR::ASRPassBaseWalkVisitor::visit_SubroutineCall(x); + edit_symbol_reference(name) + ASR::CallReplacerOnExpressionsVisitor::visit_SubroutineCall(x); } }; @@ -394,12 +413,32 @@ class EditProcedureCallsVisitor : public ASR::ASRPassBaseWalkVisitor new_args; new_args.reserve(al, n_args); for( size_t i = 0; i < n_args; i++ ) { - new_args.push_back(al, orig_args[i]); if (orig_args[i].m_value == nullptr || std::find(indices.begin(), indices.end(), i) == indices.end()) { + new_args.push_back(al, orig_args[i]); continue; } + ASR::ttype_t* orig_arg_type = ASRUtils::expr_type(orig_args[i].m_value); + if( ASRUtils::is_array(orig_arg_type) ) { + ASR::Array_t* array_t = ASR::down_cast( + ASRUtils::type_get_past_allocatable(orig_arg_type)); + if( array_t->m_physical_type != ASR::array_physical_typeType::PointerToDataArray ) { + ASR::expr_t* physical_cast = ASRUtils::EXPR(ASRUtils::make_ArrayPhysicalCast_t_util( + al, orig_args[i].m_value->base.loc, orig_args[i].m_value, array_t->m_physical_type, + ASR::array_physical_typeType::PointerToDataArray, ASRUtils::duplicate_type(al, orig_arg_type, + nullptr, ASR::array_physical_typeType::PointerToDataArray, true), nullptr)); + ASR::call_arg_t physical_cast_arg; + physical_cast_arg.loc = orig_args[i].m_value->base.loc; + physical_cast_arg.m_value = physical_cast; + new_args.push_back(al, physical_cast_arg); + } else { + new_args.push_back(al, orig_args[i]); + } + } else { + new_args.push_back(al, orig_args[i]); + } + Vec dim_vars; dim_vars.reserve(al, 2); ASRUtils::get_dimensions(orig_args[i].m_value, dim_vars, al); diff --git a/src/libasr/pass/pass_array_by_data.h b/src/libasr/pass/pass_array_by_data.h deleted file mode 100644 index 6b7fc49b16a..00000000000 --- a/src/libasr/pass/pass_array_by_data.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef LFORTRAN_PASS_ARRAY_BY_DATA_H -#define LFORTRAN_PASS_ARRAY_BY_DATA_H - -#include -#include - -namespace LCompilers { - - void pass_array_by_data(Allocator &al, ASR::TranslationUnit_t &unit, - const LCompilers::PassOptions& pass_options); - -} // namespace LCompilers - -#endif // LFORTRAN_PASS_ARRAY_BY_DATA_H diff --git a/src/libasr/pass/pass_compare.cpp b/src/libasr/pass/pass_compare.cpp index 8488fe42435..27e1bd00d99 100644 --- a/src/libasr/pass/pass_compare.cpp +++ b/src/libasr/pass/pass_compare.cpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include #include @@ -126,7 +126,7 @@ class CompareExprReplacer : public ASR::BaseExprReplacer call_arg.m_value = rig; args.push_back(al, call_arg); - return ASRUtils::EXPR(ASR::make_FunctionCall_t(al, loc, + return ASRUtils::EXPR(ASRUtils::make_FunctionCall_t_util(al, loc, fn, nullptr, args.p, args.n, bool_type, nullptr, nullptr)); } @@ -142,7 +142,7 @@ class CompareExprReplacer : public ASR::BaseExprReplacer call_arg.m_value = rig; args.push_back(al, call_arg); - return ASRUtils::EXPR(ASR::make_FunctionCall_t(al, loc, + return ASRUtils::EXPR(ASRUtils::make_FunctionCall_t_util(al, loc, fn, nullptr, args.p, args.n, bool_type, nullptr, nullptr)); } @@ -264,7 +264,7 @@ class CompareExprReplacer : public ASR::BaseExprReplacer args.push_back(al, call_arg); ASR::symbol_t *fn_sym = get_tuple_compare_func(unit.base.base.loc, unit.m_global_scope, ASRUtils::expr_type(x->m_left)); - *current_expr = ASRUtils::EXPR(ASR::make_FunctionCall_t(al, loc, + *current_expr = ASRUtils::EXPR(ASRUtils::make_FunctionCall_t_util(al, loc, fn_sym, nullptr, args.p, args.n, bool_type, nullptr, nullptr)); if (x->m_op == ASR::cmpopType::NotEq) { *current_expr = ASRUtils::EXPR(ASR::make_LogicalNot_t(al, loc, @@ -450,7 +450,7 @@ class CompareExprReplacer : public ASR::BaseExprReplacer args.push_back(al, call_arg); ASR::symbol_t *fn_sym = get_list_compare_func(unit.base.base.loc, unit.m_global_scope, ASRUtils::expr_type(x->m_left)); - *current_expr = ASRUtils::EXPR(ASR::make_FunctionCall_t(al, loc, + *current_expr = ASRUtils::EXPR(ASRUtils::make_FunctionCall_t_util(al, loc, fn_sym, nullptr, args.p, args.n, bool_type, nullptr, nullptr)); if (x->m_op == ASR::cmpopType::NotEq) { *current_expr = ASRUtils::EXPR(ASR::make_LogicalNot_t(al, loc, diff --git a/src/libasr/pass/pass_list_expr.cpp b/src/libasr/pass/pass_list_expr.cpp index 02acedd39e7..ad3e5a658d6 100644 --- a/src/libasr/pass/pass_list_expr.cpp +++ b/src/libasr/pass/pass_list_expr.cpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include #include @@ -409,7 +409,7 @@ class ListExprReplacer : public ASR::BaseExprReplacer unit.m_global_scope, x->m_type); } ASR::symbol_t *fn_sym = list_section_func_map[list_type_name]; - *current_expr = ASRUtils::EXPR(ASR::make_FunctionCall_t(al, loc, + *current_expr = ASRUtils::EXPR(ASRUtils::make_FunctionCall_t_util(al, loc, fn_sym, nullptr, args.p, args.n, x->m_type, nullptr, nullptr)); } @@ -534,7 +534,7 @@ class ListExprReplacer : public ASR::BaseExprReplacer unit.m_global_scope, x->m_type); } ASR::symbol_t *fn_sym = list_concat_func_map[list_type_name]; - *current_expr = ASRUtils::EXPR(ASR::make_FunctionCall_t(al, loc, + *current_expr = ASRUtils::EXPR(ASRUtils::make_FunctionCall_t_util(al, loc, fn_sym, nullptr, args.p, 2, x->m_type, nullptr, nullptr)); } diff --git a/src/libasr/pass/pass_manager.h b/src/libasr/pass/pass_manager.h index 4e02616469c..801719367f1 100644 --- a/src/libasr/pass/pass_manager.h +++ b/src/libasr/pass/pass_manager.h @@ -14,39 +14,39 @@ #include #endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include -#include -#include +#include +#include #include #include #include -#include -#include -#include +#include +#include +#include #include #include -#include -#include -#include +#include +#include +#include #include #include -#include +#include #include #include @@ -67,7 +67,7 @@ namespace LCompilers { std::vector _skip_passes, _c_skip_passes; std::map _passes_db = { {"do_loops", &pass_replace_do_loops}, - {"global_stmts", &pass_wrap_global_stmts_into_function}, + {"global_stmts", &pass_wrap_global_stmts}, {"implied_do_loops", &pass_replace_implied_do_loops}, {"array_op", &pass_replace_array_op}, {"intrinsic_function", &pass_replace_intrinsic_function}, @@ -83,7 +83,7 @@ namespace LCompilers { {"inline_function_calls", &pass_inline_function_calls}, {"loop_unroll", &pass_loop_unroll}, {"dead_code_removal", &pass_dead_code_removal}, - {"forall", &pass_replace_forall}, + {"forall", &pass_replace_for_all}, {"select_case", &pass_replace_select_case}, {"loop_vectorise", &pass_loop_vectorise}, {"array_dim_intrinsics_update", &pass_update_array_dim_intrinsic_calls}, diff --git a/src/libasr/pass/pass_utils.cpp b/src/libasr/pass/pass_utils.cpp index c1a1a71e9d6..1b310a20d31 100644 --- a/src/libasr/pass/pass_utils.cpp +++ b/src/libasr/pass/pass_utils.cpp @@ -67,6 +67,10 @@ namespace LCompilers { ASR::ttype_t *x_type = ASR::down_cast(x)->m_type; ASR::dimension_t* m_dims; get_dim_rank(x_type, m_dims, n_dims); + } else if (ASR::is_a(*x)) { + ASR::ttype_t* x_type = ASR::down_cast(x)->m_type; + ASR::dimension_t* m_dims; + get_dim_rank(x_type, m_dims, n_dims); } return n_dims; } @@ -105,7 +109,7 @@ namespace LCompilers { array_ref_type = struct_type; } } - ASR::expr_t* array_ref = ASRUtils::EXPR(ASR::make_ArrayItem_t(al, + ASR::expr_t* array_ref = ASRUtils::EXPR(ASRUtils::make_ArrayItem_t_util(al, arr_expr->base.loc, arr_expr, args.p, args.size(), ASRUtils::type_get_past_array( @@ -129,7 +133,7 @@ namespace LCompilers { empty_dims.reserve(al, 1); ASR::ttype_t* array_ref_type = ASRUtils::expr_type(arr_expr); array_ref_type = ASRUtils::duplicate_type(al, array_ref_type, &empty_dims); - ASR::expr_t* array_ref = ASRUtils::EXPR(ASR::make_ArrayItem_t(al, + ASR::expr_t* array_ref = ASRUtils::EXPR(ASRUtils::make_ArrayItem_t_util(al, arr_expr->base.loc, arr_expr, args.p, args.size(), ASRUtils::type_get_past_array( @@ -169,7 +173,7 @@ namespace LCompilers { array_ref_type = struct_type; } } - ASR::expr_t* array_ref = ASRUtils::EXPR(ASR::make_ArrayItem_t(al, + ASR::expr_t* array_ref = ASRUtils::EXPR(ASRUtils::make_ArrayItem_t_util(al, arr_expr->base.loc, arr_expr, args.p, args.size(), array_ref_type, @@ -198,7 +202,7 @@ namespace LCompilers { empty_dims.reserve(al, 1); ASR::ttype_t* _type = array_section->m_type; _type = ASRUtils::duplicate_type_without_dims(al, _type, loc); - ASR::expr_t* array_ref = ASRUtils::EXPR(ASR::make_ArrayItem_t(al, + ASR::expr_t* array_ref = ASRUtils::EXPR(ASRUtils::make_ArrayItem_t_util(al, loc, array_section->m_v, args.p, args.size(), ASRUtils::type_get_past_array( @@ -223,7 +227,7 @@ namespace LCompilers { empty_dims.reserve(al, 1); _type = ASRUtils::duplicate_type(al, _type, &empty_dims); ASR::expr_t* arr_var = ASRUtils::EXPR(ASR::make_Var_t(al, loc, arr)); - ASR::expr_t* array_ref = ASRUtils::EXPR(ASR::make_ArrayItem_t(al, loc, arr_var, + ASR::expr_t* array_ref = ASRUtils::EXPR(ASRUtils::make_ArrayItem_t_util(al, loc, arr_var, args.p, args.size(), ASRUtils::type_get_past_array( ASRUtils::type_get_past_allocatable(_type)), @@ -633,7 +637,7 @@ namespace LCompilers { Allocator& al, SymbolTable*& current_scope, ASR::stmt_t*& assign_stmt) { ASR::asr_t* expr_sym = ASR::make_Variable_t(al, expr->base.loc, current_scope, s2c(al, name), nullptr, 0, ASR::intentType::Local, nullptr, nullptr, ASR::storage_typeType::Default, - ASRUtils::expr_type(expr), nullptr, ASR::abiType::Source, ASR::accessType::Public, + ASRUtils::duplicate_type(al, ASRUtils::expr_type(expr)), nullptr, ASR::abiType::Source, ASR::accessType::Public, ASR::presenceType::Required, false); if( current_scope->get_symbol(name) == nullptr ) { current_scope->add_symbol(name, ASR::down_cast(expr_sym)); @@ -772,7 +776,7 @@ namespace LCompilers { args.push_back(al, arg4_); arg5_.loc = vector_length->base.loc, arg5_.m_value = vector_length; args.push_back(al, arg5_); - return ASRUtils::STMT(ASR::make_SubroutineCall_t(al, loc, v, + return ASRUtils::STMT(ASRUtils::make_SubroutineCall_t_util(al, loc, v, nullptr, args.p, args.size(), nullptr)); } diff --git a/src/libasr/pass/pass_utils.h b/src/libasr/pass/pass_utils.h index a17cad16811..305f1abc836 100644 --- a/src/libasr/pass/pass_utils.h +++ b/src/libasr/pass/pass_utils.h @@ -479,7 +479,7 @@ namespace LCompilers { Vec empty_dims; empty_dims.reserve(al, 1); array_ref_type = ASRUtils::duplicate_type(al, array_ref_type, &empty_dims); - ASR::expr_t* array_ref = ASRUtils::EXPR(ASR::make_ArrayItem_t(al, arr_var->base.loc, + ASR::expr_t* array_ref = ASRUtils::EXPR(ASRUtils::make_ArrayItem_t_util(al, arr_var->base.loc, arr_var, args.p, args.size(), ASRUtils::type_get_past_allocatable(array_ref_type), ASR::arraystorageType::RowMajor, nullptr)); @@ -646,7 +646,7 @@ namespace LCompilers { empty_dims.reserve(replacer->al, 1); array_ref_type = ASRUtils::duplicate_type(replacer->al, array_ref_type, &empty_dims); - ASR::expr_t* array_ref = ASRUtils::EXPR(ASR::make_ArrayItem_t(replacer->al, + ASR::expr_t* array_ref = ASRUtils::EXPR(ASRUtils::make_ArrayItem_t_util(replacer->al, target_section->base.base.loc, target_section->m_v, args.p, args.size(), diff --git a/src/libasr/pass/print_arr.cpp b/src/libasr/pass/print_arr.cpp index 112b82bbb10..c65d57c7da5 100644 --- a/src/libasr/pass/print_arr.cpp +++ b/src/libasr/pass/print_arr.cpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include namespace LCompilers { diff --git a/src/libasr/pass/print_arr.h b/src/libasr/pass/print_arr.h deleted file mode 100644 index e3914ac31c2..00000000000 --- a/src/libasr/pass/print_arr.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef LFORTRAN_PASS_PRINT_ARR_H -#define LFORTRAN_PASS_PRINT_ARR_H - -#include -#include - -namespace LCompilers { - - void pass_replace_print_arr(Allocator &al, ASR::TranslationUnit_t &unit, - const LCompilers::PassOptions& pass_options); - -} // namespace LCompilers - -#endif // LFORTRAN_PASS_PRINT_ARR_H diff --git a/src/libasr/pass/print_list_tuple.cpp b/src/libasr/pass/print_list_tuple.cpp index 604b1aa62ea..816ef3881d4 100644 --- a/src/libasr/pass/print_list_tuple.cpp +++ b/src/libasr/pass/print_list_tuple.cpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include namespace LCompilers { diff --git a/src/libasr/pass/print_list_tuple.h b/src/libasr/pass/print_list_tuple.h deleted file mode 100644 index 998a1d37d2b..00000000000 --- a/src/libasr/pass/print_list_tuple.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef LFORTRAN_PASS_PRINT_LIST_TUPLE_H -#define LFORTRAN_PASS_PRINT_LIST_TUPLE_H - -#include -#include - -namespace LCompilers { - - void pass_replace_print_list_tuple( - Allocator &al, ASR::TranslationUnit_t &unit, - const LCompilers::PassOptions &pass_options); - -} // namespace LCompilers - -#endif // LFORTRAN_PASS_PRINT_LIST_TUPLE_H diff --git a/src/libasr/pass/print_struct_type.cpp b/src/libasr/pass/print_struct_type.cpp index 2ce6e0e8d01..fe95cc60e26 100644 --- a/src/libasr/pass/print_struct_type.cpp +++ b/src/libasr/pass/print_struct_type.cpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include namespace LCompilers { diff --git a/src/libasr/pass/print_struct_type.h b/src/libasr/pass/print_struct_type.h deleted file mode 100644 index d8d3c3c9e36..00000000000 --- a/src/libasr/pass/print_struct_type.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef LFORTRAN_PASS_PRINT_STRUCT_TYPE_H -#define LFORTRAN_PASS_PRINT_STRUCT_TYPE_H - -#include -#include - -namespace LCompilers { - - void pass_replace_print_struct_type( - Allocator &al, ASR::TranslationUnit_t &unit, - const LCompilers::PassOptions& pass_options); - -} // namespace LCompilers - -#endif // LFORTRAN_PASS_PRINT_STRUCT_TYPE_H diff --git a/src/libasr/pass/replace_arr_slice.h b/src/libasr/pass/replace_arr_slice.h new file mode 100644 index 00000000000..c5e7339ab0b --- /dev/null +++ b/src/libasr/pass/replace_arr_slice.h @@ -0,0 +1,14 @@ +#ifndef LIBASR_PASS_REPLACE_ARR_SLICE_H +#define LIBASR_PASS_REPLACE_ARR_SLICE_H + +#include +#include + +namespace LCompilers { + + void pass_replace_arr_slice(Allocator &al, ASR::TranslationUnit_t &unit, + const PassOptions &pass_options); + +} // namespace LCompilers + +#endif // LIBASR_PASS_REPLACE_ARR_SLICE_H diff --git a/src/libasr/pass/replace_array_op.h b/src/libasr/pass/replace_array_op.h new file mode 100644 index 00000000000..565bba04238 --- /dev/null +++ b/src/libasr/pass/replace_array_op.h @@ -0,0 +1,14 @@ +#ifndef LIBASR_PASS_REPLACE_ARRAY_OP_H +#define LIBASR_PASS_REPLACE_ARRAY_OP_H + +#include +#include + +namespace LCompilers { + + void pass_replace_array_op(Allocator &al, ASR::TranslationUnit_t &unit, + const PassOptions &pass_options); + +} // namespace LCompilers + +#endif // LIBASR_PASS_REPLACE_ARRAY_OP_H diff --git a/src/libasr/pass/replace_class_constructor.h b/src/libasr/pass/replace_class_constructor.h new file mode 100644 index 00000000000..d6ca50aec87 --- /dev/null +++ b/src/libasr/pass/replace_class_constructor.h @@ -0,0 +1,14 @@ +#ifndef LIBASR_PASS_REPLACE_CLASS_CONSTRUCTOR_H +#define LIBASR_PASS_REPLACE_CLASS_CONSTRUCTOR_H + +#include +#include + +namespace LCompilers { + + void pass_replace_class_constructor(Allocator &al, ASR::TranslationUnit_t &unit, + const PassOptions &pass_options); + +} // namespace LCompilers + +#endif // LIBASR_PASS_REPLACE_CLASS_CONSTRUCTOR_H diff --git a/src/libasr/pass/replace_div_to_mul.h b/src/libasr/pass/replace_div_to_mul.h new file mode 100644 index 00000000000..e3e954babc7 --- /dev/null +++ b/src/libasr/pass/replace_div_to_mul.h @@ -0,0 +1,14 @@ +#ifndef LIBASR_PASS_REPLACE_DIV_TO_MUL_H +#define LIBASR_PASS_REPLACE_DIV_TO_MUL_H + +#include +#include + +namespace LCompilers { + + void pass_replace_div_to_mul(Allocator &al, ASR::TranslationUnit_t &unit, + const PassOptions &pass_options); + +} // namespace LCompilers + +#endif // LIBASR_PASS_REPLACE_DIV_TO_MUL_H diff --git a/src/libasr/pass/replace_do_loops.h b/src/libasr/pass/replace_do_loops.h new file mode 100644 index 00000000000..10d78fedeb1 --- /dev/null +++ b/src/libasr/pass/replace_do_loops.h @@ -0,0 +1,14 @@ +#ifndef LIBASR_PASS_REPLACE_DO_LOOPS_H +#define LIBASR_PASS_REPLACE_DO_LOOPS_H + +#include +#include + +namespace LCompilers { + + void pass_replace_do_loops(Allocator &al, ASR::TranslationUnit_t &unit, + const PassOptions &pass_options); + +} // namespace LCompilers + +#endif // LIBASR_PASS_REPLACE_DO_LOOPS_H diff --git a/src/libasr/pass/replace_flip_sign.h b/src/libasr/pass/replace_flip_sign.h new file mode 100644 index 00000000000..5d814a7a099 --- /dev/null +++ b/src/libasr/pass/replace_flip_sign.h @@ -0,0 +1,14 @@ +#ifndef LIBASR_PASS_REPLACE_FLIP_SIGN_H +#define LIBASR_PASS_REPLACE_FLIP_SIGN_H + +#include +#include + +namespace LCompilers { + + void pass_replace_flip_sign(Allocator &al, ASR::TranslationUnit_t &unit, + const PassOptions &pass_options); + +} // namespace LCompilers + +#endif // LIBASR_PASS_REPLACE_FLIP_SIGN_H diff --git a/src/libasr/pass/fma.h b/src/libasr/pass/replace_fma.h similarity index 50% rename from src/libasr/pass/fma.h rename to src/libasr/pass/replace_fma.h index 1b698e84bbf..36d5fbfa378 100644 --- a/src/libasr/pass/fma.h +++ b/src/libasr/pass/replace_fma.h @@ -1,5 +1,5 @@ -#ifndef LIBASR_PASS_FMA_H -#define LIBASR_PASS_FMA_H +#ifndef LIBASR_PASS_REPLACE_FMA_H +#define LIBASR_PASS_REPLACE_FMA_H #include #include @@ -7,8 +7,8 @@ namespace LCompilers { void pass_replace_fma(Allocator &al, ASR::TranslationUnit_t &unit, - const LCompilers::PassOptions& pass_options); + const PassOptions &pass_options); } // namespace LCompilers -#endif // LIBASR_PASS_FMA_H +#endif // LIBASR_PASS_REPLACE_FMA_H diff --git a/src/libasr/pass/replace_for_all.h b/src/libasr/pass/replace_for_all.h new file mode 100644 index 00000000000..81da30938cf --- /dev/null +++ b/src/libasr/pass/replace_for_all.h @@ -0,0 +1,14 @@ +#ifndef LIBASR_PASS_REPLACE_FOR_ALL_H +#define LIBASR_PASS_REPLACE_FOR_ALL_H + +#include +#include + +namespace LCompilers { + + void pass_replace_for_all(Allocator &al, ASR::TranslationUnit_t &unit, + const PassOptions &pass_options); + +} // namespace LCompilers + +#endif // LIBASR_PASS_REPLACE_FOR_ALL_H diff --git a/src/libasr/pass/replace_implied_do_loops.h b/src/libasr/pass/replace_implied_do_loops.h new file mode 100644 index 00000000000..dc4f0bd6fd7 --- /dev/null +++ b/src/libasr/pass/replace_implied_do_loops.h @@ -0,0 +1,14 @@ +#ifndef LIBASR_PASS_REPLACE_IMPLIED_DO_LOOPS_H +#define LIBASR_PASS_REPLACE_IMPLIED_DO_LOOPS_H + +#include +#include + +namespace LCompilers { + + void pass_replace_implied_do_loops(Allocator &al, ASR::TranslationUnit_t &unit, + const PassOptions &pass_options); + +} // namespace LCompilers + +#endif // LIBASR_PASS_REPLACE_IMPLIED_DO_LOOPS_H diff --git a/src/libasr/pass/replace_init_expr.h b/src/libasr/pass/replace_init_expr.h new file mode 100644 index 00000000000..9b31a747c24 --- /dev/null +++ b/src/libasr/pass/replace_init_expr.h @@ -0,0 +1,14 @@ +#ifndef LIBASR_PASS_REPLACE_INIT_EXPR_H +#define LIBASR_PASS_REPLACE_INIT_EXPR_H + +#include +#include + +namespace LCompilers { + + void pass_replace_init_expr(Allocator &al, ASR::TranslationUnit_t &unit, + const PassOptions &pass_options); + +} // namespace LCompilers + +#endif // LIBASR_PASS_REPLACE_INIT_EXPR_H diff --git a/src/libasr/pass/replace_intrinsic_function.h b/src/libasr/pass/replace_intrinsic_function.h new file mode 100644 index 00000000000..b2c68652659 --- /dev/null +++ b/src/libasr/pass/replace_intrinsic_function.h @@ -0,0 +1,14 @@ +#ifndef LIBASR_PASS_REPLACE_INTRINSIC_FUNCTION_H +#define LIBASR_PASS_REPLACE_INTRINSIC_FUNCTION_H + +#include +#include + +namespace LCompilers { + + void pass_replace_intrinsic_function(Allocator &al, ASR::TranslationUnit_t &unit, + const PassOptions &pass_options); + +} // namespace LCompilers + +#endif // LIBASR_PASS_REPLACE_INTRINSIC_FUNCTION_H diff --git a/src/libasr/pass/replace_param_to_const.h b/src/libasr/pass/replace_param_to_const.h new file mode 100644 index 00000000000..34f20244166 --- /dev/null +++ b/src/libasr/pass/replace_param_to_const.h @@ -0,0 +1,14 @@ +#ifndef LIBASR_PASS_REPLACE_PARAM_TO_CONST_H +#define LIBASR_PASS_REPLACE_PARAM_TO_CONST_H + +#include +#include + +namespace LCompilers { + + void pass_replace_param_to_const(Allocator &al, ASR::TranslationUnit_t &unit, + const PassOptions &pass_options); + +} // namespace LCompilers + +#endif // LIBASR_PASS_REPLACE_PARAM_TO_CONST_H diff --git a/src/libasr/pass/replace_print_arr.h b/src/libasr/pass/replace_print_arr.h new file mode 100644 index 00000000000..edd81465aaf --- /dev/null +++ b/src/libasr/pass/replace_print_arr.h @@ -0,0 +1,14 @@ +#ifndef LIBASR_PASS_REPLACE_PRINT_ARR_H +#define LIBASR_PASS_REPLACE_PRINT_ARR_H + +#include +#include + +namespace LCompilers { + + void pass_replace_print_arr(Allocator &al, ASR::TranslationUnit_t &unit, + const PassOptions &pass_options); + +} // namespace LCompilers + +#endif // LIBASR_PASS_REPLACE_PRINT_ARR_H diff --git a/src/libasr/pass/replace_print_list_tuple.h b/src/libasr/pass/replace_print_list_tuple.h new file mode 100644 index 00000000000..f8a97559942 --- /dev/null +++ b/src/libasr/pass/replace_print_list_tuple.h @@ -0,0 +1,14 @@ +#ifndef LIBASR_PASS_REPLACE_PRINT_LIST_TUPLE_H +#define LIBASR_PASS_REPLACE_PRINT_LIST_TUPLE_H + +#include +#include + +namespace LCompilers { + + void pass_replace_print_list_tuple(Allocator &al, ASR::TranslationUnit_t &unit, + const PassOptions &pass_options); + +} // namespace LCompilers + +#endif // LIBASR_PASS_REPLACE_PRINT_LIST_TUPLE_H diff --git a/src/libasr/pass/replace_print_struct_type.h b/src/libasr/pass/replace_print_struct_type.h new file mode 100644 index 00000000000..3447111ab15 --- /dev/null +++ b/src/libasr/pass/replace_print_struct_type.h @@ -0,0 +1,14 @@ +#ifndef LIBASR_PASS_REPLACE_PRINT_STRUCT_TYPE_H +#define LIBASR_PASS_REPLACE_PRINT_STRUCT_TYPE_H + +#include +#include + +namespace LCompilers { + + void pass_replace_print_struct_type(Allocator &al, ASR::TranslationUnit_t &unit, + const PassOptions &pass_options); + +} // namespace LCompilers + +#endif // LIBASR_PASS_REPLACE_PRINT_STRUCT_TYPE_H diff --git a/src/libasr/pass/replace_select_case.h b/src/libasr/pass/replace_select_case.h new file mode 100644 index 00000000000..8e6820ea0c0 --- /dev/null +++ b/src/libasr/pass/replace_select_case.h @@ -0,0 +1,14 @@ +#ifndef LIBASR_PASS_REPLACE_SELECT_CASE_H +#define LIBASR_PASS_REPLACE_SELECT_CASE_H + +#include +#include + +namespace LCompilers { + + void pass_replace_select_case(Allocator &al, ASR::TranslationUnit_t &unit, + const PassOptions &pass_options); + +} // namespace LCompilers + +#endif // LIBASR_PASS_REPLACE_SELECT_CASE_H diff --git a/src/libasr/pass/replace_sign_from_value.h b/src/libasr/pass/replace_sign_from_value.h new file mode 100644 index 00000000000..c2ac5245a0c --- /dev/null +++ b/src/libasr/pass/replace_sign_from_value.h @@ -0,0 +1,14 @@ +#ifndef LIBASR_PASS_REPLACE_SIGN_FROM_VALUE_H +#define LIBASR_PASS_REPLACE_SIGN_FROM_VALUE_H + +#include +#include + +namespace LCompilers { + + void pass_replace_sign_from_value(Allocator &al, ASR::TranslationUnit_t &unit, + const PassOptions &pass_options); + +} // namespace LCompilers + +#endif // LIBASR_PASS_REPLACE_SIGN_FROM_VALUE_H diff --git a/src/libasr/pass/replace_where.h b/src/libasr/pass/replace_where.h new file mode 100644 index 00000000000..08e3a440e0b --- /dev/null +++ b/src/libasr/pass/replace_where.h @@ -0,0 +1,14 @@ +#ifndef LIBASR_PASS_REPLACE_WHERE_H +#define LIBASR_PASS_REPLACE_WHERE_H + +#include +#include + +namespace LCompilers { + + void pass_replace_where(Allocator &al, ASR::TranslationUnit_t &unit, + const PassOptions &pass_options); + +} // namespace LCompilers + +#endif // LIBASR_PASS_REPLACE_WHERE_H diff --git a/src/libasr/pass/select_case.cpp b/src/libasr/pass/select_case.cpp index 1c5c452fd78..d5cd5e0b06b 100644 --- a/src/libasr/pass/select_case.cpp +++ b/src/libasr/pass/select_case.cpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include namespace LCompilers { diff --git a/src/libasr/pass/select_case.h b/src/libasr/pass/select_case.h deleted file mode 100644 index c560af5ff95..00000000000 --- a/src/libasr/pass/select_case.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef LFORTRAN_PASS_SELECT_CASE_H -#define LFORTRAN_PASS_SELECT_CASE_H - -#include -#include - -namespace LCompilers { - - void pass_replace_select_case(Allocator &al, ASR::TranslationUnit_t &unit, - const LCompilers::PassOptions& pass_options); - -} // namespace LCompilers - -#endif // LFORTRAN_PASS_SELECT_CASE_H diff --git a/src/libasr/pass/sign_from_value.cpp b/src/libasr/pass/sign_from_value.cpp index 141ce60c0c2..163b8703417 100644 --- a/src/libasr/pass/sign_from_value.cpp +++ b/src/libasr/pass/sign_from_value.cpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/libasr/pass/sign_from_value.h b/src/libasr/pass/sign_from_value.h deleted file mode 100644 index 28ead181595..00000000000 --- a/src/libasr/pass/sign_from_value.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef LIBASR_PASS_SIGN_FROM_VALUE_H -#define LIBASR_PASS_SIGN_FROM_VALUE_H - -#include -#include - -namespace LCompilers { - - void pass_replace_sign_from_value(Allocator &al, ASR::TranslationUnit_t &unit, - const LCompilers::PassOptions& pass_options); - -} // namespace LCompilers - -#endif // LIBASR_PASS_SIGN_FROM_VALUE_H diff --git a/src/libasr/pass/subroutine_from_function.cpp b/src/libasr/pass/subroutine_from_function.cpp index 68f55fd5529..ceea9cc5947 100644 --- a/src/libasr/pass/subroutine_from_function.cpp +++ b/src/libasr/pass/subroutine_from_function.cpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include #include @@ -15,11 +15,11 @@ namespace LCompilers { using ASR::down_cast; using ASR::is_a; -class CreateSubroutineFromFunction: public PassUtils::PassVisitor { +class CreateFunctionFromSubroutine: public PassUtils::PassVisitor { public: - CreateSubroutineFromFunction(Allocator &al_) : + CreateFunctionFromSubroutine(Allocator &al_) : PassVisitor(al_, nullptr) { pass_result.reserve(al, 1); @@ -157,7 +157,7 @@ class ReplaceFunctionCallWithSubroutineCall: result_arg.loc = result_var->base.loc; result_arg.m_value = result_var; s_args.push_back(al, result_arg); - ASR::stmt_t* subrout_call = ASRUtils::STMT(ASR::make_SubroutineCall_t( + ASR::stmt_t* subrout_call = ASRUtils::STMT(ASRUtils::make_SubroutineCall_t_util( al, x->base.base.loc, x->m_name, nullptr, s_args.p, s_args.size(), nullptr)); pass_result.push_back(al, subrout_call); result_var = nullptr; @@ -227,7 +227,7 @@ class ReplaceFunctionCallWithSubroutineCallVisitor: void pass_create_subroutine_from_function(Allocator &al, ASR::TranslationUnit_t &unit, const LCompilers::PassOptions& /*pass_options*/) { - CreateSubroutineFromFunction v(al); + CreateFunctionFromSubroutine v(al); v.visit_TranslationUnit(unit); ReplaceFunctionCallWithSubroutineCallVisitor u(al); u.visit_TranslationUnit(unit); diff --git a/src/libasr/pass/subroutine_from_function.h b/src/libasr/pass/subroutine_from_function.h deleted file mode 100644 index ee3789462c0..00000000000 --- a/src/libasr/pass/subroutine_from_function.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef LIBASR_PASS_SUBROUTINE_FROM_FUNCTION_H -#define LIBASR_PASS_SUBROUTINE_FROM_FUNCTION_H - -#include -#include - -namespace LCompilers { - - void pass_create_subroutine_from_function(Allocator &al, ASR::TranslationUnit_t &unit, - const LCompilers::PassOptions& pass_options); - -} // namespace LCompilers - -#endif // LIBASR_PASS_SUBROUTINE_FROM_FUNCTION_H diff --git a/src/libasr/pass/transform_optional_argument_functions.cpp b/src/libasr/pass/transform_optional_argument_functions.cpp index 0c0c5c01ef8..b9813d21808 100644 --- a/src/libasr/pass/transform_optional_argument_functions.cpp +++ b/src/libasr/pass/transform_optional_argument_functions.cpp @@ -88,11 +88,14 @@ class TransformFunctionsWithOptionalArguments: public PassUtils::PassVisitor new_args; + Vec new_arg_types; + new_arg_types.reserve(al, s->n_args); new_args.reserve(al, s->n_args); ASR::ttype_t* logical_type = ASRUtils::TYPE(ASR::make_Logical_t(al, s->base.base.loc, 4)); for( size_t i = 0; i < s->n_args; i++ ) { ASR::symbol_t* arg_sym = ASR::down_cast(s->m_args[i])->m_v; new_args.push_back(al, s->m_args[i]); + new_arg_types.push_back(al, ASRUtils::get_FunctionType(*s)->m_arg_types[i]); if( is_presence_optional(arg_sym) ) { std::string presence_bit_arg_name = "is_" + std::string(ASRUtils::symbol_name(arg_sym)) + "_present_"; presence_bit_arg_name = s->m_symtab->get_unique_name(presence_bit_arg_name); @@ -100,8 +103,13 @@ class TransformFunctionsWithOptionalArguments: public PassUtils::PassVisitorbase.loc, presence_bit_arg_name, al, s->m_symtab, logical_type, ASR::intentType::In); new_args.push_back(al, presence_bit_arg); + new_arg_types.push_back(al, logical_type); } } + + ASR::FunctionType_t* function_type = ASRUtils::get_FunctionType(*s); + function_type->m_arg_types = new_arg_types.p; + function_type->n_arg_types = new_arg_types.size(); s->m_args = new_args.p; s->n_args = new_args.size(); ReplacePresentCallsVisitor present_replacer(al, s); @@ -234,7 +242,13 @@ class TransformFunctionsWithOptionalArguments: public PassUtils::PassVisitor -bool fill_new_args(Vec& new_args, Allocator& al, const T& x) { +bool fill_new_args(Vec& new_args, Allocator& al, const T& x, SymbolTable* scope) { + ASR::Function_t* owning_function = nullptr; + if( scope->asr_owner && ASR::is_a(*scope->asr_owner) && + ASR::is_a(*ASR::down_cast(scope->asr_owner)) ) { + owning_function = ASR::down_cast( + ASR::down_cast(scope->asr_owner)); + } ASR::symbol_t* func_sym = ASRUtils::symbol_get_past_external(x.m_name); if( !ASR::is_a(*func_sym) ) { return false; @@ -266,9 +280,38 @@ bool fill_new_args(Vec& new_args, Allocator& al, const T& x) { ASR::presenceType::Optional ) { ASR::ttype_t* logical_t = ASRUtils::TYPE(ASR::make_Logical_t(al, x.m_args[i].loc, 4)); - ASR::expr_t* is_present = ASRUtils::EXPR( - ASR::make_LogicalConstant_t(al, x.m_args[i].loc, - x.m_args[i].m_value != nullptr, logical_t)); + ASR::expr_t* is_present = nullptr; + if( x.m_args[i].m_value == nullptr ) { + is_present = ASRUtils::EXPR(ASR::make_LogicalConstant_t( + al, x.m_args[i].loc, false, logical_t)); + } else { + if( ASR::is_a(*x.m_args[i].m_value) && + ASR::is_a( + *ASR::down_cast(x.m_args[i].m_value)->m_v) && + ASRUtils::EXPR2VAR(x.m_args[i].m_value)->m_presence == + ASR::presenceType::Optional) { + if( owning_function == nullptr ) { + LCOMPILERS_ASSERT(false); + } + + size_t k; + bool k_found = false; + for( k = 0; k < owning_function->n_args; k++ ) { + if( ASR::down_cast(owning_function->m_args[k])->m_v == + ASR::down_cast(x.m_args[i].m_value)->m_v ) { + k_found = true; + break ; + } + } + + if( k_found ) { + is_present = owning_function->m_args[k + 1]; + } + } else { + is_present = ASRUtils::EXPR(ASR::make_LogicalConstant_t( + al, x.m_args[i].loc, true, logical_t)); + } + } ASR::call_arg_t present_arg; present_arg.loc = x.m_args[i].loc; present_arg.m_value = is_present; @@ -288,15 +331,18 @@ class ReplaceFunctionCallsWithOptionalArguments: public ASR::BaseExprReplacer new_args; - if( !fill_new_args(new_args, al, *x) ) { + if( !fill_new_args(new_args, al, *x, current_scope) ) { return ; } - *current_expr = ASRUtils::EXPR(ASR::make_FunctionCall_t(al, + *current_expr = ASRUtils::EXPR(ASRUtils::make_FunctionCall_t_util(al, x->base.base.loc, x->m_name, x->m_original_name, new_args.p, new_args.size(), x->m_type, x->m_value, x->m_dt)); @@ -317,6 +363,7 @@ class ReplaceFunctionCallsWithOptionalArgumentsVisitor : public ASR::CallReplace void call_replacer() { replacer.current_expr = current_expr; + replacer.current_scope = current_scope; replacer.replace_expr(*current_expr); } @@ -334,10 +381,10 @@ class ReplaceSubroutineCallsWithOptionalArgumentsVisitor : public PassUtils::Pas void visit_SubroutineCall(const ASR::SubroutineCall_t& x) { Vec new_args; - if( !fill_new_args(new_args, al, x) ) { + if( !fill_new_args(new_args, al, x, current_scope) ) { return ; } - pass_result.push_back(al, ASRUtils::STMT(ASR::make_SubroutineCall_t(al, + pass_result.push_back(al, ASRUtils::STMT(ASRUtils::make_SubroutineCall_t_util(al, x.base.base.loc, x.m_name, x.m_original_name, new_args.p, new_args.size(), x.m_dt))); } diff --git a/src/libasr/pass/transform_optional_argument_functions.h b/src/libasr/pass/transform_optional_argument_functions.h index 647227b3256..957524fbddf 100644 --- a/src/libasr/pass/transform_optional_argument_functions.h +++ b/src/libasr/pass/transform_optional_argument_functions.h @@ -1,16 +1,14 @@ -#ifndef LFORTRAN_PASS_TRANSFORM_OPTIONAL_ARGUMENT_FUNCTIONS -#define LFORTRAN_PASS_TRANSFORM_OPTIONAL_ARGUMENT_FUNCTIONS +#ifndef LIBASR_PASS_TRANSFORM_OPTIONAL_ARGUMENT_FUNCTIONS_H +#define LIBASR_PASS_TRANSFORM_OPTIONAL_ARGUMENT_FUNCTIONS_H #include #include namespace LCompilers { - void pass_transform_optional_argument_functions( - Allocator &al, ASR::TranslationUnit_t &unit, - const LCompilers::PassOptions& pass_options - ); + void pass_transform_optional_argument_functions(Allocator &al, ASR::TranslationUnit_t &unit, + const PassOptions &pass_options); -} // namespace LFortran +} // namespace LCompilers -#endif // LFORTRAN_TRANSFORM_OPTIONAL_ARGUMENT_FUNCTIONS +#endif // LIBASR_PASS_TRANSFORM_OPTIONAL_ARGUMENT_FUNCTIONS_H diff --git a/src/libasr/pass/unused_functions.h b/src/libasr/pass/unused_functions.h index 788932539b7..d3cea9f4bc3 100644 --- a/src/libasr/pass/unused_functions.h +++ b/src/libasr/pass/unused_functions.h @@ -1,5 +1,5 @@ -#ifndef LFORTRAN_PASS_UNUSED_FUNCTIONS_H -#define LFORTRAN_PASS_UNUSED_FUNCTIONS_H +#ifndef LIBASR_PASS_UNUSED_FUNCTIONS_H +#define LIBASR_PASS_UNUSED_FUNCTIONS_H #include #include @@ -7,8 +7,8 @@ namespace LCompilers { void pass_unused_functions(Allocator &al, ASR::TranslationUnit_t &unit, - const LCompilers::PassOptions& pass_options); + const PassOptions &pass_options); } // namespace LCompilers -#endif // LFORTRAN_PASS_UNUSED_FUNCTIONS_H +#endif // LIBASR_PASS_UNUSED_FUNCTIONS_H diff --git a/src/libasr/pass/update_array_dim_intrinsic_calls.h b/src/libasr/pass/update_array_dim_intrinsic_calls.h index 0e6df1ad80a..dfd410e0a01 100644 --- a/src/libasr/pass/update_array_dim_intrinsic_calls.h +++ b/src/libasr/pass/update_array_dim_intrinsic_calls.h @@ -1,5 +1,5 @@ -#ifndef LFORTRAN_PASS_UPDATE_ARRAY_DIM_H -#define LFORTRAN_PASS_UPDATE_ARRAY_DIM_H +#ifndef LIBASR_PASS_UPDATE_ARRAY_DIM_INTRINSIC_CALLS_H +#define LIBASR_PASS_UPDATE_ARRAY_DIM_INTRINSIC_CALLS_H #include #include @@ -7,8 +7,8 @@ namespace LCompilers { void pass_update_array_dim_intrinsic_calls(Allocator &al, ASR::TranslationUnit_t &unit, - const LCompilers::PassOptions& pass_options); + const PassOptions &pass_options); } // namespace LCompilers -#endif // LFORTRAN_PASS_UPDATE_ARRAY_DIM_H +#endif // LIBASR_PASS_UPDATE_ARRAY_DIM_INTRINSIC_CALLS_H diff --git a/src/libasr/pass/where.cpp b/src/libasr/pass/where.cpp index d4f57b32d5e..e1ad88c7fc7 100644 --- a/src/libasr/pass/where.cpp +++ b/src/libasr/pass/where.cpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include namespace LCompilers { @@ -62,6 +62,13 @@ class ReplaceVar : public ASR::BaseExprReplacer } } + void replace_ArrayPhysicalCast(ASR::ArrayPhysicalCast_t* x) { + ASR::BaseExprReplacer::replace_ArrayPhysicalCast(x); + if( !ASRUtils::is_array(ASRUtils::expr_type(x->m_arg)) ) { + *current_expr = x->m_arg; + } + } + void replace_FunctionCall(ASR::FunctionCall_t* x) { uint64_t h = get_hash((ASR::asr_t*) x->m_name); if (return_var_hash.find(h) != return_var_hash.end()) { @@ -99,7 +106,7 @@ class ReplaceVar : public ASR::BaseExprReplacer args.push_back(al, *current_expr); } ASR::ttype_t* type = ASRUtils::expr_type(args[0]); - ASR::expr_t* new_expr = ASRUtils::EXPR(ASR::make_IntrinsicFunction_t(al, x->base.base.loc, x->m_intrinsic_id, args.p, x->n_args, x->m_overload_id, type, x->m_value)); + ASR::expr_t* new_expr = ASRUtils::EXPR(ASRUtils::make_IntrinsicFunction_t_util(al, x->base.base.loc, x->m_intrinsic_id, args.p, x->n_args, x->m_overload_id, type, x->m_value)); *current_expr = new_expr; } diff --git a/src/libasr/pass/where.h b/src/libasr/pass/where.h deleted file mode 100644 index d746f03ab12..00000000000 --- a/src/libasr/pass/where.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef LFORTRAN_PASS_WHERE_H -#define LFORTRAN_PASS_WHERE_H - -#include -#include - -namespace LCompilers { - - void pass_replace_where(Allocator &al, ASR::TranslationUnit_t &unit, const LCompilers::PassOptions& pass_options); - -} // namespace LCompilers - -#endif // LFORTRAN_PASS_WHERE_H diff --git a/src/libasr/pass/wrap_global_stmts.h b/src/libasr/pass/wrap_global_stmts.h new file mode 100644 index 00000000000..d9347d6b618 --- /dev/null +++ b/src/libasr/pass/wrap_global_stmts.h @@ -0,0 +1,14 @@ +#ifndef LIBASR_PASS_WRAP_GLOBAL_STMTS_H +#define LIBASR_PASS_WRAP_GLOBAL_STMTS_H + +#include +#include + +namespace LCompilers { + + void pass_wrap_global_stmts(Allocator &al, ASR::TranslationUnit_t &unit, + const PassOptions &pass_options); + +} // namespace LCompilers + +#endif // LIBASR_PASS_WRAP_GLOBAL_STMTS_H diff --git a/src/libasr/pass/wrap_global_stmts_program.h b/src/libasr/pass/wrap_global_stmts_program.h new file mode 100644 index 00000000000..7844386a473 --- /dev/null +++ b/src/libasr/pass/wrap_global_stmts_program.h @@ -0,0 +1,14 @@ +#ifndef LIBASR_PASS_WRAP_GLOBAL_STMTS_PROGRAM_H +#define LIBASR_PASS_WRAP_GLOBAL_STMTS_PROGRAM_H + +#include +#include + +namespace LCompilers { + + void pass_wrap_global_stmts_program(Allocator &al, ASR::TranslationUnit_t &unit, + const PassOptions &pass_options); + +} // namespace LCompilers + +#endif // LIBASR_PASS_WRAP_GLOBAL_STMTS_PROGRAM_H diff --git a/src/libasr/pass/wrap_global_symbols.h b/src/libasr/pass/wrap_global_symbols.h new file mode 100644 index 00000000000..225be2b965f --- /dev/null +++ b/src/libasr/pass/wrap_global_symbols.h @@ -0,0 +1,14 @@ +#ifndef LIBASR_PASS_WRAP_GLOBAL_SYMBOLS_H +#define LIBASR_PASS_WRAP_GLOBAL_SYMBOLS_H + +#include +#include + +namespace LCompilers { + + void pass_wrap_global_symbols(Allocator &al, ASR::TranslationUnit_t &unit, + const PassOptions &pass_options); + +} // namespace LCompilers + +#endif // LIBASR_PASS_WRAP_GLOBAL_SYMBOLS_H diff --git a/src/libasr/utils.h b/src/libasr/utils.h index a0b0c004511..e19e0e3ae41 100644 --- a/src/libasr/utils.h +++ b/src/libasr/utils.h @@ -20,6 +20,8 @@ enum Platform { std::string pf2s(Platform); Platform get_platform(); +std::string get_unique_ID(); + struct CompilerOptions { std::filesystem::path mod_files_dir; std::vector include_dirs; diff --git a/src/libasr/utils2.cpp b/src/libasr/utils2.cpp index 62cabe162d8..51a2a3c5f4d 100644 --- a/src/libasr/utils2.cpp +++ b/src/libasr/utils2.cpp @@ -4,6 +4,8 @@ #endif #include +#include +#include #include #include @@ -11,6 +13,19 @@ namespace LCompilers { +std::string get_unique_ID() { + static std::random_device dev; + static std::mt19937 rng(dev()); + std::uniform_int_distribution dist(0, 61); + const std::string v = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + std::string res; + for (int i = 0; i < 22; i++) { + res += v[dist(rng)]; + } + return res; +} + bool read_file(const std::string &filename, std::string &text) { std::ifstream ifs(filename.c_str(), std::ios::in | std::ios::binary diff --git a/src/lpython/semantics/python_ast_to_asr.cpp b/src/lpython/semantics/python_ast_to_asr.cpp index 2719e01fd89..947d870e98a 100644 --- a/src/lpython/semantics/python_ast_to_asr.cpp +++ b/src/lpython/semantics/python_ast_to_asr.cpp @@ -17,9 +17,9 @@ #include #include #include -#include +#include #include -#include +#include #include #include @@ -72,7 +72,8 @@ namespace CastingUtil { const std::map& kind_rules = { {ASR::ttypeType::Complex, ASR::cast_kindType::ComplexToComplex}, {ASR::ttypeType::Real, ASR::cast_kindType::RealToReal}, - {ASR::ttypeType::Integer, ASR::cast_kindType::IntegerToInteger} + {ASR::ttypeType::Integer, ASR::cast_kindType::IntegerToInteger}, + {ASR::ttypeType::UnsignedInteger, ASR::cast_kindType::UnsignedIntegerToUnsignedInteger} }; int get_type_priority(ASR::ttypeType type) { @@ -713,7 +714,8 @@ class CommonVisitor : public AST::BaseVisitor { ASRUtils::ExprStmtDuplicator expr_duplicator(al); expr_duplicator.allow_procedure_calls = true; ASRUtils::ReplaceArgVisitor arg_replacer(al, current_scope, orig_func, - orig_args, dependencies); + orig_args, dependencies, + current_module_dependencies); for( size_t i = 0; i < exprs.size(); i++ ) { ASR::expr_t* expri = exprs[i]; if (expri) { @@ -1008,7 +1010,8 @@ class CommonVisitor : public AST::BaseVisitor { ASR::ttype_t* get_type_from_var_annotation(std::string var_annotation, const Location& loc, Vec& dims, AST::expr_t** m_args=nullptr, size_t n_args=0, - bool raise_error=true) { + bool raise_error=true, ASR::abiType abi=ASR::abiType::Source, + bool is_argument=false) { ASR::ttype_t* type = nullptr; ASR::symbol_t *s = current_scope->resolve_symbol(var_annotation); if (s) { @@ -1017,65 +1020,65 @@ class CommonVisitor : public AST::BaseVisitor { if (var_sym->m_type->type == ASR::ttypeType::TypeParameter) { ASR::TypeParameter_t *type_param = ASR::down_cast(var_sym->m_type); type = ASRUtils::TYPE(ASR::make_TypeParameter_t(al, loc, type_param->m_param)); - return ASRUtils::make_Array_t_util(al, loc, type, dims.p, dims.size()); + return ASRUtils::make_Array_t_util(al, loc, type, dims.p, dims.size(), abi, is_argument); } } else { ASR::symbol_t *der_sym = ASRUtils::symbol_get_past_external(s); if( der_sym ) { if ( ASR::is_a(*der_sym) ) { type = ASRUtils::TYPE(ASR::make_Struct_t(al, loc, s)); - return ASRUtils::make_Array_t_util(al, loc, type, dims.p, dims.size()); + return ASRUtils::make_Array_t_util(al, loc, type, dims.p, dims.size(), abi, is_argument); } else if( ASR::is_a(*der_sym) ) { type = ASRUtils::TYPE(ASR::make_Enum_t(al, loc, s)); - return ASRUtils::make_Array_t_util(al, loc, type, dims.p, dims.size()); + return ASRUtils::make_Array_t_util(al, loc, type, dims.p, dims.size(), abi, is_argument); } else if( ASR::is_a(*der_sym) ) { type = ASRUtils::TYPE(ASR::make_Union_t(al, loc, s)); - return ASRUtils::make_Array_t_util(al, loc, type, dims.p, dims.size()); + return ASRUtils::make_Array_t_util(al, loc, type, dims.p, dims.size(), abi, is_argument); } } } } else if (var_annotation == "i8") { type = ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 1)); - type = ASRUtils::make_Array_t_util(al, loc, type, dims.p, dims.size()); + type = ASRUtils::make_Array_t_util(al, loc, type, dims.p, dims.size(), abi, is_argument); } else if (var_annotation == "i16") { type = ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 2)); - type = ASRUtils::make_Array_t_util(al, loc, type, dims.p, dims.size()); + type = ASRUtils::make_Array_t_util(al, loc, type, dims.p, dims.size(), abi, is_argument); } else if (var_annotation == "i32") { type = ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)); - type = ASRUtils::make_Array_t_util(al, loc, type, dims.p, dims.size()); + type = ASRUtils::make_Array_t_util(al, loc, type, dims.p, dims.size(), abi, is_argument); } else if (var_annotation == "i64") { type = ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 8)); - type = ASRUtils::make_Array_t_util(al, loc, type, dims.p, dims.size()); + type = ASRUtils::make_Array_t_util(al, loc, type, dims.p, dims.size(), abi, is_argument); } else if (var_annotation == "u8") { type = ASRUtils::TYPE(ASR::make_UnsignedInteger_t(al, loc, 1)); - type = ASRUtils::make_Array_t_util(al, loc, type, dims.p, dims.size()); + type = ASRUtils::make_Array_t_util(al, loc, type, dims.p, dims.size(), abi, is_argument); } else if (var_annotation == "u16") { type = ASRUtils::TYPE(ASR::make_UnsignedInteger_t(al, loc, 2)); - type = ASRUtils::make_Array_t_util(al, loc, type, dims.p, dims.size()); + type = ASRUtils::make_Array_t_util(al, loc, type, dims.p, dims.size(), abi, is_argument); } else if (var_annotation == "u32") { type = ASRUtils::TYPE(ASR::make_UnsignedInteger_t(al, loc, 4)); - type = ASRUtils::make_Array_t_util(al, loc, type, dims.p, dims.size()); + type = ASRUtils::make_Array_t_util(al, loc, type, dims.p, dims.size(), abi, is_argument); } else if (var_annotation == "u64") { type = ASRUtils::TYPE(ASR::make_UnsignedInteger_t(al, loc, 8)); - type = ASRUtils::make_Array_t_util(al, loc, type, dims.p, dims.size()); + type = ASRUtils::make_Array_t_util(al, loc, type, dims.p, dims.size(), abi, is_argument); } else if (var_annotation == "f32") { type = ASRUtils::TYPE(ASR::make_Real_t(al, loc, 4)); - type = ASRUtils::make_Array_t_util(al, loc, type, dims.p, dims.size()); + type = ASRUtils::make_Array_t_util(al, loc, type, dims.p, dims.size(), abi, is_argument); } else if (var_annotation == "f64") { type = ASRUtils::TYPE(ASR::make_Real_t(al, loc, 8)); - type = ASRUtils::make_Array_t_util(al, loc, type, dims.p, dims.size()); + type = ASRUtils::make_Array_t_util(al, loc, type, dims.p, dims.size(), abi, is_argument); } else if (var_annotation == "c32") { type = ASRUtils::TYPE(ASR::make_Complex_t(al, loc, 4)); - type = ASRUtils::make_Array_t_util(al, loc, type, dims.p, dims.size()); + type = ASRUtils::make_Array_t_util(al, loc, type, dims.p, dims.size(), abi, is_argument); } else if (var_annotation == "c64") { type = ASRUtils::TYPE(ASR::make_Complex_t(al, loc, 8)); - type = ASRUtils::make_Array_t_util(al, loc, type, dims.p, dims.size()); + type = ASRUtils::make_Array_t_util(al, loc, type, dims.p, dims.size(), abi, is_argument); } else if (var_annotation == "str") { type = ASRUtils::TYPE(ASR::make_Character_t(al, loc, 1, -2, nullptr)); - type = ASRUtils::make_Array_t_util(al, loc, type, dims.p, dims.size()); + type = ASRUtils::make_Array_t_util(al, loc, type, dims.p, dims.size(), abi, is_argument); } else if (var_annotation == "bool" || var_annotation == "i1") { type = ASRUtils::TYPE(ASR::make_Logical_t(al, loc, 4)); - type = ASRUtils::make_Array_t_util(al, loc, type, dims.p, dims.size()); + type = ASRUtils::make_Array_t_util(al, loc, type, dims.p, dims.size(), abi, is_argument); } else if (var_annotation == "CPtr") { type = ASRUtils::TYPE(ASR::make_CPtr_t(al, loc)); } else if (var_annotation == "pointer") { @@ -1255,7 +1258,7 @@ class CommonVisitor : public AST::BaseVisitor { visit_expr_list_with_cast(func->m_args, func->n_args, args_new, args, !ASRUtils::is_intrinsic_function2(func)); dependencies.push_back(al, ASRUtils::symbol_name(stemp)); - ASR::asr_t* func_call_asr = ASR::make_FunctionCall_t(al, loc, stemp, + ASR::asr_t* func_call_asr = ASRUtils::make_FunctionCall_t_util(al, loc, stemp, s_generic, args_new.p, args_new.size(), a_type, value, nullptr); if( ignore_return_value ) { @@ -1281,7 +1284,7 @@ class CommonVisitor : public AST::BaseVisitor { args_new.reserve(al, func->n_args); visit_expr_list_with_cast(func->m_args, func->n_args, args_new, args); dependencies.push_back(al, ASRUtils::symbol_name(stemp)); - return ASR::make_SubroutineCall_t(al, loc, stemp, + return ASRUtils::make_SubroutineCall_t_util(al, loc, stemp, s_generic, args_new.p, args_new.size(), nullptr); } } else if(ASR::is_a(*s)) { @@ -1532,7 +1535,7 @@ class CommonVisitor : public AST::BaseVisitor { std::string new_func_name = "__asr_generic_" + func_name + "_" + std::to_string(new_function_num); generic_func_subs[new_func_name] = subs; - t = pass_instantiate_generic_function(al, subs, rt_subs, + t = pass_instantiate_template(al, subs, rt_subs, ASRUtils::symbol_parent_symtab(func), new_func_name, func); dependencies.erase(s2c(al, func_name)); dependencies.push_back(al, s2c(al, new_func_name)); @@ -1650,7 +1653,8 @@ class CommonVisitor : public AST::BaseVisitor { // i32, i64, f32, f64 // f64[256], i32[:] ASR::ttype_t * ast_expr_to_asr_type(const Location &loc, const AST::expr_t &annotation, - bool &is_allocatable, bool raise_error=true) { + bool &is_allocatable, bool raise_error=true, ASR::abiType abi=ASR::abiType::Source, + bool is_argument=false) { Vec dims; dims.reserve(al, 4); AST::expr_t** m_args = nullptr; size_t n_args = 0; @@ -1659,7 +1663,9 @@ class CommonVisitor : public AST::BaseVisitor { if (AST::is_a(annotation)) { AST::Name_t *n = AST::down_cast(&annotation); var_annotation = n->m_id; - return get_type_from_var_annotation(var_annotation, annotation.base.loc, dims, m_args, n_args, raise_error); + return get_type_from_var_annotation(var_annotation, + annotation.base.loc, dims, m_args, n_args, raise_error, + abi, is_argument); } if (AST::is_a(annotation)) { @@ -1680,11 +1686,13 @@ class CommonVisitor : public AST::BaseVisitor { Vec types; types.reserve(al, 4); if (AST::is_a(*s->m_slice)) { - types.push_back(al, ast_expr_to_asr_type(loc, *s->m_slice, is_allocatable)); + types.push_back(al, ast_expr_to_asr_type(loc, *s->m_slice, + is_allocatable, raise_error, abi, is_argument)); } else if (AST::is_a(*s->m_slice)) { AST::Tuple_t *t = AST::down_cast(s->m_slice); for (size_t i=0; in_elts; i++) { - types.push_back(al, ast_expr_to_asr_type(loc, *t->m_elts[i], is_allocatable)); + types.push_back(al, ast_expr_to_asr_type(loc, *t->m_elts[i], + is_allocatable, raise_error, abi, is_argument)); } } else { throw SemanticError("Only Name or Tuple in Subscript supported for now in `tuple` annotation", @@ -1705,14 +1713,15 @@ class CommonVisitor : public AST::BaseVisitor { arg_types.reserve(al, arg_list->n_elts); for (size_t i=0; in_elts; i++) { arg_types.push_back(al, ast_expr_to_asr_type(loc, *arg_list->m_elts[i], - is_allocatable)); + is_allocatable, raise_error, abi, is_argument)); } } else { arg_types.reserve(al, 1); } ASR::ttype_t* ret_type = nullptr; if (t->n_elts == 2) { - ret_type = ast_expr_to_asr_type(loc, *t->m_elts[1], is_allocatable); + ret_type = ast_expr_to_asr_type(loc, *t->m_elts[1], + is_allocatable, raise_error, abi, is_argument); } ASR::ttype_t *type = ASRUtils::TYPE(ASR::make_FunctionType_t(al, loc, arg_types.p, arg_types.size(), ret_type, ASR::abiType::Source, @@ -1721,7 +1730,8 @@ class CommonVisitor : public AST::BaseVisitor { return type; } else if (var_annotation == "set") { if (AST::is_a(*s->m_slice)) { - ASR::ttype_t *type = ast_expr_to_asr_type(loc, *s->m_slice, is_allocatable); + ASR::ttype_t *type = ast_expr_to_asr_type(loc, *s->m_slice, + is_allocatable, raise_error, abi, is_argument); return ASRUtils::TYPE(ASR::make_Set_t(al, loc, type)); } else { throw SemanticError("Only Name in Subscript supported for now in `set`" @@ -1730,7 +1740,8 @@ class CommonVisitor : public AST::BaseVisitor { } else if (var_annotation == "list") { ASR::ttype_t *type = nullptr; if (AST::is_a(*s->m_slice) || AST::is_a(*s->m_slice)) { - type = ast_expr_to_asr_type(loc, *s->m_slice, is_allocatable); + type = ast_expr_to_asr_type(loc, *s->m_slice, + is_allocatable, raise_error, abi, is_argument); return ASRUtils::TYPE(ASR::make_List_t(al, loc, type)); } else { throw SemanticError("Only Name or Subscript inside Subscript supported for now in `list`" @@ -1739,7 +1750,8 @@ class CommonVisitor : public AST::BaseVisitor { } else if (var_annotation == "Allocatable") { ASR::ttype_t *type = nullptr; if (AST::is_a(*s->m_slice) || AST::is_a(*s->m_slice)) { - type = ast_expr_to_asr_type(loc, *s->m_slice, is_allocatable); + type = ast_expr_to_asr_type(loc, *s->m_slice, + is_allocatable, raise_error, abi, is_argument); is_allocatable = true; return type; } else { @@ -1753,8 +1765,10 @@ class CommonVisitor : public AST::BaseVisitor { throw SemanticError("`dict` annotation must have 2 elements: types" " of both keys and values", loc); } - ASR::ttype_t *key_type = ast_expr_to_asr_type(loc, *t->m_elts[0], is_allocatable); - ASR::ttype_t *value_type = ast_expr_to_asr_type(loc, *t->m_elts[1], is_allocatable); + ASR::ttype_t *key_type = ast_expr_to_asr_type(loc, *t->m_elts[0], + is_allocatable, raise_error, abi, is_argument); + ASR::ttype_t *value_type = ast_expr_to_asr_type(loc, *t->m_elts[1], + is_allocatable, raise_error, abi, is_argument); raise_error_when_dict_key_is_float_or_complex(key_type, loc); return ASRUtils::TYPE(ASR::make_Dict_t(al, loc, key_type, value_type)); } else { @@ -1762,13 +1776,16 @@ class CommonVisitor : public AST::BaseVisitor { " both keys and values", loc); } } else if (var_annotation == "Pointer") { - ASR::ttype_t *type = ast_expr_to_asr_type(loc, *s->m_slice, is_allocatable); + ASR::ttype_t *type = ast_expr_to_asr_type(loc, *s->m_slice, + is_allocatable, raise_error, abi, is_argument); return ASRUtils::TYPE(ASR::make_Pointer_t(al, loc, type)); } else if (var_annotation == "Const") { - ASR::ttype_t *type = ast_expr_to_asr_type(loc, *s->m_slice, is_allocatable); + ASR::ttype_t *type = ast_expr_to_asr_type(loc, *s->m_slice, + is_allocatable, raise_error, abi, is_argument); return ASRUtils::TYPE(ASR::make_Const_t(al, loc, type)); } else { - ASR::ttype_t* type = get_type_from_var_annotation(var_annotation, annotation.base.loc, dims, m_args, n_args, raise_error); + ASR::ttype_t* type = get_type_from_var_annotation(var_annotation, + annotation.base.loc, dims, m_args, n_args, raise_error, abi, is_argument); if (AST::is_a(*s->m_slice)) { ASR::dimension_t dim; @@ -1793,7 +1810,7 @@ class CommonVisitor : public AST::BaseVisitor { fill_dims_for_asr_type(dims, value, loc); } - if (ASRUtils::ttype_set_dimensions(&type, dims.p, dims.size(), al)) { + if (ASRUtils::ttype_set_dimensions(&type, dims.p, dims.size(), al, abi, is_argument)) { return type; } @@ -2678,11 +2695,14 @@ class CommonVisitor : public AST::BaseVisitor { dims.reserve(al, 1); \ ASR::dimension_t dim; \ dim.loc = loc; \ - dim.m_length = nullptr; \ - dim.m_start = nullptr; \ + dim.m_length = make_ConstantWithKind(make_IntegerConstant_t, \ + make_Integer_t, target_n_dims, 4, loc); \ + dim.m_start = make_ConstantWithKind(make_IntegerConstant_t, \ + make_Integer_t, 0, 4, loc); \ dims.push_back(al, dim); \ ASR::ttype_t* type = ASRUtils::make_Array_t_util(al, loc, \ - ASRUtils::expr_type(lbs[0]), dims.p, dims.size()); \ + ASRUtils::expr_type(lbs[0]), dims.p, dims.size(), ASR::abiType::Source, \ + false, ASR::array_physical_typeType::PointerToDataArray, true); \ lower_bounds = ASRUtils::EXPR(ASR::make_ArrayConstant_t(al, \ loc, lbs.p, lbs.size(), type, \ ASR::arraystorageType::RowMajor)); \ @@ -2700,7 +2720,8 @@ class CommonVisitor : public AST::BaseVisitor { target_shape = ASRUtils::EXPR(tmp); } bool is_allocatable = false; - ASR::ttype_t* asr_alloc_type = ast_expr_to_asr_type(ast_type_expr->base.loc, *ast_type_expr, is_allocatable); + ASR::ttype_t* asr_alloc_type = ast_expr_to_asr_type(ast_type_expr->base.loc, *ast_type_expr, + is_allocatable, true); ASR::ttype_t* target_type = ASRUtils::type_get_past_pointer(ASRUtils::expr_type(pptr)); if( !ASRUtils::types_equal(target_type, asr_alloc_type, true) ) { diag.add(diag::Diagnostic( @@ -2713,6 +2734,24 @@ class CommonVisitor : public AST::BaseVisitor { ); throw SemanticAbort(); } + if (ASR::is_a(*asr_alloc_type)) { + ASR::symbol_t *sym = ASR::down_cast(asr_alloc_type)->m_derived_type; + if (ASR::is_a(*sym)) { + ASR::StructType_t *st = ASR::down_cast(sym); + if (st->m_abi != ASR::abiType::BindC) { + diag.add(diag::Diagnostic( + "The struct in c_p_pointer must be C interoperable", + diag::Level::Error, diag::Stage::Semantic, { + diag::Label("not C interoperable", + {asr_alloc_type->base.loc}), + diag::Label("help: add the @ccallable decorator to this struct to make it C interoperable", + {st->base.base.loc}, false) + }) + ); + throw SemanticAbort(); + } + } + } fill_shape_and_lower_bound_for_CPtrToPointer(); return ASR::make_CPtrToPointer_t(al, loc, cptr, pptr, target_shape, lower_bounds); } @@ -2771,7 +2810,12 @@ class CommonVisitor : public AST::BaseVisitor { ASR::abiType abi=ASR::abiType::Source, bool inside_struct=false) { bool is_allocatable = false; - ASR::ttype_t *type = ast_expr_to_asr_type(x.base.base.loc, *x.m_annotation, is_allocatable); + ASR::ttype_t *type = nullptr; + if( inside_struct ) { + type = ast_expr_to_asr_type(x.base.base.loc, *x.m_annotation, is_allocatable, true); + } else { + type = ast_expr_to_asr_type(x.base.base.loc, *x.m_annotation, is_allocatable, true, abi); + } ASR::ttype_t* ann_assign_target_type_copy = ann_assign_target_type; ann_assign_target_type = type; if( ASR::is_a(*type) && @@ -3404,7 +3448,6 @@ class CommonVisitor : public AST::BaseVisitor { ASR::expr_t *value = nullptr; if (x.m_op == AST::unaryopType::Invert) { - if (ASRUtils::is_integer(*operand_type)) { if (ASRUtils::expr_value(operand) != nullptr) { int64_t op_value = ASR::down_cast( @@ -3414,8 +3457,7 @@ class CommonVisitor : public AST::BaseVisitor { } tmp = ASR::make_IntegerBitNot_t(al, x.base.base.loc, operand, dest_type, value); return; - } - else if (ASRUtils::is_unsigned_integer(*operand_type)) { + } else if (ASRUtils::is_unsigned_integer(*operand_type)) { if (ASRUtils::expr_value(operand) != nullptr) { int64_t op_value = ASR::down_cast( ASRUtils::expr_value(operand))->m_n; @@ -3425,12 +3467,10 @@ class CommonVisitor : public AST::BaseVisitor { } tmp = ASR::make_UnsignedIntegerBitNot_t(al, x.base.base.loc, operand, dest_type, value); return; - } - else if (ASRUtils::is_real(*operand_type)) { + } else if (ASRUtils::is_real(*operand_type)) { throw SemanticError("Unary operator '~' not supported for floats", x.base.base.loc); - } - else if (ASRUtils::is_logical(*operand_type)) { + } else if (ASRUtils::is_logical(*operand_type)) { if (ASRUtils::expr_value(operand) != nullptr) { bool op_value = ASR::down_cast( ASRUtils::expr_value(operand))->m_value; @@ -3444,15 +3484,14 @@ class CommonVisitor : public AST::BaseVisitor { int_type, value)); tmp = ASR::make_IntegerBitNot_t(al, x.base.base.loc, int_arg, int_type, value); return; - } - else if (ASRUtils::is_complex(*operand_type)) { + } else if (ASRUtils::is_complex(*operand_type)) { throw SemanticError("Unary operator '~' not supported for complex type", x.base.base.loc); + } else { + throw SemanticError("Unary operator '~' not supported for type " + ASRUtils::type_to_str_python(operand_type), + x.base.base.loc); } - - } - else if (x.m_op == AST::unaryopType::Not) { - + } else if (x.m_op == AST::unaryopType::Not) { ASR::expr_t *logical_arg = operand; if (ASRUtils::is_integer(*operand_type)) { if (ASRUtils::expr_value(operand) != nullptr) { @@ -3466,8 +3505,19 @@ class CommonVisitor : public AST::BaseVisitor { logical_arg = ASR::down_cast(ASR::make_Cast_t( al, x.base.base.loc, operand, ASR::cast_kindType::IntegerToLogical, logical_type, value)); - } - else if (ASRUtils::is_real(*operand_type)) { + } else if (ASRUtils::is_unsigned_integer(*operand_type)) { + if (ASRUtils::expr_value(operand) != nullptr) { + int64_t op_value = ASR::down_cast( + ASRUtils::expr_value(operand))->m_n; + bool b = (op_value == 0); + value = ASR::down_cast(ASR::make_LogicalConstant_t( + al, x.base.base.loc, b, logical_type)); + } + // cast UnsignedInteger to Logical + logical_arg = ASR::down_cast(ASR::make_Cast_t( + al, x.base.base.loc, operand, ASR::cast_kindType::UnsignedIntegerToLogical, + logical_type, value)); + } else if (ASRUtils::is_real(*operand_type)) { if (ASRUtils::expr_value(operand) != nullptr) { double op_value = ASR::down_cast( ASRUtils::expr_value(operand))->m_r; @@ -3479,16 +3529,14 @@ class CommonVisitor : public AST::BaseVisitor { logical_arg = ASR::down_cast(ASR::make_Cast_t( al, x.base.base.loc, operand, ASR::cast_kindType::RealToLogical, logical_type, value)); - } - else if (ASRUtils::is_logical(*operand_type)) { + } else if (ASRUtils::is_logical(*operand_type)) { if (ASRUtils::expr_value(operand) != nullptr) { bool op_value = ASR::down_cast( ASRUtils::expr_value(operand))->m_value; value = ASR::down_cast(ASR::make_LogicalConstant_t( al, x.base.base.loc, !op_value, logical_type)); } - } - else if (ASRUtils::is_complex(*operand_type)) { + } else if (ASRUtils::is_complex(*operand_type)) { if (ASRUtils::expr_value(operand) != nullptr) { if( ASR::is_a(*operand) ) { ASR::FunctionCall_t* operand_func_call = ASR::down_cast(operand); @@ -3505,29 +3553,33 @@ class CommonVisitor : public AST::BaseVisitor { logical_arg = ASR::down_cast(ASR::make_Cast_t( al, x.base.base.loc, operand, ASR::cast_kindType::ComplexToLogical, logical_type, value)); + } else { + throw SemanticError("Unary operator '!' not supported for type " + ASRUtils::type_to_str_python(operand_type), + x.base.base.loc); } tmp = ASR::make_LogicalNot_t(al, x.base.base.loc, logical_arg, logical_type, value); return; - - } - else if (x.m_op == AST::unaryopType::UAdd) { - + } else if (x.m_op == AST::unaryopType::UAdd) { if (ASRUtils::is_integer(*operand_type)) { if (ASRUtils::expr_value(operand) != nullptr) { int64_t op_value = ASR::down_cast( ASRUtils::expr_value(operand))->m_n; tmp = ASR::make_IntegerConstant_t(al, x.base.base.loc, op_value, operand_type); } - } - else if (ASRUtils::is_real(*operand_type)) { + } else if (ASRUtils::is_unsigned_integer(*operand_type)) { + if (ASRUtils::expr_value(operand) != nullptr) { + int64_t op_value = ASR::down_cast( + ASRUtils::expr_value(operand))->m_n; + tmp = ASR::make_UnsignedIntegerConstant_t(al, x.base.base.loc, op_value, operand_type); + } + } else if (ASRUtils::is_real(*operand_type)) { if (ASRUtils::expr_value(operand) != nullptr) { double op_value = ASR::down_cast( ASRUtils::expr_value(operand))->m_r; tmp = ASR::make_RealConstant_t(al, x.base.base.loc, op_value, operand_type); } - } - else if (ASRUtils::is_logical(*operand_type)) { + } else if (ASRUtils::is_logical(*operand_type)) { if (ASRUtils::expr_value(operand) != nullptr) { bool op_value = ASR::down_cast( ASRUtils::expr_value(operand))->m_value; @@ -3536,8 +3588,7 @@ class CommonVisitor : public AST::BaseVisitor { } tmp = ASR::make_Cast_t(al, x.base.base.loc, operand, ASR::cast_kindType::LogicalToInteger, int_type, value); - } - else if (ASRUtils::is_complex(*operand_type)) { + } else if (ASRUtils::is_complex(*operand_type)) { if (ASRUtils::expr_value(operand) != nullptr) { if( ASR::is_a(*operand) ) { ASR::FunctionCall_t* operand_func_call = ASR::down_cast(operand); @@ -3549,12 +3600,12 @@ class CommonVisitor : public AST::BaseVisitor { tmp = ASR::make_ComplexConstant_t(al, x.base.base.loc, std::real(op_value), std::imag(op_value), operand_type); } + } else { + throw SemanticError("Unary operator '+' not supported for type " + ASRUtils::type_to_str_python(operand_type), + x.base.base.loc); } return; - - } - else if (x.m_op == AST::unaryopType::USub) { - + } else if (x.m_op == AST::unaryopType::USub) { if (ASRUtils::is_integer(*operand_type)) { if (ASRUtils::expr_value(operand) != nullptr) { int64_t op_value = ASR::down_cast( @@ -3565,8 +3616,17 @@ class CommonVisitor : public AST::BaseVisitor { tmp = ASR::make_IntegerUnaryMinus_t(al, x.base.base.loc, operand, operand_type, value); return; - } - else if (ASRUtils::is_real(*operand_type)) { + } else if (ASRUtils::is_unsigned_integer(*operand_type)) { + if (ASRUtils::expr_value(operand) != nullptr) { + int64_t op_value = ASR::down_cast( + ASRUtils::expr_value(operand))->m_n; + value = ASR::down_cast(ASR::make_UnsignedIntegerConstant_t( + al, x.base.base.loc, -op_value, operand_type)); + } + tmp = ASR::make_UnsignedIntegerUnaryMinus_t(al, x.base.base.loc, operand, + operand_type, value); + return; + } else if (ASRUtils::is_real(*operand_type)) { if (ASRUtils::expr_value(operand) != nullptr) { double op_value = ASR::down_cast( ASRUtils::expr_value(operand))->m_r; @@ -3576,8 +3636,7 @@ class CommonVisitor : public AST::BaseVisitor { tmp = ASR::make_RealUnaryMinus_t(al, x.base.base.loc, operand, operand_type, value); return; - } - else if (ASRUtils::is_logical(*operand_type)) { + } else if (ASRUtils::is_logical(*operand_type)) { if (ASRUtils::expr_value(operand) != nullptr) { bool op_value = ASR::down_cast( ASRUtils::expr_value(operand))->m_value; @@ -3591,8 +3650,7 @@ class CommonVisitor : public AST::BaseVisitor { tmp = ASR::make_IntegerUnaryMinus_t(al, x.base.base.loc, int_arg, int_type, value); return; - } - else if (ASRUtils::is_complex(*operand_type)) { + } else if (ASRUtils::is_complex(*operand_type)) { if (ASRUtils::expr_value(operand) != nullptr) { ASR::ComplexConstant_t *c = ASR::down_cast( ASRUtils::expr_value(operand)); @@ -3606,6 +3664,9 @@ class CommonVisitor : public AST::BaseVisitor { tmp = ASR::make_ComplexUnaryMinus_t(al, x.base.base.loc, operand, operand_type, value); return; + } else { + throw SemanticError("Unary operator '-' not supported for type " + ASRUtils::type_to_str_python(operand_type), + x.base.base.loc); } } } @@ -4095,7 +4156,8 @@ class SymbolTableVisitor : public CommonVisitor { ASR::intentType s_intent = ASRUtils::intent_unspecified; AST::expr_t* arg_annotation_type = get_var_intent_and_annotation(x.m_args.m_args[i].m_annotation, s_intent); is_allocatable = false; - ASR::ttype_t *arg_type = ast_expr_to_asr_type(x.base.base.loc, *arg_annotation_type, is_allocatable); + ASR::ttype_t *arg_type = ast_expr_to_asr_type(x.base.base.loc, *arg_annotation_type, + is_allocatable, true, current_procedure_abi_type, s_intent != ASR::intentType::Local); if ((s_intent == ASRUtils::intent_inout || s_intent == ASRUtils::intent_out) && !ASRUtils::is_aggregate_type(arg_type)) { throw SemanticError("Simple Type " + ASRUtils::type_to_str_python(arg_type) @@ -4190,7 +4252,8 @@ class SymbolTableVisitor : public CommonVisitor { if (AST::is_a(*x.m_returns) || AST::is_a(*x.m_returns)) { std::string return_var_name = "_lpython_return_variable"; is_allocatable = false; - ASR::ttype_t *type = ast_expr_to_asr_type(x.m_returns->base.loc, *x.m_returns, is_allocatable); + ASR::ttype_t *type = ast_expr_to_asr_type(x.m_returns->base.loc, + *x.m_returns, is_allocatable, true, current_procedure_abi_type, true); ASR::storage_typeType storage_type = ASR::storage_typeType::Default; if (is_allocatable) { type = ASRUtils::TYPE(ASR::make_Allocatable_t(al, x.m_returns->base.loc, @@ -4466,6 +4529,10 @@ class SymbolTableVisitor : public CommonVisitor { } } + void visit_AugAssign(const AST::AugAssign_t &/*x*/) { + // We skip this in the SymbolTable visitor, but visit it in the BodyVisitor + } + void visit_AnnAssign(const AST::AnnAssign_t &/*x*/) { // We skip this in the SymbolTable visitor, but visit it in the BodyVisitor } @@ -4684,7 +4751,7 @@ class BodyVisitor : public CommonVisitor { std::string func_name = "global_initializer"; LCompilers::PassOptions pass_options; pass_options.run_fun = func_name; - pass_wrap_global_stmts_into_function(al, *unit, pass_options); + pass_wrap_global_stmts(al, *unit, pass_options); ASR::Module_t *mod = ASR::down_cast(main_module_sym); ASR::symbol_t *f_sym = unit->m_global_scope->get_symbol(func_name); @@ -4720,7 +4787,7 @@ class BodyVisitor : public CommonVisitor { // Wrap all the global statements into a Function LCompilers::PassOptions pass_options; pass_options.run_fun = func_name; - pass_wrap_global_stmts_into_function(al, *unit, pass_options); + pass_wrap_global_stmts(al, *unit, pass_options); ASR::Module_t *mod = ASR::down_cast(main_module_sym); ASR::symbol_t *f_sym = unit->m_global_scope->get_symbol(func_name); @@ -4765,7 +4832,7 @@ class BodyVisitor : public CommonVisitor { if (t == nullptr) { // Throw Not implemented error. throw SemanticError("Internal FunctionDef: Not implemented", x.base.base.loc); - } + } if (ASR::is_a(*t)) { ASR::Function_t *f = ASR::down_cast(t); @@ -4806,7 +4873,7 @@ class BodyVisitor : public CommonVisitor { s2c(al, mod_name), nullptr, 0, s2c(al, "global_initializer"), ASR::accessType::Public)); current_scope->add_symbol(g_func_name, es); - tmp_vec.push_back(ASR::make_SubroutineCall_t(al, x.base.base.loc, + tmp_vec.push_back(ASRUtils::make_SubroutineCall_t_util(al, x.base.base.loc, es, g_func, nullptr, 0, nullptr)); } @@ -4819,7 +4886,7 @@ class BodyVisitor : public CommonVisitor { s2c(al, mod_name), nullptr, 0, s2c(al, "global_statements"), ASR::accessType::Public)); current_scope->add_symbol(g_func_name, es); - tmp_vec.push_back(ASR::make_SubroutineCall_t(al, x.base.base.loc, + tmp_vec.push_back(ASRUtils::make_SubroutineCall_t_util(al, x.base.base.loc, es, g_func, nullptr, 0, nullptr)); } } @@ -4847,7 +4914,7 @@ class BodyVisitor : public CommonVisitor { s2c(al, mod_name), nullptr, 0, s2c(al, "global_initializer"), ASR::accessType::Public)); current_scope->add_symbol(g_func_name, es); - tmp_vec.push_back(ASR::make_SubroutineCall_t(al, x.base.base.loc, + tmp_vec.push_back(ASRUtils::make_SubroutineCall_t_util(al, x.base.base.loc, es, g_func, nullptr, 0, nullptr)); } @@ -4860,7 +4927,7 @@ class BodyVisitor : public CommonVisitor { s2c(al, mod_name), nullptr, 0, s2c(al, "global_statements"), ASR::accessType::Public)); current_scope->add_symbol(g_func_name, es); - tmp_vec.push_back(ASR::make_SubroutineCall_t(al, x.base.base.loc, + tmp_vec.push_back(ASRUtils::make_SubroutineCall_t_util(al, x.base.base.loc, es, g_func, nullptr, 0, nullptr)); } } @@ -6254,14 +6321,20 @@ class BodyVisitor : public CommonVisitor { tmp = ASR::make_StringCompare_t(al, x.base.base.loc, left, asr_op, right, type, value); } else if (ASR::is_a(*dest_type)) { - if (asr_op != ASR::cmpopType::Eq && asr_op != ASR::cmpopType::NotEq) { - throw SemanticError("Only Equal and Not-equal operators are supported for Tuples", + if (asr_op != ASR::cmpopType::Eq && asr_op != ASR::cmpopType::NotEq + && asr_op != ASR::cmpopType::Lt && asr_op != ASR::cmpopType::LtE + && asr_op != ASR::cmpopType::Gt && asr_op != ASR::cmpopType::GtE) { + throw SemanticError("Only ==, !=, <, <=, >, >= operators " + "are supported for Tuples", x.base.base.loc); } tmp = ASR::make_TupleCompare_t(al, x.base.base.loc, left, asr_op, right, type, value); } else if (ASR::is_a(*dest_type)) { - if (asr_op != ASR::cmpopType::Eq && asr_op != ASR::cmpopType::NotEq) { - throw SemanticError("Only Equal and Not-equal operators are supported for Tuples", + if (asr_op != ASR::cmpopType::Eq && asr_op != ASR::cmpopType::NotEq + && asr_op != ASR::cmpopType::Lt && asr_op != ASR::cmpopType::LtE + && asr_op != ASR::cmpopType::Gt && asr_op != ASR::cmpopType::GtE) { + throw SemanticError("Only ==, !=, <, <=, >, >= operators " + "are supported for Lists", x.base.base.loc); } tmp = ASR::make_ListCompare_t(al, x.base.base.loc, left, asr_op, right, type, value); @@ -7246,15 +7319,23 @@ class BodyVisitor : public CommonVisitor { } if (!s) { + std::string intrinsic_name = call_name; std::set not_cpython_builtin = { "sin", "cos", "gamma", "tan", "asin", "acos", "atan", "sinh", "cosh", "tanh", "exp", "exp2", "expm1", "Symbol", "diff", "expand", "sum" // For sum called over lists }; - if (ASRUtils::IntrinsicFunctionRegistry::is_intrinsic_function(call_name) && + std::set symbolic_functions = { + "sin", "cos", "log", "exp", "Abs" + }; + if ((symbolic_functions.find(call_name) != symbolic_functions.end()) && + imported_functions[call_name] == "sympy"){ + intrinsic_name = "Symbolic" + std::string(1, std::toupper(call_name[0])) + call_name.substr(1); + } + if (ASRUtils::IntrinsicFunctionRegistry::is_intrinsic_function(intrinsic_name) && (not_cpython_builtin.find(call_name) == not_cpython_builtin.end() || imported_functions.find(call_name) != imported_functions.end() )) { ASRUtils::create_intrinsic_function create_func = - ASRUtils::IntrinsicFunctionRegistry::get_create_function(call_name); + ASRUtils::IntrinsicFunctionRegistry::get_create_function(intrinsic_name); Vec args_; args_.reserve(al, x.n_args); visit_expr_list(x.m_args, x.n_args, args_); if (ASRUtils::is_array(ASRUtils::expr_type(args_[0])) && @@ -7304,7 +7385,7 @@ class BodyVisitor : public CommonVisitor { dim = ASRUtils::EXPR(ASR::make_IntegerBinOp_t(al, loc, args[1].m_value, ASR::binopType::Add, const_one, int_type, nullptr)); } - tmp = ASR::make_ArraySize_t(al, loc, var, dim, int_type, nullptr); + tmp = ASRUtils::make_ArraySize_t_util(al, loc, var, dim, int_type, nullptr); return; } else if (call_name == "empty") { // TODO: check that the `empty` arguments are compatible @@ -7381,7 +7462,8 @@ class BodyVisitor : public CommonVisitor { } else if( call_name == "pointer" ) { parse_args(x, args); ASR::ttype_t* type_ = ASRUtils::duplicate_type_with_empty_dims( - al, ASRUtils::expr_type(args[0].m_value)); + al, ASRUtils::expr_type(args[0].m_value), + ASR::array_physical_typeType::DescriptorArray, true); ASR::ttype_t *type = ASRUtils::TYPE(ASR::make_Pointer_t(al, x.base.base.loc, type_)); tmp = ASR::make_GetPointer_t(al, x.base.base.loc, args[0].m_value, type, nullptr); return ; @@ -7403,10 +7485,13 @@ class BodyVisitor : public CommonVisitor { dims.reserve(al, 1); ASR::dimension_t dim; dim.loc = x.base.base.loc; - dim.m_length = nullptr; - dim.m_start = nullptr; + dim.m_length = make_ConstantWithKind(make_IntegerConstant_t, + make_Integer_t, n_args, 4, dim.loc); + dim.m_start = make_ConstantWithKind(make_IntegerConstant_t, + make_Integer_t, 0, 4, dim.loc); dims.push_back(al, dim); - type = ASRUtils::make_Array_t_util(al, x.base.base.loc, type, dims.p, dims.size()); + type = ASRUtils::make_Array_t_util(al, x.base.base.loc, type, dims.p, dims.size(), + ASR::abiType::Source, false, ASR::array_physical_typeType::PointerToDataArray, true); tmp = ASR::make_ArrayConstant_t(al, x.base.base.loc, m_args, n_args, type, ASR::arraystorageType::RowMajor); } else { throw SemanticError("array accepts only list for now, got " + @@ -7623,7 +7708,7 @@ Result python_ast_to_asr(Allocator &al, LocationManager pass_options.run_fun = "_lpython_main_program"; pass_options.runtime_library_dir = get_runtime_library_dir(); } - pass_wrap_global_stmts_into_program(al, *tu, pass_options); + pass_wrap_global_stmts_program(al, *tu, pass_options); #if defined(WITH_LFORTRAN_ASSERT) diag::Diagnostics diagnostics; if (!asr_verify(*tu, true, diagnostics)) { diff --git a/src/lpython/semantics/python_attribute_eval.h b/src/lpython/semantics/python_attribute_eval.h index fe4b01771e0..1b455589790 100644 --- a/src/lpython/semantics/python_attribute_eval.h +++ b/src/lpython/semantics/python_attribute_eval.h @@ -116,7 +116,7 @@ struct AttributeHandler { throw SemanticError("array.size() takes no arguments", loc); } ASR::ttype_t *int_type = ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4)); - return ASR::make_ArraySize_t(al, loc, s, nullptr, int_type, nullptr); + return ASRUtils::make_ArraySize_t_util(al, loc, s, nullptr, int_type, nullptr); } static ASR::asr_t* eval_list_append(ASR::expr_t *s, Allocator &al, const Location &loc, diff --git a/src/lpython/semantics/python_intrinsic_eval.h b/src/lpython/semantics/python_intrinsic_eval.h index 1cb4b2919a8..5b7b771ffb8 100644 --- a/src/lpython/semantics/python_intrinsic_eval.h +++ b/src/lpython/semantics/python_intrinsic_eval.h @@ -396,6 +396,15 @@ struct IntrinsicNodeHandler { newdim.m_start = nullptr, newdim.m_length = nullptr; dims.push_back(al, newdim); ASR::ttype_t* empty_type = ASRUtils::duplicate_type(al, ASRUtils::expr_type(array), &dims); + ASR::array_physical_typeType array_physical_type = ASRUtils::extract_physical_type( + ASRUtils::expr_type(array)); + if( array_physical_type == ASR::array_physical_typeType::FixedSizeArray ) { + empty_type = ASRUtils::duplicate_type(al, ASRUtils::expr_type(array), + &dims, array_physical_type, true); + } else { + empty_type = ASRUtils::duplicate_type(al, ASRUtils::expr_type(array), &dims); + } + newshape = ASRUtils::cast_to_descriptor(al, newshape); return ASR::make_ArrayReshape_t(al, loc, array, newshape, empty_type, nullptr); } diff --git a/src/runtime/lpython/lpython.py b/src/runtime/lpython/lpython.py index 576e93a4b51..68c9b2aaaa6 100644 --- a/src/runtime/lpython/lpython.py +++ b/src/runtime/lpython/lpython.py @@ -17,14 +17,12 @@ class UnsignedInteger: def __init__(self, bit_width, value): if isinstance(value, UnsignedInteger): - if bit_width != value.bit_width: - raise ValueError(f"Bit width mismatch: {bit_width} vs {value.bit_width}") value = value.value - - if not (0 <= value < 2**bit_width): - raise ValueError(f"Value should be in range 0 to {2**bit_width-1} for a {bit_width}-bit unsigned integer.") self.bit_width = bit_width - self.value = value + self.value = value % (2**bit_width) + + def __bool__(self): + return self.value != 0 def __add__(self, other): if isinstance(other, self.__class__): diff --git a/tests/errors/arrays_01.py b/tests/errors/arrays_01.py new file mode 100644 index 00000000000..3c8867ae8cc --- /dev/null +++ b/tests/errors/arrays_01.py @@ -0,0 +1,17 @@ +from lpython import (i8, i32, dataclass) +from numpy import empty, int8 + +# test issue-2088 + +@dataclass +class LPBHV_small: + dim : i32 = 4 + a : i8[4] = empty(4, dtype=int8) + + +def g() -> None: + l2 : LPBHV_small = LPBHV_small( + 4, + [i8(214), i8(157), i8(3), i8(146)]) + +g() diff --git a/tests/errors/bindc_10e.py b/tests/errors/bindc_10e.py new file mode 100644 index 00000000000..bdbff7df6c4 --- /dev/null +++ b/tests/errors/bindc_10e.py @@ -0,0 +1,31 @@ +from lpython import (i64, i16, CPtr, c_p_pointer, Pointer, sizeof, packed, + dataclass, ccallable, ccall, i32) + +@ccall +def _lfortran_malloc(size: i32) -> CPtr: + pass + + +def alloc(buf_size:i64) -> CPtr: + return _lfortran_malloc(i32(buf_size)) + + +@packed +@dataclass +class S: + a: i16 + b: i64 + + +def main(): + p1: CPtr = alloc(sizeof(S)) + print(p1) + p2: Pointer[S] = c_p_pointer(p1, S) + p2.a = i16(5) + p2.b = i64(4) + print(p2.a, p2.b) + assert p2.a == i16(5) + assert p2.b == i64(4) + + +main() diff --git a/tests/errors/test_operator_01.py b/tests/errors/test_operator_01.py new file mode 100644 index 00000000000..a72de4d697b --- /dev/null +++ b/tests/errors/test_operator_01.py @@ -0,0 +1,11 @@ +from lpython import i32, dataclass + +@dataclass +class A: + n: i32 + +def main0(): + a: A = A(10) + print(-a) + +main0() diff --git a/tests/reference/asr-array_01_decl-39cf894.json b/tests/reference/asr-array_01_decl-39cf894.json index 67b87c3f977..d708d6af31d 100644 --- a/tests/reference/asr-array_01_decl-39cf894.json +++ b/tests/reference/asr-array_01_decl-39cf894.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "asr-array_01_decl-39cf894.stdout", - "stdout_hash": "f8ba6c730aea2846362708c15bb4ff33f587f833f791d26b55fc70b8", + "stdout_hash": "dd9152135900885d4e4e13ad4877666492a73480c436267dd94567c0", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/asr-array_01_decl-39cf894.stdout b/tests/reference/asr-array_01_decl-39cf894.stdout index a294f478d2a..f144a6f973c 100644 --- a/tests/reference/asr-array_01_decl-39cf894.stdout +++ b/tests/reference/asr-array_01_decl-39cf894.stdout @@ -126,6 +126,7 @@ (Real 4) [(() ())] + DescriptorArray ) () Source @@ -140,6 +141,7 @@ (Real 4) [(() ())] + DescriptorArray )] (Real 4) Source @@ -234,6 +236,7 @@ (Real 8) [(() ())] + DescriptorArray ) () Source @@ -248,6 +251,7 @@ (Real 8) [(() ())] + DescriptorArray )] (Real 8) Source @@ -334,6 +338,7 @@ (Integer 2) [(() ())] + DescriptorArray ) () Source @@ -348,6 +353,7 @@ (Integer 2) [(() ())] + DescriptorArray )] (Integer 2) Source @@ -436,6 +442,7 @@ (Integer 4) [(() ())] + DescriptorArray ) () Source @@ -450,6 +457,7 @@ (Integer 4) [(() ())] + DescriptorArray )] (Integer 4) Source @@ -533,6 +541,7 @@ (Integer 8) [(() ())] + DescriptorArray ) () Source @@ -547,6 +556,7 @@ (Integer 8) [(() ())] + DescriptorArray )] (Integer 8) Source @@ -619,6 +629,7 @@ (Complex 4) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 3 (Integer 4)))] + FixedSizeArray ) () Source @@ -639,6 +650,7 @@ (Complex 8) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 10 (Integer 4)))] + FixedSizeArray ) () Source @@ -659,6 +671,7 @@ (Real 4) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 3 (Integer 4)))] + FixedSizeArray ) () Source @@ -679,6 +692,7 @@ (Real 8) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 10 (Integer 4)))] + FixedSizeArray ) () Source @@ -699,6 +713,7 @@ (Integer 2) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 3 (Integer 4)))] + FixedSizeArray ) () Source @@ -719,6 +734,7 @@ (Integer 4) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 3 (Integer 4)))] + FixedSizeArray ) () Source @@ -739,6 +755,7 @@ (Integer 8) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 10 (Integer 4)))] + FixedSizeArray ) () Source @@ -774,7 +791,18 @@ [(FunctionCall 208 accept_i16_array () - [((Var 205 ai16))] + [((ArrayPhysicalCast + (Var 205 ai16) + FixedSizeArray + DescriptorArray + (Array + (Integer 2) + [((IntegerConstant 0 (Integer 4)) + (IntegerConstant 3 (Integer 4)))] + DescriptorArray + ) + () + ))] (Integer 2) () () @@ -787,7 +815,18 @@ [(FunctionCall 208 accept_i32_array () - [((Var 205 ai32))] + [((ArrayPhysicalCast + (Var 205 ai32) + FixedSizeArray + DescriptorArray + (Array + (Integer 4) + [((IntegerConstant 0 (Integer 4)) + (IntegerConstant 3 (Integer 4)))] + DescriptorArray + ) + () + ))] (Integer 4) () () @@ -800,7 +839,18 @@ [(FunctionCall 208 accept_i64_array () - [((Var 205 ai64))] + [((ArrayPhysicalCast + (Var 205 ai64) + FixedSizeArray + DescriptorArray + (Array + (Integer 8) + [((IntegerConstant 0 (Integer 4)) + (IntegerConstant 10 (Integer 4)))] + DescriptorArray + ) + () + ))] (Integer 8) () () @@ -813,7 +863,18 @@ [(FunctionCall 208 accept_f32_array () - [((Var 205 af32))] + [((ArrayPhysicalCast + (Var 205 af32) + FixedSizeArray + DescriptorArray + (Array + (Real 4) + [((IntegerConstant 0 (Integer 4)) + (IntegerConstant 3 (Integer 4)))] + DescriptorArray + ) + () + ))] (Real 4) () () @@ -826,7 +887,18 @@ [(FunctionCall 208 accept_f64_array () - [((Var 205 af64))] + [((ArrayPhysicalCast + (Var 205 af64) + FixedSizeArray + DescriptorArray + (Array + (Real 8) + [((IntegerConstant 0 (Integer 4)) + (IntegerConstant 10 (Integer 4)))] + DescriptorArray + ) + () + ))] (Real 8) () () diff --git a/tests/reference/asr-array_02_decl-e8f6874.json b/tests/reference/asr-array_02_decl-e8f6874.json index 9ad5016f6fd..6a5c7c46cc5 100644 --- a/tests/reference/asr-array_02_decl-e8f6874.json +++ b/tests/reference/asr-array_02_decl-e8f6874.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "asr-array_02_decl-e8f6874.stdout", - "stdout_hash": "54f947ef59beab10149fb69a1dafc8691c782ca6b9e0242eba878eda", + "stdout_hash": "ff86e48c2aec878635ceaddd671e0b89e6e20ad69c3944cd7dbfb88a", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/asr-array_02_decl-e8f6874.stdout b/tests/reference/asr-array_02_decl-e8f6874.stdout index d446e8b8edc..541f7477e51 100644 --- a/tests/reference/asr-array_02_decl-e8f6874.stdout +++ b/tests/reference/asr-array_02_decl-e8f6874.stdout @@ -78,6 +78,7 @@ (Real 4) [(() ())] + DescriptorArray ) () Source @@ -92,6 +93,7 @@ (Real 4) [(() ())] + DescriptorArray )] (Real 4) Source @@ -164,6 +166,7 @@ ()) (() ())] + DescriptorArray ) () Source @@ -180,6 +183,7 @@ ()) (() ())] + DescriptorArray )] (Real 8) Source @@ -255,6 +259,7 @@ ()) (() ())] + DescriptorArray ) () Source @@ -271,6 +276,7 @@ ()) (() ())] + DescriptorArray )] (Integer 4) Source @@ -348,6 +354,7 @@ ()) (() ())] + DescriptorArray ) () Source @@ -366,6 +373,7 @@ ()) (() ())] + DescriptorArray )] (Integer 8) Source @@ -430,6 +438,7 @@ (IntegerConstant 5 (Integer 4))) ((IntegerConstant 0 (Integer 4)) (IntegerConstant 99 (Integer 4)))] + FixedSizeArray ) () Source @@ -456,6 +465,7 @@ (IntegerConstant 11 (Integer 4))) ((IntegerConstant 0 (Integer 4)) (IntegerConstant 16 (Integer 4)))] + FixedSizeArray ) () Source @@ -476,6 +486,7 @@ (Real 4) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 3 (Integer 4)))] + FixedSizeArray ) () Source @@ -498,6 +509,7 @@ (IntegerConstant 10 (Integer 4))) ((IntegerConstant 0 (Integer 4)) (IntegerConstant 4 (Integer 4)))] + FixedSizeArray ) () Source @@ -520,6 +532,7 @@ (IntegerConstant 3 (Integer 4))) ((IntegerConstant 0 (Integer 4)) (IntegerConstant 3 (Integer 4)))] + FixedSizeArray ) () Source @@ -544,6 +557,7 @@ (IntegerConstant 10 (Integer 4))) ((IntegerConstant 0 (Integer 4)) (IntegerConstant 10 (Integer 4)))] + FixedSizeArray ) () Source @@ -578,7 +592,20 @@ [(FunctionCall 206 accept_multidim_i32_array () - [((Var 203 ai32))] + [((ArrayPhysicalCast + (Var 203 ai32) + FixedSizeArray + DescriptorArray + (Array + (Integer 4) + [((IntegerConstant 0 (Integer 4)) + (IntegerConstant 3 (Integer 4))) + ((IntegerConstant 0 (Integer 4)) + (IntegerConstant 3 (Integer 4)))] + DescriptorArray + ) + () + ))] (Integer 4) () () @@ -591,7 +618,22 @@ [(FunctionCall 206 accept_multidim_i64_array () - [((Var 203 ai64))] + [((ArrayPhysicalCast + (Var 203 ai64) + FixedSizeArray + DescriptorArray + (Array + (Integer 8) + [((IntegerConstant 0 (Integer 4)) + (IntegerConstant 10 (Integer 4))) + ((IntegerConstant 0 (Integer 4)) + (IntegerConstant 10 (Integer 4))) + ((IntegerConstant 0 (Integer 4)) + (IntegerConstant 10 (Integer 4)))] + DescriptorArray + ) + () + ))] (Integer 8) () () @@ -604,7 +646,18 @@ [(FunctionCall 206 accept_multidim_f32_array () - [((Var 203 af32))] + [((ArrayPhysicalCast + (Var 203 af32) + FixedSizeArray + DescriptorArray + (Array + (Real 4) + [((IntegerConstant 0 (Integer 4)) + (IntegerConstant 3 (Integer 4)))] + DescriptorArray + ) + () + ))] (Real 4) () () @@ -617,7 +670,20 @@ [(FunctionCall 206 accept_multidim_f64_array () - [((Var 203 af64))] + [((ArrayPhysicalCast + (Var 203 af64) + FixedSizeArray + DescriptorArray + (Array + (Real 8) + [((IntegerConstant 0 (Integer 4)) + (IntegerConstant 10 (Integer 4))) + ((IntegerConstant 0 (Integer 4)) + (IntegerConstant 4 (Integer 4)))] + DescriptorArray + ) + () + ))] (Real 8) () () diff --git a/tests/reference/asr-arrays_01-a617b64.json b/tests/reference/asr-arrays_01-a617b64.json new file mode 100644 index 00000000000..45a1b7310d4 --- /dev/null +++ b/tests/reference/asr-arrays_01-a617b64.json @@ -0,0 +1,13 @@ +{ + "basename": "asr-arrays_01-a617b64", + "cmd": "lpython --show-asr --no-color {infile} -o {outfile}", + "infile": "tests/errors/arrays_01.py", + "infile_hash": "9e11033fc97f884cd3d55a9194cb45add6805e5fc4d9473f9e1b9611", + "outfile": null, + "outfile_hash": null, + "stdout": null, + "stdout_hash": null, + "stderr": "asr-arrays_01-a617b64.stderr", + "stderr_hash": "b8317c7306f747ceefa8557c06f2a0b4a8a4bd7ae805bb494fca6ef2", + "returncode": 2 +} \ No newline at end of file diff --git a/tests/reference/asr-arrays_01-a617b64.stderr b/tests/reference/asr-arrays_01-a617b64.stderr new file mode 100644 index 00000000000..4fa39a8c3ca --- /dev/null +++ b/tests/reference/asr-arrays_01-a617b64.stderr @@ -0,0 +1,8 @@ +semantic error: Type mismatch in procedure call; the types must be compatible + --> tests/errors/arrays_01.py:15:9 + | +15 | [i8(214), i8(157), i8(3), i8(146)]) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch (passed argument type is list[i8] but required type is i8[4]) + | + 9 | a : i8[4] = empty(4, dtype=int8) + | ^^^^^ type mismatch (passed argument type is list[i8] but required type is i8[4]) diff --git a/tests/reference/asr-bindc_02-bc1a7ea.json b/tests/reference/asr-bindc_02-bc1a7ea.json index e7adaace884..4424c99c66f 100644 --- a/tests/reference/asr-bindc_02-bc1a7ea.json +++ b/tests/reference/asr-bindc_02-bc1a7ea.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "asr-bindc_02-bc1a7ea.stdout", - "stdout_hash": "854797162b43a2acc8e656672bb4b30850dcd4a3915d7ef6e579ff37", + "stdout_hash": "d7fb0284539f28d2eab1fcc630c93d73aad2210607d0fcb9e4bac673", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/asr-bindc_02-bc1a7ea.stdout b/tests/reference/asr-bindc_02-bc1a7ea.stdout index 675c4abb01c..ec40edb99aa 100644 --- a/tests/reference/asr-bindc_02-bc1a7ea.stdout +++ b/tests/reference/asr-bindc_02-bc1a7ea.stdout @@ -39,8 +39,9 @@ [(IntegerConstant 1 (Integer 4))] (Array (Integer 4) - [(() - ())] + [((IntegerConstant 0 (Integer 4)) + (IntegerConstant 1 (Integer 4)))] + PointerToDataArray ) RowMajor ) @@ -48,8 +49,9 @@ [(IntegerConstant 0 (Integer 4))] (Array (Integer 4) - [(() - ())] + [((IntegerConstant 0 (Integer 4)) + (IntegerConstant 1 (Integer 4)))] + PointerToDataArray ) RowMajor ) @@ -91,6 +93,7 @@ (Integer 2) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 2 (Integer 4)))] + FixedSizeArray ) () Source @@ -112,6 +115,7 @@ (Integer 2) [(() ())] + DescriptorArray ) ) () @@ -207,6 +211,7 @@ (Integer 2) [(() ())] + DescriptorArray ) ) () @@ -222,6 +227,7 @@ (Integer 2) [(() ())] + DescriptorArray ) ) () @@ -306,8 +312,9 @@ [(IntegerConstant 2 (Integer 4))] (Array (Integer 4) - [(() - ())] + [((IntegerConstant 0 (Integer 4)) + (IntegerConstant 1 (Integer 4)))] + PointerToDataArray ) RowMajor ) @@ -315,8 +322,9 @@ [(IntegerConstant 0 (Integer 4))] (Array (Integer 4) - [(() - ())] + [((IntegerConstant 0 (Integer 4)) + (IntegerConstant 1 (Integer 4)))] + PointerToDataArray ) RowMajor ) @@ -368,6 +376,7 @@ (Integer 2) [(() ())] + DescriptorArray ) ) () diff --git a/tests/reference/asr-bindc_10e-8b10394.json b/tests/reference/asr-bindc_10e-8b10394.json new file mode 100644 index 00000000000..9fdf2f9acd7 --- /dev/null +++ b/tests/reference/asr-bindc_10e-8b10394.json @@ -0,0 +1,13 @@ +{ + "basename": "asr-bindc_10e-8b10394", + "cmd": "lpython --show-asr --no-color {infile} -o {outfile}", + "infile": "tests/errors/bindc_10e.py", + "infile_hash": "36d1b5d366716d6a601db544fe8ff32aba76518181e71a98a4e6500c", + "outfile": null, + "outfile_hash": null, + "stdout": null, + "stdout_hash": null, + "stderr": "asr-bindc_10e-8b10394.stderr", + "stderr_hash": "7686dd8c9b718548d301e28d39cd15a85b00030172c5658b38a75af5", + "returncode": 2 +} \ No newline at end of file diff --git a/tests/reference/asr-bindc_10e-8b10394.stderr b/tests/reference/asr-bindc_10e-8b10394.stderr new file mode 100644 index 00000000000..3639b97f68f --- /dev/null +++ b/tests/reference/asr-bindc_10e-8b10394.stderr @@ -0,0 +1,12 @@ +semantic error: The struct in c_p_pointer must be C interoperable + --> tests/errors/bindc_10e.py:23:38 + | +23 | p2: Pointer[S] = c_p_pointer(p1, S) + | ^ not C interoperable + | +15 | class S: + | ~~~~~~~~... +... + | +17 | b: i64 + | ...~~~~~~~~~~ help: add the @ccallable decorator to this struct to make it C interoperable diff --git a/tests/reference/asr-doconcurrentloop_01-3fdc189.json b/tests/reference/asr-doconcurrentloop_01-3fdc189.json index 9c3bd214faf..2f90763b582 100644 --- a/tests/reference/asr-doconcurrentloop_01-3fdc189.json +++ b/tests/reference/asr-doconcurrentloop_01-3fdc189.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "asr-doconcurrentloop_01-3fdc189.stdout", - "stdout_hash": "74244cf5372405d26b361212fb85086ca79f4d632c49a8d7a0b90e3d", + "stdout_hash": "dd213c9b4fe8cfa0ab89cf81e7090a16d35f2d7b8582a87e2ae13fad", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/asr-doconcurrentloop_01-3fdc189.stdout b/tests/reference/asr-doconcurrentloop_01-3fdc189.stdout index bbd8377d50a..f460cc043e1 100644 --- a/tests/reference/asr-doconcurrentloop_01-3fdc189.stdout +++ b/tests/reference/asr-doconcurrentloop_01-3fdc189.stdout @@ -62,6 +62,7 @@ (Real 4) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 10000 (Integer 4)))] + FixedSizeArray ) () Source @@ -82,6 +83,7 @@ (Real 4) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 10000 (Integer 4)))] + FixedSizeArray ) () Source @@ -102,6 +104,7 @@ (Real 4) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 10000 (Integer 4)))] + FixedSizeArray ) () Source @@ -265,10 +268,43 @@ (SubroutineCall 8 triad () - [((Var 3 a)) - ((Var 3 b)) + [((ArrayPhysicalCast + (Var 3 a) + FixedSizeArray + DescriptorArray + (Array + (Real 4) + [((IntegerConstant 0 (Integer 4)) + (IntegerConstant 10000 (Integer 4)))] + DescriptorArray + ) + () + )) + ((ArrayPhysicalCast + (Var 3 b) + FixedSizeArray + DescriptorArray + (Array + (Real 4) + [((IntegerConstant 0 (Integer 4)) + (IntegerConstant 10000 (Integer 4)))] + DescriptorArray + ) + () + )) ((Var 3 scalar)) - ((Var 3 c))] + ((ArrayPhysicalCast + (Var 3 c) + FixedSizeArray + DescriptorArray + (Array + (Real 4) + [((IntegerConstant 0 (Integer 4)) + (IntegerConstant 10000 (Integer 4)))] + DescriptorArray + ) + () + ))] () ) (Print @@ -320,6 +356,7 @@ (Real 4) [(() ())] + DescriptorArray ) () Source @@ -340,6 +377,7 @@ (Real 4) [(() ())] + DescriptorArray ) () Source @@ -360,6 +398,7 @@ (Real 4) [(() ())] + DescriptorArray ) () Source @@ -406,17 +445,20 @@ (Real 4) [(() ())] + DescriptorArray ) (Array (Real 4) [(() ())] + DescriptorArray ) (Real 4) (Array (Real 4) [(() ())] + DescriptorArray )] () Source diff --git a/tests/reference/asr-elemental_01-b58df26.json b/tests/reference/asr-elemental_01-b58df26.json index 87547a90c69..1b2d41a2845 100644 --- a/tests/reference/asr-elemental_01-b58df26.json +++ b/tests/reference/asr-elemental_01-b58df26.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "asr-elemental_01-b58df26.stdout", - "stdout_hash": "61158069ffcb15b046dfda079ba33f849eefdfd1de6c08a815032e0b", + "stdout_hash": "d0c993d33c3eeab6546408d863d7a7a58d4b830498287b155c059b47", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/asr-elemental_01-b58df26.stdout b/tests/reference/asr-elemental_01-b58df26.stdout index a059af33fdd..13343f39502 100644 --- a/tests/reference/asr-elemental_01-b58df26.stdout +++ b/tests/reference/asr-elemental_01-b58df26.stdout @@ -102,6 +102,7 @@ (IntegerConstant 256 (Integer 4))) ((IntegerConstant 0 (Integer 4)) (IntegerConstant 64 (Integer 4)))] + FixedSizeArray ) () Source @@ -124,6 +125,7 @@ (IntegerConstant 256 (Integer 4))) ((IntegerConstant 0 (Integer 4)) (IntegerConstant 64 (Integer 4)))] + FixedSizeArray ) () Source @@ -259,6 +261,7 @@ (IntegerConstant 256 (Integer 4))) ((IntegerConstant 0 (Integer 4)) (IntegerConstant 64 (Integer 4)))] + FixedSizeArray ) () () @@ -274,6 +277,7 @@ (IntegerConstant 256 (Integer 4))) ((IntegerConstant 0 (Integer 4)) (IntegerConstant 64 (Integer 4)))] + FixedSizeArray ) () ) @@ -282,8 +286,34 @@ (SubroutineCall 234 verify2d () - [((Var 207 array2d)) - ((Var 207 cos2d)) + [((ArrayPhysicalCast + (Var 207 array2d) + FixedSizeArray + DescriptorArray + (Array + (Real 8) + [((IntegerConstant 0 (Integer 4)) + (IntegerConstant 256 (Integer 4))) + ((IntegerConstant 0 (Integer 4)) + (IntegerConstant 64 (Integer 4)))] + DescriptorArray + ) + () + )) + ((ArrayPhysicalCast + (Var 207 cos2d) + FixedSizeArray + DescriptorArray + (Array + (Real 8) + [((IntegerConstant 0 (Integer 4)) + (IntegerConstant 256 (Integer 4))) + ((IntegerConstant 0 (Integer 4)) + (IntegerConstant 64 (Integer 4)))] + DescriptorArray + ) + () + )) ((IntegerConstant 256 (Integer 4))) ((IntegerConstant 64 (Integer 4)))] () @@ -312,6 +342,7 @@ (Real 8) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 100 (Integer 4)))] + FixedSizeArray ) () Source @@ -332,6 +363,7 @@ (Real 8) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 100 (Integer 4)))] + FixedSizeArray ) () Source @@ -352,6 +384,7 @@ (Real 8) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 100 (Integer 4)))] + FixedSizeArray ) () Source @@ -509,6 +542,7 @@ (Real 8) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 100 (Integer 4)))] + FixedSizeArray ) () ) @@ -521,6 +555,7 @@ (Real 8) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 100 (Integer 4)))] + FixedSizeArray ) () ) @@ -536,6 +571,7 @@ (Real 8) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 100 (Integer 4)))] + FixedSizeArray ) () ) @@ -543,6 +579,7 @@ (Real 8) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 100 (Integer 4)))] + FixedSizeArray ) () ) @@ -551,9 +588,42 @@ (SubroutineCall 234 verify1d_mul () - [((Var 205 array_a)) - ((Var 205 array_b)) - ((Var 205 array_c)) + [((ArrayPhysicalCast + (Var 205 array_a) + FixedSizeArray + DescriptorArray + (Array + (Real 8) + [((IntegerConstant 0 (Integer 4)) + (IntegerConstant 100 (Integer 4)))] + DescriptorArray + ) + () + )) + ((ArrayPhysicalCast + (Var 205 array_b) + FixedSizeArray + DescriptorArray + (Array + (Real 8) + [((IntegerConstant 0 (Integer 4)) + (IntegerConstant 100 (Integer 4)))] + DescriptorArray + ) + () + )) + ((ArrayPhysicalCast + (Var 205 array_c) + FixedSizeArray + DescriptorArray + (Array + (Real 8) + [((IntegerConstant 0 (Integer 4)) + (IntegerConstant 100 (Integer 4)))] + DescriptorArray + ) + () + )) ((IntegerConstant 100 (Integer 4)))] () )] @@ -581,6 +651,7 @@ (Real 4) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 256 (Integer 4)))] + FixedSizeArray ) () Source @@ -605,6 +676,7 @@ (IntegerConstant 64 (Integer 4))) ((IntegerConstant 0 (Integer 4)) (IntegerConstant 16 (Integer 4)))] + FixedSizeArray ) () Source @@ -673,6 +745,7 @@ (Real 4) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 256 (Integer 4)))] + FixedSizeArray ) () Source @@ -717,6 +790,7 @@ (IntegerConstant 64 (Integer 4))) ((IntegerConstant 0 (Integer 4)) (IntegerConstant 16 (Integer 4)))] + FixedSizeArray ) () Source @@ -790,6 +864,7 @@ (Real 4) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 256 (Integer 4)))] + FixedSizeArray ) () () @@ -798,6 +873,7 @@ (Real 4) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 256 (Integer 4)))] + FixedSizeArray ) () () @@ -807,8 +883,30 @@ (SubroutineCall 234 verify1d () - [((Var 206 array1d)) - ((Var 206 sin1d)) + [((ArrayPhysicalCast + (Var 206 array1d) + FixedSizeArray + DescriptorArray + (Array + (Real 4) + [((IntegerConstant 0 (Integer 4)) + (IntegerConstant 256 (Integer 4)))] + DescriptorArray + ) + () + )) + ((ArrayPhysicalCast + (Var 206 sin1d) + FixedSizeArray + DescriptorArray + (Array + (Real 4) + [((IntegerConstant 0 (Integer 4)) + (IntegerConstant 256 (Integer 4)))] + DescriptorArray + ) + () + )) ((IntegerConstant 256 (Integer 4)))] () ) @@ -902,6 +1000,7 @@ (IntegerConstant 64 (Integer 4))) ((IntegerConstant 0 (Integer 4)) (IntegerConstant 16 (Integer 4)))] + FixedSizeArray ) () () @@ -919,6 +1018,7 @@ (IntegerConstant 64 (Integer 4))) ((IntegerConstant 0 (Integer 4)) (IntegerConstant 16 (Integer 4)))] + FixedSizeArray ) () ) @@ -927,8 +1027,38 @@ (SubroutineCall 234 verifynd () - [((Var 206 arraynd)) - ((Var 206 sinnd)) + [((ArrayPhysicalCast + (Var 206 arraynd) + FixedSizeArray + DescriptorArray + (Array + (Real 8) + [((IntegerConstant 0 (Integer 4)) + (IntegerConstant 256 (Integer 4))) + ((IntegerConstant 0 (Integer 4)) + (IntegerConstant 64 (Integer 4))) + ((IntegerConstant 0 (Integer 4)) + (IntegerConstant 16 (Integer 4)))] + DescriptorArray + ) + () + )) + ((ArrayPhysicalCast + (Var 206 sinnd) + FixedSizeArray + DescriptorArray + (Array + (Real 8) + [((IntegerConstant 0 (Integer 4)) + (IntegerConstant 256 (Integer 4))) + ((IntegerConstant 0 (Integer 4)) + (IntegerConstant 64 (Integer 4))) + ((IntegerConstant 0 (Integer 4)) + (IntegerConstant 16 (Integer 4)))] + DescriptorArray + ) + () + )) ((IntegerConstant 256 (Integer 4))) ((IntegerConstant 64 (Integer 4))) ((IntegerConstant 16 (Integer 4)))] @@ -958,6 +1088,7 @@ (Real 8) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 100 (Integer 4)))] + FixedSizeArray ) () Source @@ -978,6 +1109,7 @@ (Real 8) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 100 (Integer 4)))] + FixedSizeArray ) () Source @@ -998,6 +1130,7 @@ (Real 8) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 100 (Integer 4)))] + FixedSizeArray ) () Source @@ -1154,6 +1287,7 @@ (Real 8) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 100 (Integer 4)))] + FixedSizeArray ) () ) @@ -1175,6 +1309,7 @@ (Real 8) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 100 (Integer 4)))] + FixedSizeArray ) () ) @@ -1182,6 +1317,7 @@ (Real 8) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 100 (Integer 4)))] + FixedSizeArray ) () ) @@ -1189,6 +1325,7 @@ (Real 8) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 100 (Integer 4)))] + FixedSizeArray ) () ) @@ -1197,9 +1334,42 @@ (SubroutineCall 234 verify1d_sum () - [((Var 204 array_a)) - ((Var 204 array_b)) - ((Var 204 array_c)) + [((ArrayPhysicalCast + (Var 204 array_a) + FixedSizeArray + DescriptorArray + (Array + (Real 8) + [((IntegerConstant 0 (Integer 4)) + (IntegerConstant 100 (Integer 4)))] + DescriptorArray + ) + () + )) + ((ArrayPhysicalCast + (Var 204 array_b) + FixedSizeArray + DescriptorArray + (Array + (Real 8) + [((IntegerConstant 0 (Integer 4)) + (IntegerConstant 100 (Integer 4)))] + DescriptorArray + ) + () + )) + ((ArrayPhysicalCast + (Var 204 array_c) + FixedSizeArray + DescriptorArray + (Array + (Real 8) + [((IntegerConstant 0 (Integer 4)) + (IntegerConstant 100 (Integer 4)))] + DescriptorArray + ) + () + )) ((IntegerConstant 100 (Integer 4)))] () )] @@ -1233,6 +1403,7 @@ (IntegerConstant 8 (Integer 4))) ((IntegerConstant 0 (Integer 4)) (IntegerConstant 4 (Integer 4)))] + FixedSizeArray ) () Source @@ -1343,6 +1514,7 @@ (Integer 4) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 1 (Integer 4)))] + FixedSizeArray ) () Source @@ -1369,6 +1541,7 @@ (IntegerConstant 8 (Integer 4))) ((IntegerConstant 0 (Integer 4)) (IntegerConstant 4 (Integer 4)))] + FixedSizeArray ) () Source @@ -1389,6 +1562,7 @@ (Real 4) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 65536 (Integer 4)))] + FixedSizeArray ) () Source @@ -1557,6 +1731,7 @@ (IntegerConstant 8 (Integer 4))) ((IntegerConstant 0 (Integer 4)) (IntegerConstant 4 (Integer 4)))] + FixedSizeArray ) () () @@ -1581,6 +1756,7 @@ (IntegerConstant 8 (Integer 4))) ((IntegerConstant 0 (Integer 4)) (IntegerConstant 4 (Integer 4)))] + FixedSizeArray ) () ) @@ -1600,6 +1776,7 @@ (IntegerConstant 8 (Integer 4))) ((IntegerConstant 0 (Integer 4)) (IntegerConstant 4 (Integer 4)))] + FixedSizeArray ) () () @@ -1624,6 +1801,7 @@ (IntegerConstant 8 (Integer 4))) ((IntegerConstant 0 (Integer 4)) (IntegerConstant 4 (Integer 4)))] + FixedSizeArray ) () ) @@ -1637,6 +1815,7 @@ (IntegerConstant 8 (Integer 4))) ((IntegerConstant 0 (Integer 4)) (IntegerConstant 4 (Integer 4)))] + FixedSizeArray ) () ) @@ -1659,11 +1838,23 @@ (Var 208 observed1d) (ArrayReshape (Var 208 observed) - (Var 208 newshape) + (ArrayPhysicalCast + (Var 208 newshape) + FixedSizeArray + DescriptorArray + (Array + (Integer 4) + [((IntegerConstant 0 (Integer 4)) + (IntegerConstant 1 (Integer 4)))] + DescriptorArray + ) + () + ) (Array (Real 4) [(() ())] + FixedSizeArray ) () ) @@ -1757,6 +1948,7 @@ (Real 4) [(() ())] + DescriptorArray ) () Source @@ -1879,6 +2071,7 @@ (Real 4) [(() ())] + DescriptorArray ) () Source @@ -1909,11 +2102,13 @@ (Real 4) [(() ())] + DescriptorArray ) (Array (Real 4) [(() ())] + DescriptorArray ) (Integer 4)] () @@ -1990,6 +2185,7 @@ (Real 8) [(() ())] + DescriptorArray ) () Source @@ -2010,6 +2206,7 @@ (Real 8) [(() ())] + DescriptorArray ) () Source @@ -2062,6 +2259,7 @@ (Real 8) [(() ())] + DescriptorArray ) () Source @@ -2092,16 +2290,19 @@ (Real 8) [(() ())] + DescriptorArray ) (Array (Real 8) [(() ())] + DescriptorArray ) (Array (Real 8) [(() ())] + DescriptorArray ) (Integer 4)] () @@ -2246,6 +2447,7 @@ (Real 8) [(() ())] + DescriptorArray ) () Source @@ -2266,6 +2468,7 @@ (Real 8) [(() ())] + DescriptorArray ) () Source @@ -2318,6 +2521,7 @@ (Real 8) [(() ())] + DescriptorArray ) () Source @@ -2348,16 +2552,19 @@ (Real 8) [(() ())] + DescriptorArray ) (Array (Real 8) [(() ())] + DescriptorArray ) (Array (Real 8) [(() ())] + DescriptorArray ) (Integer 4)] () @@ -2504,6 +2711,7 @@ ()) (() ())] + DescriptorArray ) () Source @@ -2677,6 +2885,7 @@ ()) (() ())] + DescriptorArray ) () Source @@ -2725,6 +2934,7 @@ ()) (() ())] + DescriptorArray ) (Array (Real 8) @@ -2732,6 +2942,7 @@ ()) (() ())] + DescriptorArray ) (Integer 4) (Integer 4)] @@ -2806,6 +3017,7 @@ ()) (() ())] + DescriptorArray ) () Source @@ -3028,6 +3240,7 @@ ()) (() ())] + DescriptorArray ) () Source @@ -3094,6 +3307,7 @@ ()) (() ())] + DescriptorArray ) (Array (Real 8) @@ -3103,6 +3317,7 @@ ()) (() ())] + DescriptorArray ) (Integer 4) (Integer 4) diff --git a/tests/reference/asr-expr_12-6769be0.json b/tests/reference/asr-expr_12-6769be0.json index f7ad74733bd..9699ab9a3d3 100644 --- a/tests/reference/asr-expr_12-6769be0.json +++ b/tests/reference/asr-expr_12-6769be0.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "asr-expr_12-6769be0.stdout", - "stdout_hash": "5049609cf0d50065252a9e535119b51be290937f8238db73af193736", + "stdout_hash": "8f98ad27c6cc615827836082365c3b5cfb299c5630f1b30bd012c6e4", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/asr-expr_12-6769be0.stdout b/tests/reference/asr-expr_12-6769be0.stdout index 69fc2fc509c..08b776e2cc9 100644 --- a/tests/reference/asr-expr_12-6769be0.stdout +++ b/tests/reference/asr-expr_12-6769be0.stdout @@ -63,6 +63,7 @@ (Integer 2) [(() ())] + DescriptorArray ) ) () @@ -79,6 +80,7 @@ (Integer 2) [(() ())] + DescriptorArray ) )] () @@ -166,6 +168,7 @@ (Integer 2) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 2 (Integer 4)))] + FixedSizeArray ) () Source @@ -187,6 +190,7 @@ (Integer 2) [(() ())] + DescriptorArray ) ) () @@ -219,7 +223,18 @@ 7 g () [((Var 4 yptr1)) - ((Var 4 y))] + ((ArrayPhysicalCast + (Var 4 y) + FixedSizeArray + DescriptorArray + (Array + (Integer 2) + [((IntegerConstant 0 (Integer 4)) + (IntegerConstant 2 (Integer 4)))] + DescriptorArray + ) + () + ))] () ) (SubroutineCall @@ -253,6 +268,7 @@ (Integer 2) [(() ())] + DescriptorArray ) ) () @@ -274,6 +290,7 @@ (Integer 2) [(() ())] + DescriptorArray ) () Source @@ -289,12 +306,14 @@ (Integer 2) [(() ())] + DescriptorArray ) ) (Array (Integer 2) [(() ())] + DescriptorArray )] () Source @@ -357,6 +376,7 @@ (Integer 2) [(() ())] + DescriptorArray ) ) () diff --git a/tests/reference/asr-func_07-4a8c076.json b/tests/reference/asr-func_07-4a8c076.json index 38289e04a39..23a3ff6d218 100644 --- a/tests/reference/asr-func_07-4a8c076.json +++ b/tests/reference/asr-func_07-4a8c076.json @@ -8,6 +8,6 @@ "stdout": null, "stdout_hash": null, "stderr": "asr-func_07-4a8c076.stderr", - "stderr_hash": "f318e29b96f7730e9ed5fd89ae43e851f22bf50a5c3b2bde415e24e2", + "stderr_hash": "7ed110581f050d55b95ace1c09b3dc30176b30213c125e3ec19f5c68", "returncode": 2 } \ No newline at end of file diff --git a/tests/reference/asr-func_07-4a8c076.stderr b/tests/reference/asr-func_07-4a8c076.stderr index eba5600657e..d876637cc3e 100644 --- a/tests/reference/asr-func_07-4a8c076.stderr +++ b/tests/reference/asr-func_07-4a8c076.stderr @@ -2,4 +2,4 @@ semantic error: Assignment to an input function parameter `this` is not allowed --> tests/errors/func_07.py:12:5 | 12 | this._len = len(this._buf) - | ^^^^ Use InOut[StringIO] to allow assignment + | ^^^^ Use InOut[struct StringIO] to allow assignment diff --git a/tests/reference/asr-generics_array_01-682b1b2.json b/tests/reference/asr-generics_array_01-682b1b2.json index 9e9d2a23eb1..7a7ec5e99db 100644 --- a/tests/reference/asr-generics_array_01-682b1b2.json +++ b/tests/reference/asr-generics_array_01-682b1b2.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "asr-generics_array_01-682b1b2.stdout", - "stdout_hash": "7dca5c2f206b956b59f657b943e347c7b9e03cb20683ee6f9b1872e5", + "stdout_hash": "4526d79d8852d9987685aab247d0936806fbc1e735dcdf210a51ce6c", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/asr-generics_array_01-682b1b2.stdout b/tests/reference/asr-generics_array_01-682b1b2.stdout index 145f2c3bccc..ee31822975e 100644 --- a/tests/reference/asr-generics_array_01-682b1b2.stdout +++ b/tests/reference/asr-generics_array_01-682b1b2.stdout @@ -75,6 +75,7 @@ (Integer 4) [(() ())] + DescriptorArray ) () Source @@ -89,6 +90,7 @@ (Integer 4) [(() ())] + DescriptorArray ) (Integer 4)] (Integer 4) @@ -233,6 +235,7 @@ ) [(() ())] + DescriptorArray ) () Source @@ -249,6 +252,7 @@ ) [(() ())] + DescriptorArray ) (TypeParameter T @@ -328,6 +332,7 @@ (Integer 4) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 1 (Integer 4)))] + FixedSizeArray ) () Source @@ -380,7 +385,18 @@ [(FunctionCall 204 __asr_generic_f_0 () - [((Var 200 array)) + [((ArrayPhysicalCast + (Var 200 array) + FixedSizeArray + DescriptorArray + (Array + (Integer 4) + [((IntegerConstant 0 (Integer 4)) + (IntegerConstant 1 (Integer 4)))] + DescriptorArray + ) + () + )) ((Var 200 x))] (Integer 4) () diff --git a/tests/reference/asr-generics_array_02-22c8dc1.json b/tests/reference/asr-generics_array_02-22c8dc1.json index fa91aca0a68..da6b011b5b2 100644 --- a/tests/reference/asr-generics_array_02-22c8dc1.json +++ b/tests/reference/asr-generics_array_02-22c8dc1.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "asr-generics_array_02-22c8dc1.stdout", - "stdout_hash": "5e85d59b00e32dd05b50f461af3af3a6022c870828fdbc548930d40e", + "stdout_hash": "abbe2f660b512c10aabf92c0aaaf31ded8e350ab7cb23a12333167c0", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/asr-generics_array_02-22c8dc1.stdout b/tests/reference/asr-generics_array_02-22c8dc1.stdout index d22d2155272..82c99fe16d4 100644 --- a/tests/reference/asr-generics_array_02-22c8dc1.stdout +++ b/tests/reference/asr-generics_array_02-22c8dc1.stdout @@ -43,6 +43,7 @@ (Integer 4) [((IntegerConstant 0 (Integer 4)) (Var 205 n))] + PointerToDataArray ) () Source @@ -63,6 +64,7 @@ (Integer 4) [((IntegerConstant 0 (Integer 4)) (Var 205 n))] + PointerToDataArray ) () Source @@ -115,6 +117,7 @@ (Integer 4) [((IntegerConstant 0 (Integer 4)) (Var 205 n))] + PointerToDataArray ) () Source @@ -134,6 +137,7 @@ (Integer 4) () ))] + PointerToDataArray ) (Array (Integer 4) @@ -143,6 +147,7 @@ (Integer 4) () ))] + PointerToDataArray )] () Source @@ -249,6 +254,7 @@ (Real 4) [((IntegerConstant 0 (Integer 4)) (Var 206 n))] + PointerToDataArray ) () Source @@ -269,6 +275,7 @@ (Real 4) [((IntegerConstant 0 (Integer 4)) (Var 206 n))] + PointerToDataArray ) () Source @@ -321,6 +328,7 @@ (Real 4) [((IntegerConstant 0 (Integer 4)) (Var 206 n))] + PointerToDataArray ) () Source @@ -340,6 +348,7 @@ (Integer 4) () ))] + PointerToDataArray ) (Array (Real 4) @@ -349,6 +358,7 @@ (Integer 4) () ))] + PointerToDataArray )] () Source @@ -773,6 +783,7 @@ ) [((IntegerConstant 0 (Integer 4)) (Var 202 n))] + PointerToDataArray ) () Source @@ -795,6 +806,7 @@ ) [((IntegerConstant 0 (Integer 4)) (Var 202 n))] + PointerToDataArray ) () Source @@ -849,6 +861,7 @@ ) [((IntegerConstant 0 (Integer 4)) (Var 202 n))] + PointerToDataArray ) () Source @@ -870,6 +883,7 @@ (Integer 4) () ))] + PointerToDataArray ) (Array (TypeParameter @@ -881,6 +895,7 @@ (Integer 4) () ))] + PointerToDataArray )] () Source @@ -999,6 +1014,7 @@ (Real 4) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 1 (Integer 4)))] + FixedSizeArray ) () Source @@ -1019,6 +1035,7 @@ (Integer 4) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 1 (Integer 4)))] + FixedSizeArray ) () Source @@ -1039,6 +1056,7 @@ (Real 4) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 1 (Integer 4)))] + FixedSizeArray ) () Source @@ -1059,6 +1077,7 @@ (Integer 4) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 1 (Integer 4)))] + FixedSizeArray ) () Source @@ -1116,8 +1135,30 @@ 209 __asr_generic_g_0 () [((IntegerConstant 1 (Integer 4))) - ((Var 203 a_int)) - ((Var 203 b_int))] + ((ArrayPhysicalCast + (Var 203 a_int) + FixedSizeArray + PointerToDataArray + (Array + (Integer 4) + [((IntegerConstant 0 (Integer 4)) + (IntegerConstant 1 (Integer 4)))] + PointerToDataArray + ) + () + )) + ((ArrayPhysicalCast + (Var 203 b_int) + FixedSizeArray + PointerToDataArray + (Array + (Integer 4) + [((IntegerConstant 0 (Integer 4)) + (IntegerConstant 1 (Integer 4)))] + PointerToDataArray + ) + () + ))] () ) (= @@ -1172,8 +1213,30 @@ 209 __asr_generic_g_1 () [((IntegerConstant 1 (Integer 4))) - ((Var 203 a_float)) - ((Var 203 b_float))] + ((ArrayPhysicalCast + (Var 203 a_float) + FixedSizeArray + PointerToDataArray + (Array + (Real 4) + [((IntegerConstant 0 (Integer 4)) + (IntegerConstant 1 (Integer 4)))] + PointerToDataArray + ) + () + )) + ((ArrayPhysicalCast + (Var 203 b_float) + FixedSizeArray + PointerToDataArray + (Array + (Real 4) + [((IntegerConstant 0 (Integer 4)) + (IntegerConstant 1 (Integer 4)))] + PointerToDataArray + ) + () + ))] () )] () diff --git a/tests/reference/asr-generics_array_03-fb3706c.json b/tests/reference/asr-generics_array_03-fb3706c.json index d355f22f9df..176b0bfc136 100644 --- a/tests/reference/asr-generics_array_03-fb3706c.json +++ b/tests/reference/asr-generics_array_03-fb3706c.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "asr-generics_array_03-fb3706c.stdout", - "stdout_hash": "42869d188b1f1973835a818e0e62f1d60f5ce83e73d4fd34724cfe5d", + "stdout_hash": "c8b00a7b7e1d02b961328430618730c759e69fc4d5e71d294ac8538f", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/asr-generics_array_03-fb3706c.stdout b/tests/reference/asr-generics_array_03-fb3706c.stdout index fc1e4ef7b47..e8bfa98aca2 100644 --- a/tests/reference/asr-generics_array_03-fb3706c.stdout +++ b/tests/reference/asr-generics_array_03-fb3706c.stdout @@ -46,6 +46,7 @@ (Var 206 n)) ((IntegerConstant 0 (Integer 4)) (Var 206 m))] + PointerToDataArray ) () Source @@ -69,6 +70,7 @@ (Var 206 n)) ((IntegerConstant 0 (Integer 4)) (Var 206 m))] + PointerToDataArray ) () Source @@ -92,6 +94,7 @@ (Var 206 n)) ((IntegerConstant 0 (Integer 4)) (Var 206 m))] + PointerToDataArray ) () Source @@ -179,6 +182,7 @@ (Var 206 n)) ((IntegerConstant 0 (Integer 4)) (Var 206 m))] + PointerToDataArray ) () Source @@ -205,6 +209,7 @@ (Integer 4) () ))] + PointerToDataArray ) (Array (Integer 4) @@ -220,6 +225,7 @@ (Integer 4) () ))] + PointerToDataArray )] (Array (Integer 4) @@ -235,6 +241,7 @@ (Integer 4) () ))] + PointerToDataArray ) Source Implementation @@ -369,6 +376,7 @@ (Var 207 n)) ((IntegerConstant 0 (Integer 4)) (Var 207 m))] + PointerToDataArray ) () Source @@ -392,6 +400,7 @@ (Var 207 n)) ((IntegerConstant 0 (Integer 4)) (Var 207 m))] + PointerToDataArray ) () Source @@ -415,6 +424,7 @@ (Var 207 n)) ((IntegerConstant 0 (Integer 4)) (Var 207 m))] + PointerToDataArray ) () Source @@ -502,6 +512,7 @@ (Var 207 n)) ((IntegerConstant 0 (Integer 4)) (Var 207 m))] + PointerToDataArray ) () Source @@ -528,6 +539,7 @@ (Integer 4) () ))] + PointerToDataArray ) (Array (Real 4) @@ -543,6 +555,7 @@ (Integer 4) () ))] + PointerToDataArray )] (Array (Real 4) @@ -558,6 +571,7 @@ (Integer 4) () ))] + PointerToDataArray ) Source Implementation @@ -1010,6 +1024,7 @@ (Var 202 n)) ((IntegerConstant 0 (Integer 4)) (Var 202 m))] + PointerToDataArray ) () Source @@ -1035,6 +1050,7 @@ (Var 202 n)) ((IntegerConstant 0 (Integer 4)) (Var 202 m))] + PointerToDataArray ) () Source @@ -1060,6 +1076,7 @@ (Var 202 n)) ((IntegerConstant 0 (Integer 4)) (Var 202 m))] + PointerToDataArray ) () Source @@ -1149,6 +1166,7 @@ (Var 202 n)) ((IntegerConstant 0 (Integer 4)) (Var 202 m))] + PointerToDataArray ) () Source @@ -1177,6 +1195,7 @@ (Integer 4) () ))] + PointerToDataArray ) (Array (TypeParameter @@ -1194,6 +1213,7 @@ (Integer 4) () ))] + PointerToDataArray )] (Array (TypeParameter @@ -1211,6 +1231,7 @@ (Integer 4) () ))] + PointerToDataArray ) Source Implementation @@ -1372,6 +1393,7 @@ (IntegerConstant 1 (Integer 4))) ((IntegerConstant 0 (Integer 4)) (IntegerConstant 1 (Integer 4)))] + FixedSizeArray ) () Source @@ -1394,6 +1416,7 @@ (IntegerConstant 1 (Integer 4))) ((IntegerConstant 0 (Integer 4)) (IntegerConstant 1 (Integer 4)))] + FixedSizeArray ) () Source @@ -1416,6 +1439,7 @@ (IntegerConstant 1 (Integer 4))) ((IntegerConstant 0 (Integer 4)) (IntegerConstant 1 (Integer 4)))] + FixedSizeArray ) () Source @@ -1438,6 +1462,7 @@ (IntegerConstant 1 (Integer 4))) ((IntegerConstant 0 (Integer 4)) (IntegerConstant 1 (Integer 4)))] + FixedSizeArray ) () Source @@ -1460,6 +1485,7 @@ (IntegerConstant 1 (Integer 4))) ((IntegerConstant 0 (Integer 4)) (IntegerConstant 1 (Integer 4)))] + FixedSizeArray ) () Source @@ -1482,6 +1508,7 @@ (IntegerConstant 1 (Integer 4))) ((IntegerConstant 0 (Integer 4)) (IntegerConstant 1 (Integer 4)))] + FixedSizeArray ) () Source @@ -1548,14 +1575,41 @@ () [((IntegerConstant 1 (Integer 4))) ((IntegerConstant 1 (Integer 4))) - ((Var 203 a_int)) - ((Var 203 b_int))] + ((ArrayPhysicalCast + (Var 203 a_int) + FixedSizeArray + PointerToDataArray + (Array + (Integer 4) + [((IntegerConstant 0 (Integer 4)) + (IntegerConstant 1 (Integer 4))) + ((IntegerConstant 0 (Integer 4)) + (IntegerConstant 1 (Integer 4)))] + PointerToDataArray + ) + () + )) + ((ArrayPhysicalCast + (Var 203 b_int) + FixedSizeArray + PointerToDataArray + (Array + (Integer 4) + [((IntegerConstant 0 (Integer 4)) + (IntegerConstant 1 (Integer 4))) + ((IntegerConstant 0 (Integer 4)) + (IntegerConstant 1 (Integer 4)))] + PointerToDataArray + ) + () + ))] (Array (Integer 4) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 1 (Integer 4))) ((IntegerConstant 0 (Integer 4)) (IntegerConstant 1 (Integer 4)))] + FixedSizeArray ) () () @@ -1617,14 +1671,41 @@ () [((IntegerConstant 1 (Integer 4))) ((IntegerConstant 1 (Integer 4))) - ((Var 203 a_float)) - ((Var 203 b_float))] + ((ArrayPhysicalCast + (Var 203 a_float) + FixedSizeArray + PointerToDataArray + (Array + (Real 4) + [((IntegerConstant 0 (Integer 4)) + (IntegerConstant 1 (Integer 4))) + ((IntegerConstant 0 (Integer 4)) + (IntegerConstant 1 (Integer 4)))] + PointerToDataArray + ) + () + )) + ((ArrayPhysicalCast + (Var 203 b_float) + FixedSizeArray + PointerToDataArray + (Array + (Real 4) + [((IntegerConstant 0 (Integer 4)) + (IntegerConstant 1 (Integer 4))) + ((IntegerConstant 0 (Integer 4)) + (IntegerConstant 1 (Integer 4)))] + PointerToDataArray + ) + () + ))] (Array (Real 4) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 1 (Integer 4))) ((IntegerConstant 0 (Integer 4)) (IntegerConstant 1 (Integer 4)))] + FixedSizeArray ) () () diff --git a/tests/reference/asr-intent_01-66824bc.json b/tests/reference/asr-intent_01-66824bc.json index a78386d9735..ed35aec8f99 100644 --- a/tests/reference/asr-intent_01-66824bc.json +++ b/tests/reference/asr-intent_01-66824bc.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "asr-intent_01-66824bc.stdout", - "stdout_hash": "c0705fb1198e342bcc4b376fd83d8b981654f48cf14b8e563bb0ed2e", + "stdout_hash": "39edbdbd6bb1570dc829762e3103fac7b4bec3b2a408509f92b5e87f", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/asr-intent_01-66824bc.stdout b/tests/reference/asr-intent_01-66824bc.stdout index aa571599884..fdda73b1bc8 100644 --- a/tests/reference/asr-intent_01-66824bc.stdout +++ b/tests/reference/asr-intent_01-66824bc.stdout @@ -60,6 +60,7 @@ ) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 5 (Integer 4)))] + PointerToDataArray ) () Source @@ -135,6 +136,7 @@ ) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 5 (Integer 4)))] + PointerToDataArray )] () Source diff --git a/tests/reference/asr-structs_02-2ab459a.json b/tests/reference/asr-structs_02-2ab459a.json index 2056a9f8321..4d7980c0f17 100644 --- a/tests/reference/asr-structs_02-2ab459a.json +++ b/tests/reference/asr-structs_02-2ab459a.json @@ -2,11 +2,11 @@ "basename": "asr-structs_02-2ab459a", "cmd": "lpython --show-asr --no-color {infile} -o {outfile}", "infile": "tests/../integration_tests/structs_02.py", - "infile_hash": "6d54aa7c2bb850cbce2c0add7b77f9f72c9323162ae080c7eef4867a", + "infile_hash": "281bc75fb743f18fb6f011b278d7ab8103cc688f5856a59cb1f54895", "outfile": null, "outfile_hash": null, "stdout": "asr-structs_02-2ab459a.stdout", - "stdout_hash": "e5df0fb84bfc694b884736c1c4a5ddaec25933d8dba54e894de3e961", + "stdout_hash": "3a3e1108225886c52d459a08a26d5b35d4aea338982034d43079769d", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/asr-structs_02-2ab459a.stdout b/tests/reference/asr-structs_02-2ab459a.stdout index feaf95ffa61..83bfd63a07c 100644 --- a/tests/reference/asr-structs_02-2ab459a.stdout +++ b/tests/reference/asr-structs_02-2ab459a.stdout @@ -304,28 +304,6 @@ () ) () - ) - (CPtrToPointer - (Var 3 a) - (Var 3 a2) - () - () - ) - (Print - () - [(Var 3 a) - (Var 3 a2) - (GetPointer - (Var 3 a1) - (Pointer - (Struct - 8 A - ) - ) - () - )] - () - () )] () Public diff --git a/tests/reference/asr-structs_02-f95782c.json b/tests/reference/asr-structs_02-f95782c.json index fa782be8d7f..c7ea7537c12 100644 --- a/tests/reference/asr-structs_02-f95782c.json +++ b/tests/reference/asr-structs_02-f95782c.json @@ -8,6 +8,6 @@ "stdout": null, "stdout_hash": null, "stderr": "asr-structs_02-f95782c.stderr", - "stderr_hash": "e77891a7762fcd30afe98c91c7ffeae4342b646a0d44eebd2cb08f1b", + "stderr_hash": "832411f3c9770493283e58b9017703a7d1cd178f42a19da6f8a38571", "returncode": 2 } \ No newline at end of file diff --git a/tests/reference/asr-structs_02-f95782c.stderr b/tests/reference/asr-structs_02-f95782c.stderr index 55efe8b586c..e087537e578 100644 --- a/tests/reference/asr-structs_02-f95782c.stderr +++ b/tests/reference/asr-structs_02-f95782c.stderr @@ -1,4 +1,4 @@ -semantic error: `s` must be initialized with an instance of S +semantic error: `s` must be initialized with an instance of struct S --> tests/errors/structs_02.py:8:5 | 8 | s: S diff --git a/tests/reference/asr-structs_05-fa98307.json b/tests/reference/asr-structs_05-fa98307.json index 152e6eb1c33..fa3c4115031 100644 --- a/tests/reference/asr-structs_05-fa98307.json +++ b/tests/reference/asr-structs_05-fa98307.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "asr-structs_05-fa98307.stdout", - "stdout_hash": "89178aaa9800865290a98917ec98733999257c474639ebb3019454bc", + "stdout_hash": "126996c1bff76c9dc4827514d19dcdb2c6380400ffdc1eaacd778df5", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/asr-structs_05-fa98307.stdout b/tests/reference/asr-structs_05-fa98307.stdout index bcdae0a6ce3..0394efb58f2 100644 --- a/tests/reference/asr-structs_05-fa98307.stdout +++ b/tests/reference/asr-structs_05-fa98307.stdout @@ -205,6 +205,7 @@ ) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 2 (Integer 4)))] + FixedSizeArray ) () Source @@ -356,7 +357,20 @@ (SubroutineCall 207 verify () - [((Var 203 y)) + [((ArrayPhysicalCast + (Var 203 y) + FixedSizeArray + DescriptorArray + (Array + (Struct + 207 A + ) + [((IntegerConstant 0 (Integer 4)) + (IntegerConstant 2 (Integer 4)))] + DescriptorArray + ) + () + )) ((IntegerConstant 1 (Integer 4))) ((RealConstant 1.100000 @@ -388,13 +402,39 @@ (SubroutineCall 207 update_2 () - [((Var 203 y))] + [((ArrayPhysicalCast + (Var 203 y) + FixedSizeArray + DescriptorArray + (Array + (Struct + 207 A + ) + [((IntegerConstant 0 (Integer 4)) + (IntegerConstant 2 (Integer 4)))] + DescriptorArray + ) + () + ))] () ) (SubroutineCall 207 verify () - [((Var 203 y)) + [((ArrayPhysicalCast + (Var 203 y) + FixedSizeArray + DescriptorArray + (Array + (Struct + 207 A + ) + [((IntegerConstant 0 (Integer 4)) + (IntegerConstant 2 (Integer 4)))] + DescriptorArray + ) + () + )) ((IntegerConstant 2 (Integer 4))) ((RealConstant 1.200000 @@ -572,6 +612,7 @@ ) [(() ())] + DescriptorArray ) () Source @@ -588,6 +629,7 @@ ) [(() ())] + DescriptorArray )] () Source @@ -795,6 +837,7 @@ ) [(() ())] + DescriptorArray ) () Source @@ -911,6 +954,7 @@ ) [(() ())] + DescriptorArray ) (Integer 4) (Real 8) diff --git a/tests/reference/asr-subscript1-1acfc19.json b/tests/reference/asr-subscript1-1acfc19.json index 8b0f04438d0..81892b1c868 100644 --- a/tests/reference/asr-subscript1-1acfc19.json +++ b/tests/reference/asr-subscript1-1acfc19.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "asr-subscript1-1acfc19.stdout", - "stdout_hash": "525763c986157dbbe39b072c5a099773d34a0721f114dcda7fe7fea5", + "stdout_hash": "78574b40f96a23a89ac38097f6fe32c3cbf3b35b6df7835d3b48fde7", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/asr-subscript1-1acfc19.stdout b/tests/reference/asr-subscript1-1acfc19.stdout index f82e98e82c9..fb3eaea5255 100644 --- a/tests/reference/asr-subscript1-1acfc19.stdout +++ b/tests/reference/asr-subscript1-1acfc19.stdout @@ -25,6 +25,7 @@ (Integer 4) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 5 (Integer 4)))] + FixedSizeArray ) () Source @@ -45,6 +46,7 @@ (Integer 4) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 2 (Integer 4)))] + FixedSizeArray ) () Source @@ -283,6 +285,7 @@ (Integer 4) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 5 (Integer 4)))] + FixedSizeArray ) () ) @@ -299,6 +302,7 @@ (Integer 4) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 5 (Integer 4)))] + FixedSizeArray ) () ) diff --git a/tests/reference/asr-test_annassign_type_mismatch-7dac7be.json b/tests/reference/asr-test_annassign_type_mismatch-7dac7be.json index 76dc427cbbc..b9527150ed7 100644 --- a/tests/reference/asr-test_annassign_type_mismatch-7dac7be.json +++ b/tests/reference/asr-test_annassign_type_mismatch-7dac7be.json @@ -8,6 +8,6 @@ "stdout": null, "stdout_hash": null, "stderr": "asr-test_annassign_type_mismatch-7dac7be.stderr", - "stderr_hash": "a794ce35be79f7fcbb0889e04091555055f3c1c537bcf14840d33e60", + "stderr_hash": "26fc89f95c7dda5f1d9c3cb1af9843880cf693eb7b97125372b11f80", "returncode": 2 } \ No newline at end of file diff --git a/tests/reference/asr-test_annassign_type_mismatch-7dac7be.stderr b/tests/reference/asr-test_annassign_type_mismatch-7dac7be.stderr index 895ff95d9d9..6fd7b199ea1 100644 --- a/tests/reference/asr-test_annassign_type_mismatch-7dac7be.stderr +++ b/tests/reference/asr-test_annassign_type_mismatch-7dac7be.stderr @@ -2,4 +2,4 @@ semantic error: Type mismatch in annotation-assignment, the types must be compat --> tests/errors/test_annassign_type_mismatch.py:4:5 | 4 | x: i32[4] = [1, 2, 3, 4] - | ^ ^^^^^^^^^^^^ type mismatch ('i32[5]' and 'list[i32]') + | ^ ^^^^^^^^^^^^ type mismatch ('i32[4]' and 'list[i32]') diff --git a/tests/reference/asr-test_annassign_type_mismatch2-fc883f7.json b/tests/reference/asr-test_annassign_type_mismatch2-fc883f7.json index c12f4b6535d..2bb48c32ddb 100644 --- a/tests/reference/asr-test_annassign_type_mismatch2-fc883f7.json +++ b/tests/reference/asr-test_annassign_type_mismatch2-fc883f7.json @@ -8,6 +8,6 @@ "stdout": null, "stdout_hash": null, "stderr": "asr-test_annassign_type_mismatch2-fc883f7.stderr", - "stderr_hash": "3c2bbba713689c37ed22127cdd7a37ab6b1bce03d01380803884849d", + "stderr_hash": "873b4521e2155bc92405db41e7745a4fb5441b5d80f94467d7b1b637", "returncode": 2 } \ No newline at end of file diff --git a/tests/reference/asr-test_annassign_type_mismatch2-fc883f7.stderr b/tests/reference/asr-test_annassign_type_mismatch2-fc883f7.stderr index 9cc02d675fb..2a4f9ccd10b 100644 --- a/tests/reference/asr-test_annassign_type_mismatch2-fc883f7.stderr +++ b/tests/reference/asr-test_annassign_type_mismatch2-fc883f7.stderr @@ -2,4 +2,4 @@ semantic error: Type mismatch in annotation-assignment, the types must be compat --> tests/errors/test_annassign_type_mismatch2.py:4:5 | 4 | x: f64[5] = [1.0, 2.0, 3.0, 4.0, 5.0] - | ^ ^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch ('f64[6]' and 'list[f64]') + | ^ ^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch ('f64[5]' and 'list[f64]') diff --git a/tests/reference/asr-test_numpy_03-e600a49.json b/tests/reference/asr-test_numpy_03-e600a49.json index 388996a6df9..f4307ac708f 100644 --- a/tests/reference/asr-test_numpy_03-e600a49.json +++ b/tests/reference/asr-test_numpy_03-e600a49.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "asr-test_numpy_03-e600a49.stdout", - "stdout_hash": "44f0e82338fbf20e153e2e0209b4d3071fef4cc74fcd787506a72931", + "stdout_hash": "0aa23c1a54fabeae70560ae38226fa5b5a68028a57c59563699cc00e", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/asr-test_numpy_03-e600a49.stdout b/tests/reference/asr-test_numpy_03-e600a49.stdout index 5c5342f4543..46d394b7e29 100644 --- a/tests/reference/asr-test_numpy_03-e600a49.stdout +++ b/tests/reference/asr-test_numpy_03-e600a49.stdout @@ -64,6 +64,7 @@ (IntegerConstant 16 (Integer 4))) ((IntegerConstant 0 (Integer 4)) (IntegerConstant 16 (Integer 4)))] + FixedSizeArray ) () Source @@ -84,6 +85,7 @@ (Real 8) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 256 (Integer 4)))] + FixedSizeArray ) () Source @@ -199,6 +201,7 @@ (IntegerConstant 16 (Integer 4))) ((IntegerConstant 0 (Integer 4)) (IntegerConstant 16 (Integer 4)))] + FixedSizeArray ) () Source @@ -219,6 +222,7 @@ (Real 8) [(() ())] + DescriptorArray ) () Source @@ -319,6 +323,7 @@ (Integer 4) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 2 (Integer 4)))] + FixedSizeArray ) () Source @@ -339,6 +344,7 @@ (Integer 4) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 3 (Integer 4)))] + FixedSizeArray ) () Source @@ -353,6 +359,7 @@ (Real 8) [(() ())] + DescriptorArray )] () Source @@ -424,11 +431,23 @@ (Var 200 a) (ArrayReshape (Var 200 b) - (Var 200 newshape) + (ArrayPhysicalCast + (Var 200 newshape) + FixedSizeArray + DescriptorArray + (Array + (Integer 4) + [((IntegerConstant 0 (Integer 4)) + (IntegerConstant 2 (Integer 4)))] + DescriptorArray + ) + () + ) (Array (Real 8) [(() ())] + FixedSizeArray ) () ) @@ -556,11 +575,23 @@ (Var 200 c) (ArrayReshape (Var 200 d) - (Var 200 newshape1) + (ArrayPhysicalCast + (Var 200 newshape1) + FixedSizeArray + DescriptorArray + (Array + (Integer 4) + [((IntegerConstant 0 (Integer 4)) + (IntegerConstant 3 (Integer 4)))] + DescriptorArray + ) + () + ) (Array (Real 8) [(() ())] + DescriptorArray ) () ) @@ -693,6 +724,7 @@ ()) (() ())] + DescriptorArray ) () Source @@ -713,6 +745,7 @@ (Real 8) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 256 (Integer 4)))] + FixedSizeArray ) () Source @@ -1012,6 +1045,7 @@ (IntegerConstant 16 (Integer 4))) ((IntegerConstant 0 (Integer 4)) (IntegerConstant 16 (Integer 4)))] + FixedSizeArray ) () Source @@ -1032,6 +1066,7 @@ (Real 8) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 4096 (Integer 4)))] + FixedSizeArray ) () Source @@ -1132,6 +1167,7 @@ (Integer 4) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 1 (Integer 4)))] + FixedSizeArray ) () Source @@ -1152,6 +1188,7 @@ (Integer 4) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 1 (Integer 4)))] + FixedSizeArray ) () Source @@ -1168,6 +1205,7 @@ ()) (() ())] + DescriptorArray )] () Source @@ -1209,11 +1247,23 @@ (Var 199 b) (ArrayReshape (Var 199 a) - (Var 199 newshape) + (ArrayPhysicalCast + (Var 199 newshape) + FixedSizeArray + DescriptorArray + (Array + (Integer 4) + [((IntegerConstant 0 (Integer 4)) + (IntegerConstant 1 (Integer 4)))] + DescriptorArray + ) + () + ) (Array (Real 8) [(() ())] + DescriptorArray ) () ) @@ -1337,11 +1387,23 @@ (Var 199 d) (ArrayReshape (Var 199 c) - (Var 199 newshape1) + (ArrayPhysicalCast + (Var 199 newshape1) + FixedSizeArray + DescriptorArray + (Array + (Integer 4) + [((IntegerConstant 0 (Integer 4)) + (IntegerConstant 1 (Integer 4)))] + DescriptorArray + ) + () + ) (Array (Real 8) [(() ())] + FixedSizeArray ) () ) @@ -1390,6 +1452,7 @@ (IntegerConstant 16 (Integer 4))) ((IntegerConstant 0 (Integer 4)) (IntegerConstant 16 (Integer 4)))] + FixedSizeArray ) () Source @@ -1560,6 +1623,7 @@ (Real 8) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 4096 (Integer 4)))] + FixedSizeArray ) () Source @@ -1717,7 +1781,20 @@ (SubroutineCall 218 test_nd_to_1d () - [((Var 201 a))] + [((ArrayPhysicalCast + (Var 201 a) + FixedSizeArray + DescriptorArray + (Array + (Real 8) + [((IntegerConstant 0 (Integer 4)) + (IntegerConstant 16 (Integer 4))) + ((IntegerConstant 0 (Integer 4)) + (IntegerConstant 16 (Integer 4)))] + DescriptorArray + ) + () + ))] () ) (DoLoop @@ -1740,7 +1817,18 @@ (SubroutineCall 218 test_1d_to_nd () - [((Var 201 d))] + [((ArrayPhysicalCast + (Var 201 d) + FixedSizeArray + DescriptorArray + (Array + (Real 8) + [((IntegerConstant 0 (Integer 4)) + (IntegerConstant 4096 (Integer 4)))] + DescriptorArray + ) + () + ))] () )] () diff --git a/tests/reference/asr-test_numpy_04-ecbb614.json b/tests/reference/asr-test_numpy_04-ecbb614.json index 64afc75844d..a15494d5323 100644 --- a/tests/reference/asr-test_numpy_04-ecbb614.json +++ b/tests/reference/asr-test_numpy_04-ecbb614.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "asr-test_numpy_04-ecbb614.stdout", - "stdout_hash": "8d5841023c8c7109b3f432f12f11d5c72548f9bf51476d5c2f73e1a1", + "stdout_hash": "ccc6b3e8a19f7b5aff49cef591cc45883a979fc7a1f3b7665496b242", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/asr-test_numpy_04-ecbb614.stdout b/tests/reference/asr-test_numpy_04-ecbb614.stdout index 661e582b44f..821870fd992 100644 --- a/tests/reference/asr-test_numpy_04-ecbb614.stdout +++ b/tests/reference/asr-test_numpy_04-ecbb614.stdout @@ -122,6 +122,7 @@ (Real 8) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 3 (Integer 4)))] + FixedSizeArray ) () Source @@ -165,8 +166,9 @@ )] (Array (Real 8) - [(() - ())] + [((IntegerConstant 0 (Integer 4)) + (IntegerConstant 3 (Integer 4)))] + PointerToDataArray ) RowMajor ) @@ -319,6 +321,7 @@ (Integer 4) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 3 (Integer 4)))] + FixedSizeArray ) () Source @@ -353,8 +356,9 @@ (IntegerConstant 3 (Integer 4))] (Array (Integer 4) - [(() - ())] + [((IntegerConstant 0 (Integer 4)) + (IntegerConstant 3 (Integer 4)))] + PointerToDataArray ) RowMajor ) diff --git a/tests/reference/asr-test_operator_01-0f232bf.json b/tests/reference/asr-test_operator_01-0f232bf.json new file mode 100644 index 00000000000..9cb9b85ba82 --- /dev/null +++ b/tests/reference/asr-test_operator_01-0f232bf.json @@ -0,0 +1,13 @@ +{ + "basename": "asr-test_operator_01-0f232bf", + "cmd": "lpython --show-asr --no-color {infile} -o {outfile}", + "infile": "tests/errors/test_operator_01.py", + "infile_hash": "fe3fc1c23c2f63265b758b4d5d757943c1462811c5bc5e7a14abb64d", + "outfile": null, + "outfile_hash": null, + "stdout": null, + "stdout_hash": null, + "stderr": "asr-test_operator_01-0f232bf.stderr", + "stderr_hash": "6f529c2fc1fc5a489879c5d684c3415269794e563be85d62098aed7c", + "returncode": 2 +} \ No newline at end of file diff --git a/tests/reference/asr-test_operator_01-0f232bf.stderr b/tests/reference/asr-test_operator_01-0f232bf.stderr new file mode 100644 index 00000000000..1a939f05a86 --- /dev/null +++ b/tests/reference/asr-test_operator_01-0f232bf.stderr @@ -0,0 +1,5 @@ +semantic error: Unary operator '-' not supported for type struct A + --> tests/errors/test_operator_01.py:9:11 + | +9 | print(-a) + | ^^ diff --git a/tests/reference/asr-test_integer_bitnot-08e2e96.json b/tests/reference/asr-test_unary_op_03-e799eae.json similarity index 65% rename from tests/reference/asr-test_integer_bitnot-08e2e96.json rename to tests/reference/asr-test_unary_op_03-e799eae.json index 7d353e647bd..bbb18e1083e 100644 --- a/tests/reference/asr-test_integer_bitnot-08e2e96.json +++ b/tests/reference/asr-test_unary_op_03-e799eae.json @@ -1,11 +1,11 @@ { - "basename": "asr-test_integer_bitnot-08e2e96", + "basename": "asr-test_unary_op_03-e799eae", "cmd": "lpython --show-asr --no-color {infile} -o {outfile}", - "infile": "tests/../integration_tests/test_integer_bitnot.py", + "infile": "tests/../integration_tests/test_unary_op_03.py", "infile_hash": "ce63509c56eb6c68ca6d64cc2a195644f3d2fc285f3ec8865551eff5", "outfile": null, "outfile_hash": null, - "stdout": "asr-test_integer_bitnot-08e2e96.stdout", + "stdout": "asr-test_unary_op_03-e799eae.stdout", "stdout_hash": "1f4fb022cfd7bf115d1506ac0d53aa3206003060d0a14c63c75cd75f", "stderr": null, "stderr_hash": null, diff --git a/tests/reference/asr-test_integer_bitnot-08e2e96.stdout b/tests/reference/asr-test_unary_op_03-e799eae.stdout similarity index 100% rename from tests/reference/asr-test_integer_bitnot-08e2e96.stdout rename to tests/reference/asr-test_unary_op_03-e799eae.stdout diff --git a/tests/reference/asr-vec_01-66ac423.json b/tests/reference/asr-vec_01-66ac423.json index b346263af49..90eff11d6fa 100644 --- a/tests/reference/asr-vec_01-66ac423.json +++ b/tests/reference/asr-vec_01-66ac423.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "asr-vec_01-66ac423.stdout", - "stdout_hash": "f82e51f9464e67dc2bbfe6988a8b6a1c1776312be87afd4175ebe5cc", + "stdout_hash": "49151993950e6ac89ab0d0a39cc2d0ff258186636fb759f9cdd6dc9d", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/asr-vec_01-66ac423.stdout b/tests/reference/asr-vec_01-66ac423.stdout index 3cd86e19f72..356cb0846e8 100644 --- a/tests/reference/asr-vec_01-66ac423.stdout +++ b/tests/reference/asr-vec_01-66ac423.stdout @@ -62,6 +62,7 @@ (Real 8) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 9216 (Integer 4)))] + FixedSizeArray ) () Source @@ -82,6 +83,7 @@ (Real 8) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 9216 (Integer 4)))] + FixedSizeArray ) () Source diff --git a/tests/reference/c-structs_33-4a3339f.json b/tests/reference/c-structs_33-4a3339f.json new file mode 100644 index 00000000000..73a432ee7b4 --- /dev/null +++ b/tests/reference/c-structs_33-4a3339f.json @@ -0,0 +1,13 @@ +{ + "basename": "c-structs_33-4a3339f", + "cmd": "lpython --no-color --show-c {infile}", + "infile": "tests/../integration_tests/structs_33.py", + "infile_hash": "15fdcb483c864b6322ebcf6c495e635bbe917f1d8b407ccf4dc3e2ee", + "outfile": null, + "outfile_hash": null, + "stdout": "c-structs_33-4a3339f.stdout", + "stdout_hash": "425a22068f547e15ba187e2974220f28f0af3a70305b67cfd4a6a655", + "stderr": null, + "stderr_hash": null, + "returncode": 0 +} \ No newline at end of file diff --git a/tests/reference/c-structs_33-4a3339f.stdout b/tests/reference/c-structs_33-4a3339f.stdout new file mode 100644 index 00000000000..5aaf931d35a --- /dev/null +++ b/tests/reference/c-structs_33-4a3339f.stdout @@ -0,0 +1,61 @@ +#include + +#include +#include +#include +#include +#include + +struct dimension_descriptor +{ + int32_t lower_bound, length; +}; +struct __attribute__((packed)) inner_struct { + int32_t inner_field; +}; + +struct __attribute__((packed)) outer_struct { + struct inner_struct inner_s; +}; + + +inline void struct_deepcopy_outer_struct(struct outer_struct* src, struct outer_struct* dest); +inline void struct_deepcopy_inner_struct(struct inner_struct* src, struct inner_struct* dest); + + +// Implementations +void check() +{ + struct inner_struct inner_struct_instance_value; + struct inner_struct* inner_struct_instance = &inner_struct_instance_value; + struct outer_struct outer_struct_instance_value; + struct outer_struct* outer_struct_instance = &outer_struct_instance_value; + struct outer_struct outer_struct_instance2_value; + struct outer_struct* outer_struct_instance2 = &outer_struct_instance2_value; + outer_struct_instance->inner_s.inner_field = 5; + struct_deepcopy_outer_struct(outer_struct_instance, outer_struct_instance2); + struct_deepcopy_inner_struct(&outer_struct_instance2->inner_s, inner_struct_instance); + ASSERT(inner_struct_instance->inner_field == 5); +} + +void _lpython_main_program() +{ + check(); +} + +int main(int argc, char* argv[]) +{ + _lpython_set_argv(argc, argv); + _lpython_main_program(); + return 0; +} + +void struct_deepcopy_inner_struct(struct inner_struct* src, struct inner_struct* dest) { + dest->inner_field = src->inner_field; +} + +void struct_deepcopy_outer_struct(struct outer_struct* src, struct outer_struct* dest) { + struct_deepcopy_inner_struct(&(src->inner_s), &(dest->inner_s));; +} + + diff --git a/tests/reference/cpp-test_integer_bitnot-20195fd.json b/tests/reference/cpp-test_unary_op_03-fd9669a.json similarity index 65% rename from tests/reference/cpp-test_integer_bitnot-20195fd.json rename to tests/reference/cpp-test_unary_op_03-fd9669a.json index f7e5ac26d25..222158be867 100644 --- a/tests/reference/cpp-test_integer_bitnot-20195fd.json +++ b/tests/reference/cpp-test_unary_op_03-fd9669a.json @@ -1,11 +1,11 @@ { - "basename": "cpp-test_integer_bitnot-20195fd", + "basename": "cpp-test_unary_op_03-fd9669a", "cmd": "lpython --no-color --show-cpp {infile}", - "infile": "tests/../integration_tests/test_integer_bitnot.py", + "infile": "tests/../integration_tests/test_unary_op_03.py", "infile_hash": "ce63509c56eb6c68ca6d64cc2a195644f3d2fc285f3ec8865551eff5", "outfile": null, "outfile_hash": null, - "stdout": "cpp-test_integer_bitnot-20195fd.stdout", + "stdout": "cpp-test_unary_op_03-fd9669a.stdout", "stdout_hash": "48b5d7305b106351301408a544f22089e27a6e819f8440ce71e7078d", "stderr": null, "stderr_hash": null, diff --git a/tests/reference/cpp-test_integer_bitnot-20195fd.stdout b/tests/reference/cpp-test_unary_op_03-fd9669a.stdout similarity index 100% rename from tests/reference/cpp-test_integer_bitnot-20195fd.stdout rename to tests/reference/cpp-test_unary_op_03-fd9669a.stdout diff --git a/tests/reference/llvm-test_integer_bitnot-6894b6d.json b/tests/reference/llvm-test_unary_op_03-046fb86.json similarity index 65% rename from tests/reference/llvm-test_integer_bitnot-6894b6d.json rename to tests/reference/llvm-test_unary_op_03-046fb86.json index b85a0d04b24..45dc186a348 100644 --- a/tests/reference/llvm-test_integer_bitnot-6894b6d.json +++ b/tests/reference/llvm-test_unary_op_03-046fb86.json @@ -1,11 +1,11 @@ { - "basename": "llvm-test_integer_bitnot-6894b6d", + "basename": "llvm-test_unary_op_03-046fb86", "cmd": "lpython --no-color --show-llvm {infile} -o {outfile}", - "infile": "tests/../integration_tests/test_integer_bitnot.py", + "infile": "tests/../integration_tests/test_unary_op_03.py", "infile_hash": "ce63509c56eb6c68ca6d64cc2a195644f3d2fc285f3ec8865551eff5", "outfile": null, "outfile_hash": null, - "stdout": "llvm-test_integer_bitnot-6894b6d.stdout", + "stdout": "llvm-test_unary_op_03-046fb86.stdout", "stdout_hash": "af0bd6b1156e27caa40bf623d0d05a7ce9a3233f03a74d51d154d0b4", "stderr": null, "stderr_hash": null, diff --git a/tests/reference/llvm-test_integer_bitnot-6894b6d.stdout b/tests/reference/llvm-test_unary_op_03-046fb86.stdout similarity index 100% rename from tests/reference/llvm-test_integer_bitnot-6894b6d.stdout rename to tests/reference/llvm-test_unary_op_03-046fb86.stdout diff --git a/tests/reference/pass_loop_vectorise-vec_01-be9985e.json b/tests/reference/pass_loop_vectorise-vec_01-be9985e.json index 0534554be07..9b4b67643bd 100644 --- a/tests/reference/pass_loop_vectorise-vec_01-be9985e.json +++ b/tests/reference/pass_loop_vectorise-vec_01-be9985e.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "pass_loop_vectorise-vec_01-be9985e.stdout", - "stdout_hash": "c496e06f9f289d07096ba430c4cb030f6b0ca76952444c839f994e05", + "stdout_hash": "184a5f48d343ba747f2cd233617038d2c68c923009b3a46c14ca79f4", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/pass_loop_vectorise-vec_01-be9985e.stdout b/tests/reference/pass_loop_vectorise-vec_01-be9985e.stdout index 31121eab7c2..3ee0a9b3e30 100644 --- a/tests/reference/pass_loop_vectorise-vec_01-be9985e.stdout +++ b/tests/reference/pass_loop_vectorise-vec_01-be9985e.stdout @@ -62,6 +62,7 @@ (Real 8) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 9216 (Integer 4)))] + FixedSizeArray ) () Source @@ -82,6 +83,7 @@ (Real 8) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 9216 (Integer 4)))] + FixedSizeArray ) () Source @@ -139,6 +141,7 @@ (Real 8) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 9216 (Integer 4)))] + FixedSizeArray ) () Source @@ -159,6 +162,7 @@ (Real 8) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 9216 (Integer 4)))] + FixedSizeArray ) () Source @@ -237,11 +241,13 @@ (Real 8) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 9216 (Integer 4)))] + FixedSizeArray ) (Array (Real 8) [((IntegerConstant 0 (Integer 4)) (IntegerConstant 9216 (Integer 4)))] + FixedSizeArray ) (Integer 4) (Integer 4) diff --git a/tests/tests.toml b/tests/tests.toml index 1864b762fc0..13ac8257cdd 100644 --- a/tests/tests.toml +++ b/tests/tests.toml @@ -337,6 +337,10 @@ asr = true filename = "../integration_tests/structs_05.py" asr = true +[[test]] +filename = "../integration_tests/structs_33.py" +c = true + [[test]] filename = "../integration_tests/callback_01.py" asr = true @@ -408,7 +412,7 @@ filename = "../integration_tests/expr_05.py" asr = true [[test]] -filename = "../integration_tests/test_integer_bitnot.py" +filename = "../integration_tests/test_unary_op_03.py" asr = true llvm = true cpp = true @@ -651,6 +655,10 @@ asr = true filename = "errors/structs_01.py" asr = true +[[test]] +filename = "errors/arrays_01.py" +asr = true + [[test]] filename = "errors/structs_02.py" asr = true @@ -845,6 +853,10 @@ asr = true filename = "errors/test_pow4.py" asr = true +[[test]] +filename = "errors/test_operator_01.py" +asr = true + [[test]] filename = "errors/test_ord.py" asr = true @@ -1143,6 +1155,10 @@ asr = true filename = "errors/bindc_04.py" asr = true +[[test]] +filename = "errors/bindc_10e.py" +asr = true + [[test]] filename = "errors/cptr_01.py" asr = true