Skip to content

Commit

Permalink
Backend: add support for unsigned integers
Browse files Browse the repository at this point in the history
  • Loading branch information
certik committed May 10, 2023
1 parent 248725b commit 1ca113f
Show file tree
Hide file tree
Showing 4 changed files with 242 additions and 5 deletions.
4 changes: 4 additions & 0 deletions src/libasr/asr_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -974,6 +974,10 @@ ASR::asr_t* make_Cast_t_value(Allocator &al, const Location &a_loc,
int64_t int_value = ASR::down_cast<ASR::IntegerConstant_t>(
ASRUtils::expr_value(a_arg))->m_n;
value = ASR::down_cast<ASR::expr_t>(ASR::make_IntegerConstant_t(al, a_loc, int_value, a_type));
} else if (a_kind == ASR::cast_kindType::IntegerToUnsignedInteger) {
int64_t int_value = ASR::down_cast<ASR::IntegerConstant_t>(
ASRUtils::expr_value(a_arg))->m_n;
value = ASR::down_cast<ASR::expr_t>(ASR::make_UnsignedIntegerConstant_t(al, a_loc, int_value, a_type));
} else if (a_kind == ASR::cast_kindType::IntegerToLogical) {
// TODO: implement
} else if (a_kind == ASR::cast_kindType::ComplexToComplex) {
Expand Down
61 changes: 60 additions & 1 deletion src/libasr/asr_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -842,6 +842,11 @@ static inline bool extract_value(ASR::expr_t* value_expr, T& value) {
value = (T) const_int->m_n;
break;
}
case ASR::exprType::UnsignedIntegerConstant: {
ASR::UnsignedIntegerConstant_t* const_int = ASR::down_cast<ASR::UnsignedIntegerConstant_t>(value_expr);
value = (T) const_int->m_n;
break;
}
case ASR::exprType::RealConstant: {
ASR::RealConstant_t* const_real = ASR::down_cast<ASR::RealConstant_t>(value_expr);
value = (T) const_real->m_r;
Expand Down Expand Up @@ -924,6 +929,16 @@ static inline std::string get_type_code(const ASR::ttype_t *t, bool use_undersco
is_dimensional = integer->n_dims > 0;
break;
}
case ASR::ttypeType::UnsignedInteger: {
ASR::UnsignedInteger_t *integer = ASR::down_cast<ASR::UnsignedInteger_t>(t);
res = "u" + std::to_string(integer->m_kind * 8);
if( encode_dimensions_ ) {
encode_dimensions(integer->n_dims, res, use_underscore_sep);
return res;
}
is_dimensional = integer->n_dims > 0;
break;
}
case ASR::ttypeType::Real: {
ASR::Real_t *real = ASR::down_cast<ASR::Real_t>(t);
res = "r" + std::to_string(real->m_kind * 8);
Expand Down Expand Up @@ -1090,7 +1105,7 @@ static inline std::string type_to_str_python(const ASR::ttype_t *t,
{
switch (t->type) {
case ASR::ttypeType::Integer: {
ASR::Integer_t *i = (ASR::Integer_t*)t;
ASR::Integer_t *i = ASR::down_cast<ASR::Integer_t>(t);
std::string res = "";
switch (i->m_kind) {
case 1: { res = "i8"; break; }
Expand All @@ -1104,6 +1119,21 @@ static inline std::string type_to_str_python(const ASR::ttype_t *t,
}
return res;
}
case ASR::ttypeType::UnsignedInteger: {
ASR::UnsignedInteger_t *i = ASR::down_cast<ASR::UnsignedInteger_t>(t);
std::string res = "";
switch (i->m_kind) {
case 1: { res = "u8"; break; }
case 2: { res = "u16"; break; }
case 4: { res = "u32"; break; }
case 8: { res = "u64"; break; }
default: { throw LCompilersException("UnsignedInteger kind not supported"); }
}
if (i->n_dims == 1 && for_error_message) {
res = type_python_1dim_helper(res, i->m_dims);
}
return res;
}
case ASR::ttypeType::Real: {
ASR::Real_t *r = (ASR::Real_t*)t;
std::string res = "";
Expand Down Expand Up @@ -1374,6 +1404,9 @@ static inline int extract_kind_from_ttype_t(const ASR::ttype_t* type) {
case ASR::ttypeType::Integer : {
return ASR::down_cast<ASR::Integer_t>(type)->m_kind;
}
case ASR::ttypeType::UnsignedInteger : {
return ASR::down_cast<ASR::UnsignedInteger_t>(type)->m_kind;
}
case ASR::ttypeType::Real : {
return ASR::down_cast<ASR::Real_t>(type)->m_kind;
}
Expand Down Expand Up @@ -1406,6 +1439,10 @@ static inline bool is_integer(ASR::ttype_t &x) {
return ASR::is_a<ASR::Integer_t>(*type_get_past_pointer(&x));
}

static inline bool is_unsigned_integer(ASR::ttype_t &x) {
return ASR::is_a<ASR::UnsignedInteger_t>(*type_get_past_pointer(&x));
}

static inline bool is_real(ASR::ttype_t &x) {
return ASR::is_a<ASR::Real_t>(*type_get_past_pointer(&x));
}
Expand Down Expand Up @@ -1485,6 +1522,12 @@ inline int extract_dimensions_from_ttype(ASR::ttype_t *x,
m_dims = Integer_type->m_dims;
break;
}
case ASR::ttypeType::UnsignedInteger: {
ASR::UnsignedInteger_t* Integer_type = ASR::down_cast<ASR::UnsignedInteger_t>(x);
n_dims = Integer_type->n_dims;
m_dims = Integer_type->m_dims;
break;
}
case ASR::ttypeType::Real: {
ASR::Real_t* Real_type = ASR::down_cast<ASR::Real_t>(x);
n_dims = Real_type->n_dims;
Expand Down Expand Up @@ -2122,6 +2165,22 @@ inline bool types_equal(ASR::ttype_t *a, ASR::ttype_t *b,
}
break;
}
case (ASR::ttypeType::UnsignedInteger) : {
ASR::UnsignedInteger_t *a2 = ASR::down_cast<ASR::UnsignedInteger_t>(a);
ASR::UnsignedInteger_t *b2 = ASR::down_cast<ASR::UnsignedInteger_t>(b);
if (a2->m_kind == b2->m_kind) {
if( check_for_dimensions ) {
return ASRUtils::dimensions_equal(
a2->m_dims, a2->n_dims,
b2->m_dims, b2->n_dims);
} else {
return true;
}
} else {
return false;
}
break;
}
case ASR::ttypeType::CPtr: {
return true;
}
Expand Down
178 changes: 174 additions & 4 deletions src/libasr/codegen/asr_to_llvm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2867,6 +2867,36 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
}
break;
}
case (ASR::ttypeType::UnsignedInteger) : {
ASR::UnsignedInteger_t* v_type = down_cast<ASR::UnsignedInteger_t>(asr_type);
m_dims = v_type->m_dims;
n_dims = v_type->n_dims;
a_kind = v_type->m_kind;
if( n_dims > 0 ) {
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(asr_type), ASRUtils::get_fixed_size_of_array(
v_type->m_dims, v_type->n_dims));
} else {
llvm_type = get_el_type(asr_type)->getPointerTo();
}
} else {
is_array_type = true;
llvm::Type* el_type = get_el_type(asr_type);
if( m_storage == ASR::storage_typeType::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);
}
}
} else {
// 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::Real_t>(asr_type);
m_dims = v_type->m_dims;
Expand Down Expand Up @@ -3459,6 +3489,34 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
}
break;
}
case (ASR::ttypeType::UnsignedInteger) : {
ASR::UnsignedInteger_t* v_type = down_cast<ASR::UnsignedInteger_t>(asr_type);
n_dims = v_type->n_dims;
a_kind = v_type->m_kind;
if( n_dims > 0 ) {
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 = getIntType(a_kind, true);
} else {
is_array_type = true;
llvm::Type* el_type = get_el_type(asr_type);
if( m_storage == ASR::storage_typeType::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);
}
}
} else {
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<ASR::Class_t>(*t2);
Expand Down Expand Up @@ -3904,6 +3962,11 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
return_type = getIntType(a_kind);
break;
}
case (ASR::ttypeType::UnsignedInteger) : {
int a_kind = down_cast<ASR::UnsignedInteger_t>(return_var_type0)->m_kind;
return_type = getIntType(a_kind);
break;
}
case (ASR::ttypeType::Real) : {
int a_kind = down_cast<ASR::Real_t>(return_var_type0)->m_kind;
return_type = getFPType(a_kind);
Expand Down Expand Up @@ -5019,6 +5082,47 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
}
}

void visit_UnsignedIntegerCompare(const ASR::UnsignedIntegerCompare_t &x) {
if (x.m_value) {
this->visit_expr_wrapper(x.m_value, true);
return;
}
this->visit_expr_wrapper(x.m_left, true);
llvm::Value *left = tmp;
this->visit_expr_wrapper(x.m_right, true);
llvm::Value *right = tmp;
switch (x.m_op) {
case (ASR::cmpopType::Eq) : {
tmp = builder->CreateICmpEQ(left, right);
break;
}
case (ASR::cmpopType::Gt) : {
tmp = builder->CreateICmpUGT(left, right);
break;
}
case (ASR::cmpopType::GtE) : {
tmp = builder->CreateICmpUGE(left, right);
break;
}
case (ASR::cmpopType::Lt) : {
tmp = builder->CreateICmpULT(left, right);
break;
}
case (ASR::cmpopType::LtE) : {
tmp = builder->CreateICmpULE(left, right);
break;
}
case (ASR::cmpopType::NotEq) : {
tmp = builder->CreateICmpNE(left, right);
break;
}
default : {
throw CodeGenError("Comparison operator not implemented",
x.base.base.loc);
}
}
}

void visit_RealCompare(const ASR::RealCompare_t &x) {
if (x.m_value) {
this->visit_expr_wrapper(x.m_value, true);
Expand Down Expand Up @@ -5498,7 +5602,8 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
tmp = lfortran_str_slice(str, left, right, step, left_present, right_present);
}

void visit_IntegerBinOp(const ASR::IntegerBinOp_t &x) {
template <typename T>
void handle_SU_IntegerBinOp(const T &x) {
if (x.m_value) {
this->visit_expr_wrapper(x.m_value, true);
return;
Expand All @@ -5507,7 +5612,8 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
llvm::Value *left_val = tmp;
this->visit_expr_wrapper(x.m_right, true);
llvm::Value *right_val = tmp;
LCOMPILERS_ASSERT(ASRUtils::is_integer(*x.m_type))
LCOMPILERS_ASSERT(ASRUtils::is_integer(*x.m_type) ||
ASRUtils::is_unsigned_integer(*x.m_type))
switch (x.m_op) {
case ASR::binopType::Add: {
tmp = builder->CreateAdd(left_val, right_val);
Expand Down Expand Up @@ -5571,6 +5677,14 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
}
}

void visit_IntegerBinOp(const ASR::IntegerBinOp_t &x) {
handle_SU_IntegerBinOp(x);
}

void visit_UnsignedIntegerBinOp(const ASR::UnsignedIntegerBinOp_t &x) {
handle_SU_IntegerBinOp(x);
}

void visit_RealBinOp(const ASR::RealBinOp_t &x) {
if (x.m_value) {
this->visit_expr_wrapper(x.m_value, true);
Expand Down Expand Up @@ -5776,11 +5890,11 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
tmp = lfortran_complex_bin_op(zero_c, c, f_name, type);
}

void visit_IntegerConstant(const ASR::IntegerConstant_t &x) {
template <typename T>
void handle_SU_IntegerConstant(const T &x) {
int64_t val = x.m_n;
int a_kind = ASRUtils::extract_kind_from_ttype_t(x.m_type);
switch( a_kind ) {

case 1: {
tmp = llvm::ConstantInt::get(context, llvm::APInt(8, val, true));
break ;
Expand All @@ -5805,6 +5919,14 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
}
}

void visit_IntegerConstant(const ASR::IntegerConstant_t &x) {
handle_SU_IntegerConstant(x);
}

void visit_UnsignedIntegerConstant(const ASR::UnsignedIntegerConstant_t &x) {
handle_SU_IntegerConstant(x);
}

void visit_RealConstant(const ASR::RealConstant_t &x) {
double val = x.m_r;
int a_kind = ((ASR::Real_t*)(&(x.m_type->base)))->m_kind;
Expand Down Expand Up @@ -6385,6 +6507,24 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
}
break;
}
case (ASR::cast_kindType::IntegerToUnsignedInteger) : {
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->CreateSExt(tmp, getIntType(dest_kind));
} else {
tmp = builder->CreateTrunc(tmp, getIntType(dest_kind));
}
}
break;
}
case (ASR::cast_kindType::UnsignedIntegerToInteger) : {
// tmp = tmp
break;
}
case (ASR::cast_kindType::ComplexToComplex) : {
llvm::Type *target_type;
int arg_kind = -1, dest_kind = -1;
Expand Down Expand Up @@ -6698,6 +6838,31 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
}
}
args.push_back(tmp);
} else if (ASRUtils::is_unsigned_integer(*t)) {
switch( a_kind ) {
case 1 : {
fmt.push_back("%hhi");
break;
}
case 2 : {
fmt.push_back("%hi");
break;
}
case 4 : {
fmt.push_back("%d");
break;
}
case 8 : {
fmt.push_back("%lld");
break;
}
default: {
throw CodeGenError(R"""(Printing support is available only
for 8, 16, 32, and 64 bit unsigned integer kinds.)""",
x.base.base.loc);
}
}
args.push_back(tmp);
} else if (ASRUtils::is_real(*t)) {
llvm::Value *d;
switch( a_kind ) {
Expand Down Expand Up @@ -7093,6 +7258,11 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
target_type = getIntType(a_kind);
break;
}
case (ASR::ttypeType::UnsignedInteger) : {
int a_kind = down_cast<ASR::UnsignedInteger_t>(arg_type)->m_kind;
target_type = getIntType(a_kind);
break;
}
case (ASR::ttypeType::Real) : {
int a_kind = down_cast<ASR::Real_t>(arg_type)->m_kind;
target_type = getFPType(a_kind);
Expand Down
Loading

0 comments on commit 1ca113f

Please sign in to comment.