diff --git a/integration_tests/bindc_03.py b/integration_tests/bindc_03.py index d1e9fd17e4..d1153d36f2 100644 --- a/integration_tests/bindc_03.py +++ b/integration_tests/bindc_03.py @@ -1,6 +1,7 @@ from lpython import (c_p_pointer, CPtr, pointer, i32, Pointer, ccall, p_c_pointer, dataclass, - ccallable, empty_c_void_p) + ccallable, empty_c_void_p, cptr_to_u64, + u64_to_cptr, u64) @dataclass class ArrayWrapped: @@ -51,6 +52,11 @@ def run(): assert a != empty_c_void_p() array_wrapped.array = a f(array_wrapped.array) + q: u64 = cptr_to_u64(a) + x: CPtr + x = u64_to_cptr(q) + array_wrapped.array = x + f(array_wrapped.array) array_wrapped1 = array_wrapped h(array_wrapped1.array) diff --git a/src/libasr/ASR.asdl b/src/libasr/ASR.asdl index fc690bde91..4b6de2c536 100644 --- a/src/libasr/ASR.asdl +++ b/src/libasr/ASR.asdl @@ -414,6 +414,8 @@ cast_kind | LogicalToCharacter | UnsignedIntegerToInteger | IntegerToUnsignedInteger + | CPtrToUnsignedInteger + | UnsignedIntegerToCPtr dimension = (expr? start, expr? length) diff --git a/src/libasr/codegen/asr_to_c_cpp.h b/src/libasr/codegen/asr_to_c_cpp.h index 57a3f7fbdd..a5828eab37 100644 --- a/src/libasr/codegen/asr_to_c_cpp.h +++ b/src/libasr/codegen/asr_to_c_cpp.h @@ -1513,6 +1513,16 @@ R"(#include last_expr_precedence = 2; break; } + case (ASR::cast_kindType::CPtrToUnsignedInteger) : { + src = "(uint64_t)(" + src + ")"; + last_expr_precedence = 2; + break; + } + case (ASR::cast_kindType::UnsignedIntegerToCPtr) : { + src = "(void*)(" + src + ")"; + last_expr_precedence = 2; + break; + } default : throw CodeGenError("Cast kind " + std::to_string(x.m_kind) + " not implemented", x.base.base.loc); } diff --git a/src/libasr/codegen/asr_to_llvm.cpp b/src/libasr/codegen/asr_to_llvm.cpp index cf49850006..dc5e559d22 100644 --- a/src/libasr/codegen/asr_to_llvm.cpp +++ b/src/libasr/codegen/asr_to_llvm.cpp @@ -6818,6 +6818,14 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor // tmp = tmp break; } + case (ASR::cast_kindType::CPtrToUnsignedInteger) : { + tmp = builder->CreatePtrToInt(tmp, getIntType(8, false)); + break; + } + case (ASR::cast_kindType::UnsignedIntegerToCPtr) : { + tmp = builder->CreateIntToPtr(tmp, llvm::Type::getVoidTy(context)->getPointerTo()); + break; + } case (ASR::cast_kindType::ComplexToComplex) : { llvm::Type *target_type; int arg_kind = -1, dest_kind = -1; diff --git a/src/lpython/semantics/python_ast_to_asr.cpp b/src/lpython/semantics/python_ast_to_asr.cpp index 8c4dbbc497..b9923dc55b 100644 --- a/src/lpython/semantics/python_ast_to_asr.cpp +++ b/src/lpython/semantics/python_ast_to_asr.cpp @@ -6985,7 +6985,7 @@ class BodyVisitor : public CommonVisitor { // This will all be removed once we port it to intrinsic functions // Intrinsic functions if (call_name == "size") { - parse_args(x, args);; + parse_args(x, args); if( args.size() < 1 || args.size() > 2 ) { throw SemanticError("array accepts only 1 (arr) or 2 (arr, axis) arguments, got " + std::to_string(args.size()) + " arguments instead.", @@ -7018,6 +7018,43 @@ class BodyVisitor : public CommonVisitor { } tmp = ASR::make_PointerNullConstant_t(al, x.base.base.loc, type); return; + } else if (call_name == "cptr_to_u64") { + parse_args(x, args); + if (args.size() != 1) { + throw SemanticError("cptr_to_u64 accpets exactly 1 argument", + x.base.base.loc); + } + + ASR::expr_t *var = args[0].m_value; + ASR::ttype_t *a_type = ASRUtils::expr_type(var); + if (!ASR::is_a(*a_type)) { + throw SemanticError("Argument of type `CPtr` is expected in cptr_to_u64", + x.base.base.loc); + } + ASR::ttype_t *u_type = ASRUtils::TYPE(ASR::make_UnsignedInteger_t(al, + x.base.base.loc, 8, nullptr, 0)); + + tmp = ASR::make_Cast_t(al, x.base.base.loc, + var, ASR::cast_kindType::CPtrToUnsignedInteger, u_type, nullptr); + return; + } else if (call_name == "u64_to_cptr") { + parse_args(x, args); + if (args.size() != 1) { + throw SemanticError("u64_to_cptr accpets exactly 1 argument", + x.base.base.loc); + } + + ASR::expr_t *var = args[0].m_value; + ASR::ttype_t *a_type = ASRUtils::expr_type(var); + if (!ASR::is_a(*a_type)) { + throw SemanticError("Argument of type `u64` is expected in u64_to_cptr", + x.base.base.loc); + } + ASR::ttype_t *c_type = ASRUtils::TYPE(ASR::make_CPtr_t(al, x.base.base.loc)); + + tmp = ASR::make_Cast_t(al, x.base.base.loc, + var, ASR::cast_kindType::UnsignedIntegerToCPtr, c_type, nullptr); + return; } else if (call_name == "TypeVar") { // Ignore TypeVar for now, we handle it based on the identifier itself tmp = nullptr; diff --git a/src/runtime/lpython/lpython.py b/src/runtime/lpython/lpython.py index 62c70bbb8e..79f28948b4 100644 --- a/src/runtime/lpython/lpython.py +++ b/src/runtime/lpython/lpython.py @@ -591,6 +591,12 @@ def __repr__(self): return ctypes_c_void_p() +def cptr_to_u64(cptr): + return ctypes.addressof(cptr) + +def u64_to_cptr(ivalue): + return ctypes.c_void_p(ivalue) + def sizeof(arg): return ctypes.sizeof(convert_type_to_ctype(arg))