Skip to content

Commit

Permalink
Merge pull request lcompilers#1775 from certik/uint4
Browse files Browse the repository at this point in the history
Implement unsigned arrays support
  • Loading branch information
certik committed May 10, 2023
2 parents e9453fd + 5562678 commit 9b8fa1e
Show file tree
Hide file tree
Showing 9 changed files with 244 additions and 2 deletions.
1 change: 1 addition & 0 deletions integration_tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,7 @@ RUN(NAME expr_15 LABELS cpython llvm c)

RUN(NAME expr_01u LABELS cpython llvm c)
RUN(NAME expr_02u LABELS cpython llvm c)
RUN(NAME expr_03u LABELS cpython llvm c)

RUN(NAME loop_01 LABELS cpython llvm c)
RUN(NAME loop_02 LABELS cpython llvm c wasm wasm_x86 wasm_x64)
Expand Down
159 changes: 159 additions & 0 deletions integration_tests/expr_03u.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
from lpython import u8, u16, u32, u64, i8, i32, TypeVar
from numpy import (empty, uint8, uint16, uint32, uint64, int8, int16, int32,
int64, size)

n = TypeVar("n")
def add_i8(n: i32, x: i8[n], y: i8[n]) -> i8[n]:
return x + y

def add_i8_loop(n: i32, x: i8[n], y: i8[n]) -> i8[n]:
z: i8[n] = empty(n, dtype=int8)
i: i32
for i in range(n):
z[i] = x[i] + y[i]
return z

def add_u8(n: i32, x: u8[n], y: u8[n]) -> u8[n]:
return x + y

def add_u8_loop(n: i32, x: u8[n], y: u8[n]) -> u8[n]:
z: u8[n] = empty(n, dtype=uint8)
i: i32
for i in range(n):
z[i] = x[i] + y[i]
return z

def add_u16(n: i32, x: u16[n], y: u16[n]) -> u16[n]:
return x + y

def add_u16_loop(n: i32, x: u16[n], y: u16[n]) -> u16[n]:
z: u16[n] = empty(n, dtype=uint16)
i: i32
for i in range(n):
z[i] = x[i] + y[i]
return z

def add_u32(n: i32, x: u32[n], y: u32[n]) -> u32[n]:
return x + y

def add_u32_loop(n: i32, x: u32[n], y: u32[n]) -> u32[n]:
z: u32[n] = empty(n, dtype=uint32)
i: i32
for i in range(n):
z[i] = x[i] + y[i]
return z

def add_u64(n: i32, x: u64[n], y: u64[n]) -> u64[n]:
return x + y

def add_u64_loop(n: i32, x: u64[n], y: u64[n]) -> u64[n]:
z: u64[n] = empty(n, dtype=uint64)
i: i32
for i in range(n):
z[i] = x[i] + y[i]
return z

def main_i8():
x: i8[3] = empty(3, dtype=int8)
y: i8[3] = empty(3, dtype=int8)
z: i8[3] = empty(3, dtype=int8)
x[0] = i8(1)
x[1] = i8(2)
x[2] = i8(3)
y[0] = i8(2)
y[1] = i8(3)
y[2] = i8(4)
z = add_i8(size(x), x, y)
assert z[0] == i8(3)
assert z[1] == i8(5)
assert z[2] == i8(7)
z = add_i8_loop(size(x), x, y)
assert z[0] == i8(3)
assert z[1] == i8(5)
assert z[2] == i8(7)

def main_u8():
x: u8[3] = empty(3, dtype=uint8)
y: u8[3] = empty(3, dtype=uint8)
z: u8[3] = empty(3, dtype=uint8)
x[0] = u8(1)
x[1] = u8(2)
x[2] = u8(3)
y[0] = u8(2)
y[1] = u8(3)
y[2] = u8(4)
z = add_u8(size(x), x, y)
assert z[0] == u8(3)
assert z[1] == u8(5)
assert z[2] == u8(7)
z = add_u8_loop(size(x), x, y)
assert z[0] == u8(3)
assert z[1] == u8(5)
assert z[2] == u8(7)

def main_u16():
x: u16[3] = empty(3, dtype=uint16)
y: u16[3] = empty(3, dtype=uint16)
z: u16[3] = empty(3, dtype=uint16)
x[0] = u16(1)
x[1] = u16(2)
x[2] = u16(3)
y[0] = u16(2)
y[1] = u16(3)
y[2] = u16(4)
z = add_u16(size(x), x, y)
assert z[0] == u16(3)
assert z[1] == u16(5)
assert z[2] == u16(7)
z = add_u16_loop(size(x), x, y)
assert z[0] == u16(3)
assert z[1] == u16(5)
assert z[2] == u16(7)

def main_u32():
x: u32[3] = empty(3, dtype=uint32)
y: u32[3] = empty(3, dtype=uint32)
z: u32[3] = empty(3, dtype=uint32)
x[0] = u32(1)
x[1] = u32(2)
x[2] = u32(3)
y[0] = u32(2)
y[1] = u32(3)
y[2] = u32(4)
z = add_u32(size(x), x, y)
assert z[0] == u32(3)
assert z[1] == u32(5)
assert z[2] == u32(7)
z = add_u32_loop(size(x), x, y)
assert z[0] == u32(3)
assert z[1] == u32(5)
assert z[2] == u32(7)

def main_u64():
x: u64[3] = empty(3, dtype=uint64)
y: u64[3] = empty(3, dtype=uint64)
z: u64[3] = empty(3, dtype=uint64)
x[0] = u64(1)
x[1] = u64(2)
x[2] = u64(3)
y[0] = u64(2)
y[1] = u64(3)
y[2] = u64(4)
z = add_u64(size(x), x, y)
assert z[0] == u64(3)
assert z[1] == u64(5)
assert z[2] == u64(7)
z = add_u64_loop(size(x), x, y)
assert z[0] == u64(3)
assert z[1] == u64(5)
assert z[2] == u64(7)

main_i8()
main_u8()
main_u16()
main_u32()
main_u64()

# Not implemented yet in LPython:
#if __name__ == "__main__":
# main()
21 changes: 21 additions & 0 deletions src/libasr/asr_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -618,6 +618,8 @@ static inline bool is_value_constant(ASR::expr_t *a_value) {
}
if (ASR::is_a<ASR::IntegerConstant_t>(*a_value)) {
// OK
} else if (ASR::is_a<ASR::UnsignedIntegerConstant_t>(*a_value)) {
// OK
} else if (ASR::is_a<ASR::RealConstant_t>(*a_value)) {
// OK
} else if (ASR::is_a<ASR::ComplexConstant_t>(*a_value)) {
Expand Down Expand Up @@ -1674,6 +1676,12 @@ inline bool ttype_set_dimensions(ASR::ttype_t *x,
Integer_type->m_dims = m_dims;
return true;
}
case ASR::ttypeType::UnsignedInteger: {
ASR::UnsignedInteger_t* Integer_type = ASR::down_cast<ASR::UnsignedInteger_t>(x);
Integer_type->n_dims = n_dims;
Integer_type->m_dims = m_dims;
return true;
}
case ASR::ttypeType::Real: {
ASR::Real_t* Real_type = ASR::down_cast<ASR::Real_t>(x);
Real_type->n_dims = n_dims;
Expand Down Expand Up @@ -1737,6 +1745,7 @@ static inline bool is_aggregate_type(ASR::ttype_t* asr_type) {
}
return ASRUtils::is_array(asr_type) ||
!(ASR::is_a<ASR::Integer_t>(*asr_type) ||
ASR::is_a<ASR::UnsignedInteger_t>(*asr_type) ||
ASR::is_a<ASR::Real_t>(*asr_type) ||
ASR::is_a<ASR::Complex_t>(*asr_type) ||
ASR::is_a<ASR::Logical_t>(*asr_type));
Expand All @@ -1752,6 +1761,13 @@ static inline ASR::ttype_t* duplicate_type(Allocator& al, const ASR::ttype_t* t,
return ASRUtils::TYPE(ASR::make_Integer_t(al, t->base.loc,
tnew->m_kind, dimsp, dimsn));
}
case ASR::ttypeType::UnsignedInteger: {
ASR::UnsignedInteger_t* tnew = ASR::down_cast<ASR::UnsignedInteger_t>(t);
ASR::dimension_t* dimsp = dims ? dims->p : tnew->m_dims;
size_t dimsn = dims ? dims->n : tnew->n_dims;
return ASRUtils::TYPE(ASR::make_UnsignedInteger_t(al, t->base.loc,
tnew->m_kind, dimsp, dimsn));
}
case ASR::ttypeType::Real: {
ASR::Real_t* tnew = ASR::down_cast<ASR::Real_t>(t);
ASR::dimension_t* dimsp = dims ? dims->p : tnew->m_dims;
Expand Down Expand Up @@ -1841,6 +1857,11 @@ static inline ASR::ttype_t* duplicate_type_without_dims(Allocator& al, const ASR
return ASRUtils::TYPE(ASR::make_Integer_t(al, loc,
tnew->m_kind, nullptr, 0));
}
case ASR::ttypeType::UnsignedInteger: {
ASR::UnsignedInteger_t* tnew = ASR::down_cast<ASR::UnsignedInteger_t>(t);
return ASRUtils::TYPE(ASR::make_UnsignedInteger_t(al, loc,
tnew->m_kind, nullptr, 0));
}
case ASR::ttypeType::Real: {
ASR::Real_t* tnew = ASR::down_cast<ASR::Real_t>(t);
return ASRUtils::TYPE(ASR::make_Real_t(al, loc,
Expand Down
4 changes: 4 additions & 0 deletions src/libasr/codegen/asr_to_llvm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,10 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
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;
Expand Down
4 changes: 4 additions & 0 deletions src/libasr/codegen/c_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,10 @@ namespace CUtils {
type_src = "int" + std::to_string(kind * 8) + "_t";
break;
}
case ASR::ttypeType::UnsignedInteger: {
type_src = "uint" + std::to_string(kind * 8) + "_t";
break;
}
case ASR::ttypeType::Logical: {
type_src = "bool";
break;
Expand Down
21 changes: 20 additions & 1 deletion src/libasr/pass/array_op.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,11 @@ class ReplaceArrayOp: public ASR::BaseExprReplacer<ReplaceArrayOp> {
al, loc, left, (ASR::binopType)x->m_op,
right, x->m_type, nullptr));

case ASR::exprType::UnsignedIntegerBinOp:
return ASRUtils::EXPR(ASR::make_UnsignedIntegerBinOp_t(
al, loc, left, (ASR::binopType)x->m_op,
right, x->m_type, nullptr));

case ASR::exprType::RealBinOp:
return ASRUtils::EXPR(ASR::make_RealBinOp_t(
al, loc, left, (ASR::binopType)x->m_op,
Expand All @@ -330,6 +335,11 @@ class ReplaceArrayOp: public ASR::BaseExprReplacer<ReplaceArrayOp> {
al, loc, left, (ASR::cmpopType)x->m_op,
right, x->m_type, nullptr));

case ASR::exprType::UnsignedIntegerCompare:
return ASRUtils::EXPR(ASR::make_UnsignedIntegerCompare_t(
al, loc, left, (ASR::cmpopType)x->m_op,
right, x->m_type, nullptr));

case ASR::exprType::RealCompare:
return ASRUtils::EXPR(ASR::make_RealCompare_t(
al, loc, left, (ASR::cmpopType)x->m_op,
Expand All @@ -355,7 +365,8 @@ class ReplaceArrayOp: public ASR::BaseExprReplacer<ReplaceArrayOp> {
case ASR::exprType::RealCompare:
case ASR::exprType::ComplexCompare:
case ASR::exprType::LogicalCompare:
case ASR::exprType::IntegerCompare: {
case ASR::exprType::IntegerCompare:
case ASR::exprType::UnsignedIntegerCompare: {
ASR::ttype_t* arr_expr_type = ASRUtils::expr_type(arr_expr);
ASR::dimension_t* m_dims;
size_t n_dims = ASRUtils::extract_dimensions_from_ttype(arr_expr_type, m_dims);
Expand Down Expand Up @@ -647,6 +658,10 @@ class ReplaceArrayOp: public ASR::BaseExprReplacer<ReplaceArrayOp> {
replace_ArrayOpCommon(x, "_integer_bin_op_res");
}

void replace_UnsignedIntegerBinOp(ASR::UnsignedIntegerBinOp_t* x) {
replace_ArrayOpCommon(x, "_unsigned_integer_bin_op_res");
}

void replace_ComplexBinOp(ASR::ComplexBinOp_t* x) {
replace_ArrayOpCommon<ASR::ComplexBinOp_t>(x, "_complex_bin_op_res");
}
Expand All @@ -659,6 +674,10 @@ class ReplaceArrayOp: public ASR::BaseExprReplacer<ReplaceArrayOp> {
replace_ArrayOpCommon<ASR::IntegerCompare_t>(x, "_integer_comp_op_res");
}

void replace_UnsignedIntegerCompare(ASR::UnsignedIntegerCompare_t* x) {
replace_ArrayOpCommon<ASR::UnsignedIntegerCompare_t>(x, "_unsigned_integer_comp_op_res");
}

void replace_RealCompare(ASR::RealCompare_t* x) {
replace_ArrayOpCommon<ASR::RealCompare_t>(x, "_real_comp_op_res");
}
Expand Down
17 changes: 17 additions & 0 deletions src/libasr/pass/pass_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ namespace LCompilers {
m_dims = x_type_ref->m_dims;
break;
}
case ASR::ttypeType::UnsignedInteger: {
ASR::UnsignedInteger_t* x_type_ref = ASR::down_cast<ASR::UnsignedInteger_t>(t2);
n_dims = x_type_ref->n_dims;
m_dims = x_type_ref->m_dims;
break;
}
case ASR::ttypeType::Real: {
ASR::Real_t* x_type_ref = ASR::down_cast<ASR::Real_t>(t2);
n_dims = x_type_ref->n_dims;
Expand Down Expand Up @@ -69,6 +75,17 @@ namespace LCompilers {
}
break;
}
case ASR::ttypeType::UnsignedInteger: {
ASR::UnsignedInteger_t* x_type_ref = ASR::down_cast<ASR::UnsignedInteger_t>(t2);
if( create_new ) {
new_type = ASRUtils::TYPE(ASR::make_UnsignedInteger_t(*al, x_type->base.loc, x_type_ref->m_kind,
m_dims, n_dims));
} else {
x_type_ref->n_dims = n_dims;
x_type_ref->m_dims = m_dims;
}
break;
}
case ASR::ttypeType::Real: {
ASR::Real_t* x_type_ref = ASR::down_cast<ASR::Real_t>(t2);
if( create_new ) {
Expand Down
15 changes: 15 additions & 0 deletions src/lpython/semantics/python_ast_to_asr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -733,6 +733,21 @@ class CommonVisitor : public AST::BaseVisitor<Struct> {
}
return ASRUtils::TYPE(ASR::make_Integer_t(al, loc, t->m_kind, new_dims.p, new_dims.size()));
}
case ASR::ttypeType::UnsignedInteger: {
ASR::UnsignedInteger_t *t = ASR::down_cast<ASR::UnsignedInteger_t>(return_type);
fill_expr_in_ttype_t(func_calls, t->m_dims, t->n_dims);
fix_exprs_ttype_t(func_calls, args, f);
Vec<ASR::dimension_t> new_dims;
new_dims.reserve(al, t->n_dims);
for( size_t i = 0; i < func_calls.size(); i += 2 ) {
ASR::dimension_t new_dim;
new_dim.loc = func_calls[i]->base.loc;
new_dim.m_start = func_calls[i];
new_dim.m_length = func_calls[i + 1];
new_dims.push_back(al, new_dim);
}
return ASRUtils::TYPE(ASR::make_UnsignedInteger_t(al, loc, t->m_kind, new_dims.p, new_dims.size()));
}
case ASR::ttypeType::Real: {
ASR::Real_t *t = ASR::down_cast<ASR::Real_t>(return_type);
fill_expr_in_ttype_t(func_calls, t->m_dims, t->n_dims);
Expand Down
4 changes: 3 additions & 1 deletion src/lpython/semantics/python_comptime_eval.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ struct ProceduresDatabase {
"float32", "float64",
"reshape", "array", "int16",
"complex64", "complex128",
"int8", "exp", "exp2"}},
"int8", "exp", "exp2",
"uint8", "uint16", "uint32", "uint64",
"size"}},
{"math", {"sin", "cos", "tan",
"asin", "acos", "atan",
"exp", "exp2", "expm1"}},
Expand Down

0 comments on commit 9b8fa1e

Please sign in to comment.