Skip to content

Commit 1ca113f

Browse files
committed
Backend: add support for unsigned integers
1 parent 248725b commit 1ca113f

File tree

4 files changed

+242
-5
lines changed

4 files changed

+242
-5
lines changed

src/libasr/asr_utils.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -974,6 +974,10 @@ ASR::asr_t* make_Cast_t_value(Allocator &al, const Location &a_loc,
974974
int64_t int_value = ASR::down_cast<ASR::IntegerConstant_t>(
975975
ASRUtils::expr_value(a_arg))->m_n;
976976
value = ASR::down_cast<ASR::expr_t>(ASR::make_IntegerConstant_t(al, a_loc, int_value, a_type));
977+
} else if (a_kind == ASR::cast_kindType::IntegerToUnsignedInteger) {
978+
int64_t int_value = ASR::down_cast<ASR::IntegerConstant_t>(
979+
ASRUtils::expr_value(a_arg))->m_n;
980+
value = ASR::down_cast<ASR::expr_t>(ASR::make_UnsignedIntegerConstant_t(al, a_loc, int_value, a_type));
977981
} else if (a_kind == ASR::cast_kindType::IntegerToLogical) {
978982
// TODO: implement
979983
} else if (a_kind == ASR::cast_kindType::ComplexToComplex) {

src/libasr/asr_utils.h

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -842,6 +842,11 @@ static inline bool extract_value(ASR::expr_t* value_expr, T& value) {
842842
value = (T) const_int->m_n;
843843
break;
844844
}
845+
case ASR::exprType::UnsignedIntegerConstant: {
846+
ASR::UnsignedIntegerConstant_t* const_int = ASR::down_cast<ASR::UnsignedIntegerConstant_t>(value_expr);
847+
value = (T) const_int->m_n;
848+
break;
849+
}
845850
case ASR::exprType::RealConstant: {
846851
ASR::RealConstant_t* const_real = ASR::down_cast<ASR::RealConstant_t>(value_expr);
847852
value = (T) const_real->m_r;
@@ -924,6 +929,16 @@ static inline std::string get_type_code(const ASR::ttype_t *t, bool use_undersco
924929
is_dimensional = integer->n_dims > 0;
925930
break;
926931
}
932+
case ASR::ttypeType::UnsignedInteger: {
933+
ASR::UnsignedInteger_t *integer = ASR::down_cast<ASR::UnsignedInteger_t>(t);
934+
res = "u" + std::to_string(integer->m_kind * 8);
935+
if( encode_dimensions_ ) {
936+
encode_dimensions(integer->n_dims, res, use_underscore_sep);
937+
return res;
938+
}
939+
is_dimensional = integer->n_dims > 0;
940+
break;
941+
}
927942
case ASR::ttypeType::Real: {
928943
ASR::Real_t *real = ASR::down_cast<ASR::Real_t>(t);
929944
res = "r" + std::to_string(real->m_kind * 8);
@@ -1090,7 +1105,7 @@ static inline std::string type_to_str_python(const ASR::ttype_t *t,
10901105
{
10911106
switch (t->type) {
10921107
case ASR::ttypeType::Integer: {
1093-
ASR::Integer_t *i = (ASR::Integer_t*)t;
1108+
ASR::Integer_t *i = ASR::down_cast<ASR::Integer_t>(t);
10941109
std::string res = "";
10951110
switch (i->m_kind) {
10961111
case 1: { res = "i8"; break; }
@@ -1104,6 +1119,21 @@ static inline std::string type_to_str_python(const ASR::ttype_t *t,
11041119
}
11051120
return res;
11061121
}
1122+
case ASR::ttypeType::UnsignedInteger: {
1123+
ASR::UnsignedInteger_t *i = ASR::down_cast<ASR::UnsignedInteger_t>(t);
1124+
std::string res = "";
1125+
switch (i->m_kind) {
1126+
case 1: { res = "u8"; break; }
1127+
case 2: { res = "u16"; break; }
1128+
case 4: { res = "u32"; break; }
1129+
case 8: { res = "u64"; break; }
1130+
default: { throw LCompilersException("UnsignedInteger kind not supported"); }
1131+
}
1132+
if (i->n_dims == 1 && for_error_message) {
1133+
res = type_python_1dim_helper(res, i->m_dims);
1134+
}
1135+
return res;
1136+
}
11071137
case ASR::ttypeType::Real: {
11081138
ASR::Real_t *r = (ASR::Real_t*)t;
11091139
std::string res = "";
@@ -1374,6 +1404,9 @@ static inline int extract_kind_from_ttype_t(const ASR::ttype_t* type) {
13741404
case ASR::ttypeType::Integer : {
13751405
return ASR::down_cast<ASR::Integer_t>(type)->m_kind;
13761406
}
1407+
case ASR::ttypeType::UnsignedInteger : {
1408+
return ASR::down_cast<ASR::UnsignedInteger_t>(type)->m_kind;
1409+
}
13771410
case ASR::ttypeType::Real : {
13781411
return ASR::down_cast<ASR::Real_t>(type)->m_kind;
13791412
}
@@ -1406,6 +1439,10 @@ static inline bool is_integer(ASR::ttype_t &x) {
14061439
return ASR::is_a<ASR::Integer_t>(*type_get_past_pointer(&x));
14071440
}
14081441

1442+
static inline bool is_unsigned_integer(ASR::ttype_t &x) {
1443+
return ASR::is_a<ASR::UnsignedInteger_t>(*type_get_past_pointer(&x));
1444+
}
1445+
14091446
static inline bool is_real(ASR::ttype_t &x) {
14101447
return ASR::is_a<ASR::Real_t>(*type_get_past_pointer(&x));
14111448
}
@@ -1485,6 +1522,12 @@ inline int extract_dimensions_from_ttype(ASR::ttype_t *x,
14851522
m_dims = Integer_type->m_dims;
14861523
break;
14871524
}
1525+
case ASR::ttypeType::UnsignedInteger: {
1526+
ASR::UnsignedInteger_t* Integer_type = ASR::down_cast<ASR::UnsignedInteger_t>(x);
1527+
n_dims = Integer_type->n_dims;
1528+
m_dims = Integer_type->m_dims;
1529+
break;
1530+
}
14881531
case ASR::ttypeType::Real: {
14891532
ASR::Real_t* Real_type = ASR::down_cast<ASR::Real_t>(x);
14901533
n_dims = Real_type->n_dims;
@@ -2122,6 +2165,22 @@ inline bool types_equal(ASR::ttype_t *a, ASR::ttype_t *b,
21222165
}
21232166
break;
21242167
}
2168+
case (ASR::ttypeType::UnsignedInteger) : {
2169+
ASR::UnsignedInteger_t *a2 = ASR::down_cast<ASR::UnsignedInteger_t>(a);
2170+
ASR::UnsignedInteger_t *b2 = ASR::down_cast<ASR::UnsignedInteger_t>(b);
2171+
if (a2->m_kind == b2->m_kind) {
2172+
if( check_for_dimensions ) {
2173+
return ASRUtils::dimensions_equal(
2174+
a2->m_dims, a2->n_dims,
2175+
b2->m_dims, b2->n_dims);
2176+
} else {
2177+
return true;
2178+
}
2179+
} else {
2180+
return false;
2181+
}
2182+
break;
2183+
}
21252184
case ASR::ttypeType::CPtr: {
21262185
return true;
21272186
}

src/libasr/codegen/asr_to_llvm.cpp

Lines changed: 174 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2867,6 +2867,36 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
28672867
}
28682868
break;
28692869
}
2870+
case (ASR::ttypeType::UnsignedInteger) : {
2871+
ASR::UnsignedInteger_t* v_type = down_cast<ASR::UnsignedInteger_t>(asr_type);
2872+
m_dims = v_type->m_dims;
2873+
n_dims = v_type->n_dims;
2874+
a_kind = v_type->m_kind;
2875+
if( n_dims > 0 ) {
2876+
if( m_abi == ASR::abiType::BindC ) {
2877+
if( ASRUtils::is_fixed_size_array(v_type->m_dims, v_type->n_dims) ) {
2878+
llvm_type = llvm::ArrayType::get(get_el_type(asr_type), ASRUtils::get_fixed_size_of_array(
2879+
v_type->m_dims, v_type->n_dims));
2880+
} else {
2881+
llvm_type = get_el_type(asr_type)->getPointerTo();
2882+
}
2883+
} else {
2884+
is_array_type = true;
2885+
llvm::Type* el_type = get_el_type(asr_type);
2886+
if( m_storage == ASR::storage_typeType::Allocatable ) {
2887+
is_malloc_array_type = true;
2888+
llvm_type = arr_descr->get_malloc_array_type(asr_type, el_type);
2889+
} else {
2890+
llvm_type = arr_descr->get_array_type(asr_type, el_type);
2891+
}
2892+
}
2893+
} else {
2894+
// LLVM does not distinguish signed and unsigned integer types
2895+
// Only integer operations can be signed/unsigned
2896+
llvm_type = getIntType(a_kind);
2897+
}
2898+
break;
2899+
}
28702900
case (ASR::ttypeType::Real) : {
28712901
ASR::Real_t* v_type = down_cast<ASR::Real_t>(asr_type);
28722902
m_dims = v_type->m_dims;
@@ -3459,6 +3489,34 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
34593489
}
34603490
break;
34613491
}
3492+
case (ASR::ttypeType::UnsignedInteger) : {
3493+
ASR::UnsignedInteger_t* v_type = down_cast<ASR::UnsignedInteger_t>(asr_type);
3494+
n_dims = v_type->n_dims;
3495+
a_kind = v_type->m_kind;
3496+
if( n_dims > 0 ) {
3497+
if (m_abi == ASR::abiType::BindC ||
3498+
(!ASRUtils::is_dimension_empty(v_type->m_dims, v_type->n_dims))) {
3499+
// Bind(C) arrays are represened as a pointer
3500+
type = getIntType(a_kind, true);
3501+
} else {
3502+
is_array_type = true;
3503+
llvm::Type* el_type = get_el_type(asr_type);
3504+
if( m_storage == ASR::storage_typeType::Allocatable ) {
3505+
type = arr_descr->get_malloc_array_type(asr_type, el_type, get_pointer);
3506+
} else {
3507+
type = arr_descr->get_array_type(asr_type, el_type, get_pointer);
3508+
}
3509+
}
3510+
} else {
3511+
if (arg_m_abi == ASR::abiType::BindC
3512+
&& arg_m_value_attr) {
3513+
type = getIntType(a_kind, false);
3514+
} else {
3515+
type = getIntType(a_kind, true);
3516+
}
3517+
}
3518+
break;
3519+
}
34623520
case (ASR::ttypeType::Pointer) : {
34633521
ASR::ttype_t *t2 = ASRUtils::type_get_past_pointer(asr_type);
34643522
bool is_pointer_ = ASR::is_a<ASR::Class_t>(*t2);
@@ -3904,6 +3962,11 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
39043962
return_type = getIntType(a_kind);
39053963
break;
39063964
}
3965+
case (ASR::ttypeType::UnsignedInteger) : {
3966+
int a_kind = down_cast<ASR::UnsignedInteger_t>(return_var_type0)->m_kind;
3967+
return_type = getIntType(a_kind);
3968+
break;
3969+
}
39073970
case (ASR::ttypeType::Real) : {
39083971
int a_kind = down_cast<ASR::Real_t>(return_var_type0)->m_kind;
39093972
return_type = getFPType(a_kind);
@@ -5019,6 +5082,47 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
50195082
}
50205083
}
50215084

5085+
void visit_UnsignedIntegerCompare(const ASR::UnsignedIntegerCompare_t &x) {
5086+
if (x.m_value) {
5087+
this->visit_expr_wrapper(x.m_value, true);
5088+
return;
5089+
}
5090+
this->visit_expr_wrapper(x.m_left, true);
5091+
llvm::Value *left = tmp;
5092+
this->visit_expr_wrapper(x.m_right, true);
5093+
llvm::Value *right = tmp;
5094+
switch (x.m_op) {
5095+
case (ASR::cmpopType::Eq) : {
5096+
tmp = builder->CreateICmpEQ(left, right);
5097+
break;
5098+
}
5099+
case (ASR::cmpopType::Gt) : {
5100+
tmp = builder->CreateICmpUGT(left, right);
5101+
break;
5102+
}
5103+
case (ASR::cmpopType::GtE) : {
5104+
tmp = builder->CreateICmpUGE(left, right);
5105+
break;
5106+
}
5107+
case (ASR::cmpopType::Lt) : {
5108+
tmp = builder->CreateICmpULT(left, right);
5109+
break;
5110+
}
5111+
case (ASR::cmpopType::LtE) : {
5112+
tmp = builder->CreateICmpULE(left, right);
5113+
break;
5114+
}
5115+
case (ASR::cmpopType::NotEq) : {
5116+
tmp = builder->CreateICmpNE(left, right);
5117+
break;
5118+
}
5119+
default : {
5120+
throw CodeGenError("Comparison operator not implemented",
5121+
x.base.base.loc);
5122+
}
5123+
}
5124+
}
5125+
50225126
void visit_RealCompare(const ASR::RealCompare_t &x) {
50235127
if (x.m_value) {
50245128
this->visit_expr_wrapper(x.m_value, true);
@@ -5498,7 +5602,8 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
54985602
tmp = lfortran_str_slice(str, left, right, step, left_present, right_present);
54995603
}
55005604

5501-
void visit_IntegerBinOp(const ASR::IntegerBinOp_t &x) {
5605+
template <typename T>
5606+
void handle_SU_IntegerBinOp(const T &x) {
55025607
if (x.m_value) {
55035608
this->visit_expr_wrapper(x.m_value, true);
55045609
return;
@@ -5507,7 +5612,8 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
55075612
llvm::Value *left_val = tmp;
55085613
this->visit_expr_wrapper(x.m_right, true);
55095614
llvm::Value *right_val = tmp;
5510-
LCOMPILERS_ASSERT(ASRUtils::is_integer(*x.m_type))
5615+
LCOMPILERS_ASSERT(ASRUtils::is_integer(*x.m_type) ||
5616+
ASRUtils::is_unsigned_integer(*x.m_type))
55115617
switch (x.m_op) {
55125618
case ASR::binopType::Add: {
55135619
tmp = builder->CreateAdd(left_val, right_val);
@@ -5571,6 +5677,14 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
55715677
}
55725678
}
55735679

5680+
void visit_IntegerBinOp(const ASR::IntegerBinOp_t &x) {
5681+
handle_SU_IntegerBinOp(x);
5682+
}
5683+
5684+
void visit_UnsignedIntegerBinOp(const ASR::UnsignedIntegerBinOp_t &x) {
5685+
handle_SU_IntegerBinOp(x);
5686+
}
5687+
55745688
void visit_RealBinOp(const ASR::RealBinOp_t &x) {
55755689
if (x.m_value) {
55765690
this->visit_expr_wrapper(x.m_value, true);
@@ -5776,11 +5890,11 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
57765890
tmp = lfortran_complex_bin_op(zero_c, c, f_name, type);
57775891
}
57785892

5779-
void visit_IntegerConstant(const ASR::IntegerConstant_t &x) {
5893+
template <typename T>
5894+
void handle_SU_IntegerConstant(const T &x) {
57805895
int64_t val = x.m_n;
57815896
int a_kind = ASRUtils::extract_kind_from_ttype_t(x.m_type);
57825897
switch( a_kind ) {
5783-
57845898
case 1: {
57855899
tmp = llvm::ConstantInt::get(context, llvm::APInt(8, val, true));
57865900
break ;
@@ -5805,6 +5919,14 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
58055919
}
58065920
}
58075921

5922+
void visit_IntegerConstant(const ASR::IntegerConstant_t &x) {
5923+
handle_SU_IntegerConstant(x);
5924+
}
5925+
5926+
void visit_UnsignedIntegerConstant(const ASR::UnsignedIntegerConstant_t &x) {
5927+
handle_SU_IntegerConstant(x);
5928+
}
5929+
58085930
void visit_RealConstant(const ASR::RealConstant_t &x) {
58095931
double val = x.m_r;
58105932
int a_kind = ((ASR::Real_t*)(&(x.m_type->base)))->m_kind;
@@ -6385,6 +6507,24 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
63856507
}
63866508
break;
63876509
}
6510+
case (ASR::cast_kindType::IntegerToUnsignedInteger) : {
6511+
int arg_kind = -1, dest_kind = -1;
6512+
extract_kinds(x, arg_kind, dest_kind);
6513+
if( arg_kind > 0 && dest_kind > 0 &&
6514+
arg_kind != dest_kind )
6515+
{
6516+
if (dest_kind > arg_kind) {
6517+
tmp = builder->CreateSExt(tmp, getIntType(dest_kind));
6518+
} else {
6519+
tmp = builder->CreateTrunc(tmp, getIntType(dest_kind));
6520+
}
6521+
}
6522+
break;
6523+
}
6524+
case (ASR::cast_kindType::UnsignedIntegerToInteger) : {
6525+
// tmp = tmp
6526+
break;
6527+
}
63886528
case (ASR::cast_kindType::ComplexToComplex) : {
63896529
llvm::Type *target_type;
63906530
int arg_kind = -1, dest_kind = -1;
@@ -6698,6 +6838,31 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
66986838
}
66996839
}
67006840
args.push_back(tmp);
6841+
} else if (ASRUtils::is_unsigned_integer(*t)) {
6842+
switch( a_kind ) {
6843+
case 1 : {
6844+
fmt.push_back("%hhi");
6845+
break;
6846+
}
6847+
case 2 : {
6848+
fmt.push_back("%hi");
6849+
break;
6850+
}
6851+
case 4 : {
6852+
fmt.push_back("%d");
6853+
break;
6854+
}
6855+
case 8 : {
6856+
fmt.push_back("%lld");
6857+
break;
6858+
}
6859+
default: {
6860+
throw CodeGenError(R"""(Printing support is available only
6861+
for 8, 16, 32, and 64 bit unsigned integer kinds.)""",
6862+
x.base.base.loc);
6863+
}
6864+
}
6865+
args.push_back(tmp);
67016866
} else if (ASRUtils::is_real(*t)) {
67026867
llvm::Value *d;
67036868
switch( a_kind ) {
@@ -7093,6 +7258,11 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
70937258
target_type = getIntType(a_kind);
70947259
break;
70957260
}
7261+
case (ASR::ttypeType::UnsignedInteger) : {
7262+
int a_kind = down_cast<ASR::UnsignedInteger_t>(arg_type)->m_kind;
7263+
target_type = getIntType(a_kind);
7264+
break;
7265+
}
70967266
case (ASR::ttypeType::Real) : {
70977267
int a_kind = down_cast<ASR::Real_t>(arg_type)->m_kind;
70987268
target_type = getFPType(a_kind);

0 commit comments

Comments
 (0)