Skip to content

Commit 8da8f21

Browse files
authored
Merge pull request #1848 from Smit-create/i-1736
Support CPtr <-> u64 casting
2 parents d9163ab + 57d7c72 commit 8da8f21

File tree

6 files changed

+71
-2
lines changed

6 files changed

+71
-2
lines changed

integration_tests/bindc_03.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from lpython import (c_p_pointer, CPtr, pointer, i32,
22
Pointer, ccall, p_c_pointer, dataclass,
3-
ccallable, empty_c_void_p)
3+
ccallable, empty_c_void_p, cptr_to_u64,
4+
u64_to_cptr, u64)
45

56
@dataclass
67
class ArrayWrapped:
@@ -51,6 +52,11 @@ def run():
5152
assert a != empty_c_void_p()
5253
array_wrapped.array = a
5354
f(array_wrapped.array)
55+
q: u64 = cptr_to_u64(a)
56+
x: CPtr
57+
x = u64_to_cptr(q)
58+
array_wrapped.array = x
59+
f(array_wrapped.array)
5460
array_wrapped1 = array_wrapped
5561
h(array_wrapped1.array)
5662

src/libasr/ASR.asdl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,8 @@ cast_kind
414414
| LogicalToCharacter
415415
| UnsignedIntegerToInteger
416416
| IntegerToUnsignedInteger
417+
| CPtrToUnsignedInteger
418+
| UnsignedIntegerToCPtr
417419

418420
dimension = (expr? start, expr? length)
419421

src/libasr/codegen/asr_to_c_cpp.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1513,6 +1513,16 @@ R"(#include <stdio.h>
15131513
last_expr_precedence = 2;
15141514
break;
15151515
}
1516+
case (ASR::cast_kindType::CPtrToUnsignedInteger) : {
1517+
src = "(uint64_t)(" + src + ")";
1518+
last_expr_precedence = 2;
1519+
break;
1520+
}
1521+
case (ASR::cast_kindType::UnsignedIntegerToCPtr) : {
1522+
src = "(void*)(" + src + ")";
1523+
last_expr_precedence = 2;
1524+
break;
1525+
}
15161526
default : throw CodeGenError("Cast kind " + std::to_string(x.m_kind) + " not implemented",
15171527
x.base.base.loc);
15181528
}

src/libasr/codegen/asr_to_llvm.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6818,6 +6818,14 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
68186818
// tmp = tmp
68196819
break;
68206820
}
6821+
case (ASR::cast_kindType::CPtrToUnsignedInteger) : {
6822+
tmp = builder->CreatePtrToInt(tmp, getIntType(8, false));
6823+
break;
6824+
}
6825+
case (ASR::cast_kindType::UnsignedIntegerToCPtr) : {
6826+
tmp = builder->CreateIntToPtr(tmp, llvm::Type::getVoidTy(context)->getPointerTo());
6827+
break;
6828+
}
68216829
case (ASR::cast_kindType::ComplexToComplex) : {
68226830
llvm::Type *target_type;
68236831
int arg_kind = -1, dest_kind = -1;

src/lpython/semantics/python_ast_to_asr.cpp

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6985,7 +6985,7 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
69856985
// This will all be removed once we port it to intrinsic functions
69866986
// Intrinsic functions
69876987
if (call_name == "size") {
6988-
parse_args(x, args);;
6988+
parse_args(x, args);
69896989
if( args.size() < 1 || args.size() > 2 ) {
69906990
throw SemanticError("array accepts only 1 (arr) or 2 (arr, axis) arguments, got " +
69916991
std::to_string(args.size()) + " arguments instead.",
@@ -7018,6 +7018,43 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
70187018
}
70197019
tmp = ASR::make_PointerNullConstant_t(al, x.base.base.loc, type);
70207020
return;
7021+
} else if (call_name == "cptr_to_u64") {
7022+
parse_args(x, args);
7023+
if (args.size() != 1) {
7024+
throw SemanticError("cptr_to_u64 accpets exactly 1 argument",
7025+
x.base.base.loc);
7026+
}
7027+
7028+
ASR::expr_t *var = args[0].m_value;
7029+
ASR::ttype_t *a_type = ASRUtils::expr_type(var);
7030+
if (!ASR::is_a<ASR::CPtr_t>(*a_type)) {
7031+
throw SemanticError("Argument of type `CPtr` is expected in cptr_to_u64",
7032+
x.base.base.loc);
7033+
}
7034+
ASR::ttype_t *u_type = ASRUtils::TYPE(ASR::make_UnsignedInteger_t(al,
7035+
x.base.base.loc, 8, nullptr, 0));
7036+
7037+
tmp = ASR::make_Cast_t(al, x.base.base.loc,
7038+
var, ASR::cast_kindType::CPtrToUnsignedInteger, u_type, nullptr);
7039+
return;
7040+
} else if (call_name == "u64_to_cptr") {
7041+
parse_args(x, args);
7042+
if (args.size() != 1) {
7043+
throw SemanticError("u64_to_cptr accpets exactly 1 argument",
7044+
x.base.base.loc);
7045+
}
7046+
7047+
ASR::expr_t *var = args[0].m_value;
7048+
ASR::ttype_t *a_type = ASRUtils::expr_type(var);
7049+
if (!ASR::is_a<ASR::UnsignedInteger_t>(*a_type)) {
7050+
throw SemanticError("Argument of type `u64` is expected in u64_to_cptr",
7051+
x.base.base.loc);
7052+
}
7053+
ASR::ttype_t *c_type = ASRUtils::TYPE(ASR::make_CPtr_t(al, x.base.base.loc));
7054+
7055+
tmp = ASR::make_Cast_t(al, x.base.base.loc,
7056+
var, ASR::cast_kindType::UnsignedIntegerToCPtr, c_type, nullptr);
7057+
return;
70217058
} else if (call_name == "TypeVar") {
70227059
// Ignore TypeVar for now, we handle it based on the identifier itself
70237060
tmp = nullptr;

src/runtime/lpython/lpython.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,12 @@ def __repr__(self):
591591

592592
return ctypes_c_void_p()
593593

594+
def cptr_to_u64(cptr):
595+
return ctypes.addressof(cptr)
596+
597+
def u64_to_cptr(ivalue):
598+
return ctypes.c_void_p(ivalue)
599+
594600
def sizeof(arg):
595601
return ctypes.sizeof(convert_type_to_ctype(arg))
596602

0 commit comments

Comments
 (0)