Skip to content

Commit

Permalink
Merge pull request lcompilers#765 from czgdp1807/multidim
Browse files Browse the repository at this point in the history
Adding support for multi-dimensional arrays in ASR
  • Loading branch information
certik committed Jul 15, 2022
2 parents a7e8ec3 + 2396484 commit afc4804
Show file tree
Hide file tree
Showing 12 changed files with 269 additions and 134 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -194,5 +194,7 @@ integration_tests/expr_08
integration_tests/expr_08.c
integration_tests/array_01_decl
integration_tests/array_01_decl.c
integration_tests/array_02_decl
integration_tests/array_02_decl.c
integration_tests/expr_12
integration_tests/expr_12.c
1 change: 1 addition & 0 deletions integration_tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ endmacro(RUN)

# Test zero and non-zero exit code and assert statements
RUN(NAME array_01_decl LABELS cpython llvm c)
RUN(NAME array_02_decl LABELS cpython llvm c)
RUN(NAME bindc_01 LABELS llvm c)
RUN(NAME bindc_02 LABELS llvm c)
RUN(NAME bindc_04 LABELS llvm)
Expand Down
29 changes: 29 additions & 0 deletions integration_tests/array_02_decl.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
from ltypes import i32, i64, f32, f64, c32, c64
from numpy import empty

def accept_multidim_i32_array(xi32: i32[:, :]) -> i32:
return xi32[0, 0]

def accept_multidim_i64_array(xi64: i64[:, :, :]) -> i64:
return xi64[9, 9, 9]

def accept_multidim_f32_array(xf32: f32[:]) -> f32:
return xf32[0]

def accept_multidim_f64_array(xf64: f64[:, :]) -> f64:
return xf64[0, 1]

def declare_arrays():
ai32: i32[3, 3] = empty([3, 3])
ai64: i64[10, 10, 10] = empty([10, 10, 10])
af32: f32[3] = empty(3)
af64: f64[10, 4] = empty([10, 4])
ac32: c32[3, 5, 99] = empty([3, 5, 99])
ac64: c64[10, 13, 11, 16] = empty([10, 13, 11, 16])
print(accept_multidim_i32_array(ai32))
print(accept_multidim_i64_array(ai64))
print(accept_multidim_f32_array(af32))
print(accept_multidim_f64_array(af64))


declare_arrays()
60 changes: 53 additions & 7 deletions src/libasr/codegen/asr_to_c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,11 @@ class ASRToCVisitor : public BaseCCPPVisitor<ASRToCVisitor>
"{\n int32_t lower_bound, upper_bound;\n};\n")) {
}

std::string convert_dims_c(size_t n_dims, ASR::dimension_t *m_dims)
std::string convert_dims_c(size_t n_dims, ASR::dimension_t *m_dims,
bool convert_to_1d=false)
{
std::string dims;
size_t size = 1;
for (size_t i=0; i<n_dims; i++) {
ASR::expr_t *start = m_dims[i].m_start;
ASR::expr_t *end = m_dims[i].m_end;
Expand All @@ -60,14 +62,19 @@ class ASRToCVisitor : public BaseCCPPVisitor<ASRToCVisitor>
int64_t start_int = -1, end_int = -1;
ASRUtils::extract_value(start_value, start_int);
ASRUtils::extract_value(end_value, end_int);
size *= (end_int - start_int + 1);
dims += "[" + std::to_string(end_int - start_int + 1) + "]";
} else {
size = 0;
dims += "[ /* FIXME symbolic dimensions */ ]";
}
} else {
throw CodeGenError("Dimension type not supported");
}
}
if( convert_to_1d && size != 0 ) {
dims = "[" + std::to_string(size) + "]";
}
return dims;
}

Expand Down Expand Up @@ -113,7 +120,7 @@ class ASRToCVisitor : public BaseCCPPVisitor<ASRToCVisitor>
sub += " = &" + variable_name + ";\n";
if( !is_pointer ) {
sub += indent + format_type_c(dims, type_name_copy, std::string(v_m_name) + "_data",
use_ref, dummy) + ";\n";
use_ref, dummy) + ";\n";
sub += indent + std::string(v_m_name) + "->data = " + std::string(v_m_name) + "_data;\n";
for (int i = 0; i < n_dims; i++) {
if( m_dims[i].m_start ) {
Expand Down Expand Up @@ -154,19 +161,20 @@ class ASRToCVisitor : public BaseCCPPVisitor<ASRToCVisitor>
ASR::ttype_t *t2 = ASR::down_cast<ASR::Pointer_t>(v.m_type)->m_type;
if (ASRUtils::is_integer(*t2)) {
ASR::Integer_t *t = ASR::down_cast<ASR::Integer_t>(t2);
std::string dims = convert_dims_c(t->n_dims, t->m_dims);
std::string type_name = "int" + std::to_string(t->m_kind * 8) + "_t";
if( !ASRUtils::is_array(v.m_type) ) {
type_name.append(" *");
}
if( is_array ) {
std::string dims = convert_dims_c(t->n_dims, t->m_dims, true);
std::string encoded_type_name = "i" + std::to_string(t->m_kind * 8);
generate_array_decl(sub, std::string(v.m_name), type_name, dims,
encoded_type_name, t->m_dims, t->n_dims,
use_ref, dummy,
v.m_intent != ASRUtils::intent_in &&
v.m_intent != ASRUtils::intent_inout, true);
} else {
std::string dims = convert_dims_c(t->n_dims, t->m_dims);
sub = format_type_c(dims, type_name, v.m_name, use_ref, dummy);
}
} else if(ASR::is_a<ASR::Derived_t>(*t2)) {
Expand All @@ -187,47 +195,50 @@ class ASRToCVisitor : public BaseCCPPVisitor<ASRToCVisitor>
if (ASRUtils::is_integer(*v.m_type)) {
headers.insert("inttypes");
ASR::Integer_t *t = ASR::down_cast<ASR::Integer_t>(v.m_type);
dims = convert_dims_c(t->n_dims, t->m_dims);
std::string type_name = "int" + std::to_string(t->m_kind * 8) + "_t";
if( is_array ) {
dims = convert_dims_c(t->n_dims, t->m_dims, true);
std::string encoded_type_name = "i" + std::to_string(t->m_kind * 8);
generate_array_decl(sub, std::string(v.m_name), type_name, dims,
encoded_type_name, t->m_dims, t->n_dims,
use_ref, dummy,
v.m_intent != ASRUtils::intent_in &&
v.m_intent != ASRUtils::intent_inout);
} else {
dims = convert_dims_c(t->n_dims, t->m_dims);
sub = format_type_c(dims, type_name, v.m_name, use_ref, dummy);
}
} else if (ASRUtils::is_real(*v.m_type)) {
ASR::Real_t *t = ASR::down_cast<ASR::Real_t>(v.m_type);
dims = convert_dims_c(t->n_dims, t->m_dims);
std::string type_name = "float";
if (t->m_kind == 8) type_name = "double";
if( is_array ) {
dims = convert_dims_c(t->n_dims, t->m_dims, true);
std::string encoded_type_name = "f" + std::to_string(t->m_kind * 8);
generate_array_decl(sub, std::string(v.m_name), type_name, dims,
encoded_type_name, t->m_dims, t->n_dims,
use_ref, dummy,
v.m_intent != ASRUtils::intent_in &&
v.m_intent != ASRUtils::intent_inout);
} else {
dims = convert_dims_c(t->n_dims, t->m_dims);
sub = format_type_c(dims, type_name, v.m_name, use_ref, dummy);
}
} else if (ASRUtils::is_complex(*v.m_type)) {
headers.insert("complex");
ASR::Complex_t *t = ASR::down_cast<ASR::Complex_t>(v.m_type);
dims = convert_dims_c(t->n_dims, t->m_dims);
std::string type_name = "float complex";
if (t->m_kind == 8) type_name = "double complex";
if( is_array ) {
dims = convert_dims_c(t->n_dims, t->m_dims, true);
std::string encoded_type_name = "c" + std::to_string(t->m_kind * 8);
generate_array_decl(sub, std::string(v.m_name), type_name, dims,
encoded_type_name, t->m_dims, t->n_dims,
use_ref, dummy,
v.m_intent != ASRUtils::intent_in &&
v.m_intent != ASRUtils::intent_inout);
} else {
dims = convert_dims_c(t->n_dims, t->m_dims);
sub = format_type_c(dims, type_name, v.m_name, use_ref, dummy);
}
} else if (ASRUtils::is_logical(*v.m_type)) {
Expand All @@ -242,8 +253,8 @@ class ASRToCVisitor : public BaseCCPPVisitor<ASRToCVisitor>
std::string indent(indentation_level*indentation_spaces, ' ');
ASR::Derived_t *t = ASR::down_cast<ASR::Derived_t>(v.m_type);
std::string der_type_name = ASRUtils::symbol_name(t->m_derived_type);
std::string dims = convert_dims_c(t->n_dims, t->m_dims);
if( is_array ) {
dims = convert_dims_c(t->n_dims, t->m_dims, true);
std::string encoded_type_name = "x" + der_type_name;
std::string type_name = std::string("struct ") + der_type_name;
generate_array_decl(sub, std::string(v.m_name), type_name, dims,
Expand All @@ -252,6 +263,7 @@ class ASRToCVisitor : public BaseCCPPVisitor<ASRToCVisitor>
v.m_intent != ASRUtils::intent_in &&
v.m_intent != ASRUtils::intent_inout);
} else if( v.m_intent == ASRUtils::intent_local && pre_initialise_derived_type) {
dims = convert_dims_c(t->n_dims, t->m_dims);
std::string value_var_name = v.m_parent_symtab->get_unique_name(std::string(v.m_name) + "_value");
sub = format_type_c(dims, "struct " + der_type_name,
value_var_name, use_ref, dummy);
Expand All @@ -269,6 +281,7 @@ class ASRToCVisitor : public BaseCCPPVisitor<ASRToCVisitor>
}
return sub;
} else {
dims = convert_dims_c(t->n_dims, t->m_dims);
if( v.m_intent == ASRUtils::intent_in ||
v.m_intent == ASRUtils::intent_inout ) {
use_ref = false;
Expand Down Expand Up @@ -594,6 +607,39 @@ R"(
src = out;
}

void visit_ArrayItem(const ASR::ArrayItem_t &x) {
this->visit_expr(*x.m_v);
std::string array = src;
std::string out = array;
ASR::dimension_t* m_dims;
ASRUtils::extract_dimensions_from_ttype(ASRUtils::expr_type(x.m_v), m_dims);
out += "->data[";
std::string index = "";
for (size_t i=0; i<x.n_args; i++) {
std::string current_index = "";
if (x.m_args[i].m_right) {
this->visit_expr(*x.m_args[i].m_right);
} else {
src = "/* FIXME right index */";
}

current_index += "(" + src + " - " + array + "->dims["
+ std::to_string(i) + "].lower_bound)";
for( size_t j = 0; j < i; j++ ) {
std::string lb = array + "->dims[" + std::to_string(j) + "].lower_bound";
std::string ub = array + "->dims[" + std::to_string(j) + "].upper_bound";
current_index += " * (" + ub + " - " + lb + " + 1)";
}
index += current_index;
if (i < x.n_args - 1) {
index += " + ";
}
}
out += index + "]";
last_expr_precedence = 2;
src = out;
}

};

Result<std::string> asr_to_c(Allocator &al, ASR::TranslationUnit_t &asr,
Expand Down
38 changes: 1 addition & 37 deletions src/libasr/codegen/asr_to_c_cpp.h
Original file line number Diff line number Diff line change
Expand Up @@ -553,7 +553,7 @@ R"(#include <stdio.h>
target += "->data";
}
} else if (ASR::is_a<ASR::ArrayItem_t>(*x.m_target)) {
visit_ArrayItem(*ASR::down_cast<ASR::ArrayItem_t>(x.m_target));
self().visit_ArrayItem(*ASR::down_cast<ASR::ArrayItem_t>(x.m_target));
target = src;
} else if (ASR::is_a<ASR::DerivedRef_t>(*x.m_target)) {
visit_DerivedRef(*ASR::down_cast<ASR::DerivedRef_t>(x.m_target));
Expand Down Expand Up @@ -638,42 +638,6 @@ R"(#include <stdio.h>
}
}

void visit_ArrayItem(const ASR::ArrayItem_t &x) {
this->visit_expr(*x.m_v);
std::string array = src;
std::string out = array;
ASR::dimension_t* m_dims;
ASRUtils::extract_dimensions_from_ttype(ASRUtils::expr_type(x.m_v), m_dims);
if( is_c ) {
out += "->data[";
} else {
out += "->data->operator[](";
}
for (size_t i=0; i<x.n_args; i++) {
if (x.m_args[i].m_right) {
self().visit_expr(*x.m_args[i].m_right);
} else {
src = "/* FIXME right index */";
}
out += src;
out += " - " + array + "->dims[" + std::to_string(i) + "].lower_bound";
if (i < x.n_args-1) {
if( is_c ) {
out += "][";
} else {
out += ", ";
}
}
}
if( is_c ) {
out += "]";
} else {
out += ")";
}
last_expr_precedence = 2;
src = out;
}

void visit_Cast(const ASR::Cast_t &x) {
self().visit_expr(*x.m_arg);
switch (x.m_kind) {
Expand Down
26 changes: 26 additions & 0 deletions src/libasr/codegen/asr_to_cpp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -659,6 +659,32 @@ Kokkos::View<T*> from_std_vector(const std::vector<T> &v)
src = out;
}

void visit_ArrayItem(const ASR::ArrayItem_t &x) {
this->visit_expr(*x.m_v);
std::string array = src;
std::string out = array;
ASR::dimension_t* m_dims;
ASRUtils::extract_dimensions_from_ttype(ASRUtils::expr_type(x.m_v), m_dims);
out += "->data->operator[](";
std::string index = "";
for (size_t i=0; i<x.n_args; i++) {
std::string current_index = "";
if (x.m_args[i].m_right) {
this->visit_expr(*x.m_args[i].m_right);
} else {
src = "/* FIXME right index */";
}
out += src;
out += " - " + array + "->dims[" + std::to_string(i) + "].lower_bound";
if (i < x.n_args - 1) {
out += ", ";
}
}
out += ")";
last_expr_precedence = 2;
src = out;
}

};

Result<std::string> asr_to_cpp(Allocator &al, ASR::TranslationUnit_t &asr,
Expand Down
Loading

0 comments on commit afc4804

Please sign in to comment.