Skip to content

Commit 1aad65e

Browse files
authored
Merge pull request #1822 from czgdp1807/c_p_ptr
Add ``lower_bounds`` in ``CPtrToPointer``
2 parents 31ce17a + 5dbf888 commit 1aad65e

13 files changed

+103
-51
lines changed

integration_tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,7 @@ RUN(NAME bindc_01 LABELS cpython llvm c)
288288
RUN(NAME bindc_02 LABELS cpython llvm c)
289289
RUN(NAME bindc_04 LABELS llvm c)
290290
RUN(NAME bindc_07 LABELS cpython llvm c)
291+
RUN(NAME bindc_08 LABELS cpython llvm c)
291292
RUN(NAME exit_01 LABELS cpython llvm c)
292293
RUN(NAME exit_02 FAIL LABELS cpython llvm c)
293294
RUN(NAME exit_03 LABELS cpython llvm c wasm wasm_x86 wasm_x64)

integration_tests/bindc_08.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# file: main.py
2+
from lpython import CPtr, i32, dataclass, c_p_pointer, Pointer, empty_c_void_p, p_c_pointer
3+
4+
from numpy import empty
5+
6+
@dataclass
7+
class Foo:
8+
x: i32
9+
y: i32
10+
11+
def init(foos_ptr: CPtr) -> None:
12+
foos: Pointer[Foo[1]] = c_p_pointer(foos_ptr, Foo[1])
13+
foos[0] = Foo(3, 2)
14+
15+
def main() -> None:
16+
foos: Foo[1] = empty(1, dtype=Foo)
17+
foos_ptr: CPtr = empty_c_void_p()
18+
foos[0] = Foo(0, 1)
19+
p_c_pointer(foos, foos_ptr)
20+
init(foos_ptr)
21+
print("foos[0].x = ", foos[0].x)
22+
print("foos[0].y = ", foos[0].y)
23+
assert foos[0].x == 3
24+
assert foos[0].y == 2
25+
26+
main()

src/libasr/ASR.asdl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ stmt
207207
| ListAppend(expr a, expr ele)
208208
| AssociateBlockCall(symbol m)
209209
| SelectType(expr selector, type_stmt* body, stmt* default)
210-
| CPtrToPointer(expr cptr, expr ptr, expr? shape)
210+
| CPtrToPointer(expr cptr, expr ptr, expr? shape, expr? lower_bounds)
211211
| BlockCall(int label, symbol m)
212212
| SetInsert(expr a, expr ele)
213213
| SetRemove(expr a, expr ele)

src/libasr/codegen/asr_to_c.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1090,14 +1090,19 @@ R"(
10901090
std::string dest_src = std::move(src);
10911091
src = "";
10921092
std::string indent(indentation_level*indentation_spaces, ' ');
1093+
ASR::ArrayConstant_t* lower_bounds = nullptr;
1094+
if( x.m_lower_bounds ) {
1095+
LCOMPILERS_ASSERT(ASR::is_a<ASR::ArrayConstant_t>(*x.m_lower_bounds));
1096+
lower_bounds = ASR::down_cast<ASR::ArrayConstant_t>(x.m_lower_bounds);
1097+
}
10931098
if( ASRUtils::is_array(ASRUtils::expr_type(x.m_ptr)) ) {
10941099
std::string dim_set_code = "";
10951100
ASR::dimension_t* m_dims = nullptr;
10961101
int n_dims = ASRUtils::extract_dimensions_from_ttype(ASRUtils::expr_type(x.m_ptr), m_dims);
10971102
dim_set_code = indent + dest_src + "->n_dims = " + std::to_string(n_dims) + ";\n";
10981103
for( int i = 0; i < n_dims; i++ ) {
1099-
if( m_dims[i].m_start ) {
1100-
visit_expr(*m_dims[i].m_start);
1104+
if( lower_bounds ) {
1105+
visit_expr(*lower_bounds->m_args[i]);
11011106
} else {
11021107
src = "0";
11031108
}

src/libasr/codegen/asr_to_llvm.cpp

Lines changed: 18 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -4400,6 +4400,12 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
44004400
llvm_cptr = builder->CreateBitCast(llvm_cptr, llvm_fptr_data_type->getPointerTo());
44014401
builder->CreateStore(llvm_cptr, fptr_data);
44024402
llvm::Value* prod = llvm::ConstantInt::get(context, llvm::APInt(32, 1));
4403+
ASR::ArrayConstant_t* lower_bounds = nullptr;
4404+
if( x.m_lower_bounds ) {
4405+
LCOMPILERS_ASSERT(ASR::is_a<ASR::ArrayConstant_t>(*x.m_lower_bounds));
4406+
lower_bounds = ASR::down_cast<ASR::ArrayConstant_t>(x.m_lower_bounds);
4407+
LCOMPILERS_ASSERT(fptr_rank == (int) lower_bounds->n_args);
4408+
}
44034409
for( int i = 0; i < fptr_rank; i++ ) {
44044410
llvm::Value* curr_dim = llvm::ConstantInt::get(context, llvm::APInt(32, i));
44054411
llvm::Value* desi = arr_descr->get_pointer_to_dimension_descriptor(fptr_des, curr_dim);
@@ -4409,6 +4415,13 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
44094415
builder->CreateStore(prod, desi_stride);
44104416
llvm::Value* i32_one = llvm::ConstantInt::get(context, llvm::APInt(32, 1));
44114417
llvm::Value* new_lb = i32_one;
4418+
if( lower_bounds ) {
4419+
int ptr_loads_copy = ptr_loads;
4420+
ptr_loads = 2;
4421+
this->visit_expr_wrapper(lower_bounds->m_args[i], true);
4422+
ptr_loads = ptr_loads_copy;
4423+
new_lb = tmp;
4424+
}
44124425
llvm::Value* new_ub = shape_data ? CreateLoad(llvm_utils->create_ptr_gep(shape_data, i)) : i32_one;
44134426
builder->CreateStore(new_lb, desi_lb);
44144427
llvm::Value* new_size = builder->CreateAdd(builder->CreateSub(new_ub, new_lb), i32_one);
@@ -6048,46 +6061,11 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
60486061
for (size_t i=0; i < x.n_args; i++) {
60496062
llvm::Value *llvm_el = llvm_utils->create_gep(p_fxn, i);
60506063
ASR::expr_t *el = x.m_args[i];
6051-
llvm::Value *llvm_val;
6052-
if (ASR::is_a<ASR::Integer_t>(*x.m_type)) {
6053-
ASR::IntegerConstant_t *ci = ASR::down_cast<ASR::IntegerConstant_t>(el);
6054-
switch (ASR::down_cast<ASR::Integer_t>(x.m_type)->m_kind) {
6055-
case (4) : {
6056-
int32_t el_value = ci->m_n;
6057-
llvm_val = llvm::ConstantInt::get(context, llvm::APInt(32, static_cast<int32_t>(el_value), true));
6058-
break;
6059-
}
6060-
case (8) : {
6061-
int64_t el_value = ci->m_n;
6062-
llvm_val = llvm::ConstantInt::get(context, llvm::APInt(32, el_value, true));
6063-
break;
6064-
}
6065-
default :
6066-
throw CodeGenError("ConstArray integer kind not supported yet");
6067-
}
6068-
} else if (ASR::is_a<ASR::Real_t>(*x.m_type)) {
6069-
ASR::RealConstant_t *cr = ASR::down_cast<ASR::RealConstant_t>(el);
6070-
switch (ASR::down_cast<ASR::Real_t>(x.m_type)->m_kind) {
6071-
case (4) : {
6072-
float el_value = cr->m_r;
6073-
llvm_val = llvm::ConstantFP::get(context, llvm::APFloat(el_value));
6074-
break;
6075-
}
6076-
case (8) : {
6077-
double el_value = cr->m_r;
6078-
llvm_val = llvm::ConstantFP::get(context, llvm::APFloat(el_value));
6079-
break;
6080-
}
6081-
default :
6082-
throw CodeGenError("ConstArray real kind not supported yet");
6083-
}
6084-
} else if (ASR::is_a<ASR::Logical_t>(*x.m_type)) {
6085-
ASR::LogicalConstant_t *cr = ASR::down_cast<ASR::LogicalConstant_t>(el);
6086-
llvm_val = llvm::ConstantInt::get(context, llvm::APInt(1, cr->m_value));
6087-
} else {
6088-
throw CodeGenError("ConstArray type not supported yet");
6089-
}
6090-
builder->CreateStore(llvm_val, llvm_el);
6064+
int64_t ptr_loads_copy = ptr_loads;
6065+
ptr_loads = 2;
6066+
this->visit_expr_wrapper(el, true);
6067+
ptr_loads = ptr_loads_copy;
6068+
builder->CreateStore(tmp, llvm_el);
60916069
}
60926070
// Return the vector as float* type:
60936071
tmp = llvm_utils->create_gep(p_fxn, 0);

src/lpython/semantics/python_ast_to_asr.cpp

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2513,6 +2513,35 @@ class CommonVisitor : public AST::BaseVisitor<Struct> {
25132513
current_scope->add_or_overwrite_symbol(var_name, v_sym);
25142514
}
25152515

2516+
#define fill_shape_and_lower_bound_for_CPtrToPointer() ASR::dimension_t* target_dims = nullptr; \
2517+
int target_n_dims = ASRUtils::extract_dimensions_from_ttype(target_type, target_dims); \
2518+
ASR::expr_t* target_shape = nullptr; \
2519+
ASR::expr_t* lower_bounds = nullptr; \
2520+
if( target_n_dims > 0 ) { \
2521+
Vec<ASR::expr_t*> sizes, lbs; \
2522+
sizes.reserve(al, target_n_dims); \
2523+
lbs.reserve(al, target_n_dims); \
2524+
bool success = true; \
2525+
for( int i = 0; i < target_n_dims; i++ ) { \
2526+
if( target_dims->m_length == nullptr ) { \
2527+
success = false; \
2528+
break; \
2529+
} \
2530+
sizes.push_back(al, target_dims->m_length); \
2531+
lbs.push_back(al, ASRUtils::EXPR(ASR::make_IntegerConstant_t( \
2532+
al, loc, 0, ASRUtils::TYPE( \
2533+
ASR::make_Integer_t(al, loc, 4, nullptr, 0))))); \
2534+
} \
2535+
if( success ) { \
2536+
target_shape = ASRUtils::EXPR(ASR::make_ArrayConstant_t(al, \
2537+
loc, sizes.p, sizes.size(), ASRUtils::expr_type(target_dims[0].m_length), \
2538+
ASR::arraystorageType::RowMajor)); \
2539+
lower_bounds = ASRUtils::EXPR(ASR::make_ArrayConstant_t(al, \
2540+
loc, lbs.p, lbs.size(), ASRUtils::expr_type(lbs[0]), \
2541+
ASR::arraystorageType::RowMajor)); \
2542+
} \
2543+
} \
2544+
25162545
ASR::asr_t* create_CPtrToPointerFromArgs(AST::expr_t* ast_cptr, AST::expr_t* ast_pptr,
25172546
AST::expr_t* ast_type_expr, const Location& loc) {
25182547
this->visit_expr(*ast_cptr);
@@ -2532,8 +2561,8 @@ class CommonVisitor : public AST::BaseVisitor<Struct> {
25322561
);
25332562
throw SemanticAbort();
25342563
}
2535-
return ASR::make_CPtrToPointer_t(al, loc, cptr,
2536-
pptr, nullptr);
2564+
fill_shape_and_lower_bound_for_CPtrToPointer();
2565+
return ASR::make_CPtrToPointer_t(al, loc, cptr, pptr, target_shape, lower_bounds);
25372566
}
25382567

25392568
void visit_AnnAssignUtil(const AST::AnnAssign_t& x, std::string& var_name,
@@ -6151,8 +6180,10 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
61516180
);
61526181
throw SemanticAbort();
61536182
}
6154-
return ASR::make_CPtrToPointer_t(al, x.base.base.loc, cptr,
6155-
pptr, nullptr);
6183+
const Location& loc = x.base.base.loc;
6184+
fill_shape_and_lower_bound_for_CPtrToPointer();
6185+
return ASR::make_CPtrToPointer_t(al, loc, cptr,
6186+
pptr, target_shape, lower_bounds);
61566187
}
61576188

61586189
ASR::asr_t* create_PointerToCPtr(const AST::Call_t& x) {

src/runtime/lpython/lpython.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,10 @@ def __call__(self, arg):
4444
return self._convert(arg)
4545

4646
def dataclass(arg):
47-
arg.__class_getitem__ = lambda self: None
47+
def __class_getitem__(key):
48+
return Array(arg, key)
49+
arg.__class_getitem__ = __class_getitem__
50+
4851
return py_dataclass(arg)
4952

5053
def is_dataclass(obj):
@@ -266,6 +269,8 @@ def convert_type_to_ctype(arg):
266269
elif arg is None:
267270
raise NotImplementedError("Type cannot be None")
268271
elif isinstance(arg, Array):
272+
if is_dataclass(arg._type):
273+
return arg
269274
type = convert_type_to_ctype(arg._type)
270275
return ctypes.POINTER(type)
271276
elif is_dataclass(arg):
@@ -535,6 +540,8 @@ def __setattr__(self, name: str, value):
535540
def c_p_pointer(cptr, targettype):
536541
targettype_ptr = convert_type_to_ctype(targettype)
537542
if isinstance(targettype, Array):
543+
if py_is_dataclass(targettype._type):
544+
return ctypes.cast(cptr.value, ctypes.py_object).value
538545
newa = ctypes.cast(cptr, targettype_ptr)
539546
return newa
540547
else:

tests/reference/asr-bindc_01-6d521a9.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"outfile": null,
77
"outfile_hash": null,
88
"stdout": "asr-bindc_01-6d521a9.stdout",
9-
"stdout_hash": "d02c57ff6ddb41568c291b11a31301870bf2bc3a970461a71ec23a9d",
9+
"stdout_hash": "26baf870cb5fc3b568cb3d4bf45527713699c39609b6598186843330",
1010
"stderr": null,
1111
"stderr_hash": null,
1212
"returncode": 0

tests/reference/asr-bindc_01-6d521a9.stdout

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
(Var 5 queries)
3737
(Var 5 x)
3838
()
39+
()
3940
)
4041
(Print
4142
()

tests/reference/asr-bindc_02-bc1a7ea.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"outfile": null,
77
"outfile_hash": null,
88
"stdout": "asr-bindc_02-bc1a7ea.stdout",
9-
"stdout_hash": "a74aa56cff206d4ef8fb0766f1cf596c122255882a7df3f5e4fcf4e7",
9+
"stdout_hash": "dcf32037db14152961ae628f9687bfe7dfba3a34bb5a0e8da314fed1",
1010
"stderr": null,
1111
"stderr_hash": null,
1212
"returncode": 0

tests/reference/asr-bindc_02-bc1a7ea.stdout

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
(Var 196 queries)
3737
(Var 196 x)
3838
()
39+
()
3940
)
4041
(Print
4142
()
@@ -271,6 +272,7 @@
271272
(Var 193 yq)
272273
(Var 193 yptr1)
273274
()
275+
()
274276
)
275277
(Print
276278
()

tests/reference/asr-structs_02-2ab459a.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"outfile": null,
77
"outfile_hash": null,
88
"stdout": "asr-structs_02-2ab459a.stdout",
9-
"stdout_hash": "ae8e8d2163b51eb20e19e6257618899aa4fbe78452e760a38608651d",
9+
"stdout_hash": "c2089c22d28d4a379936dcc63db58a39094875021b2a12bd51e70583",
1010
"stderr": null,
1111
"stderr_hash": null,
1212
"returncode": 0

tests/reference/asr-structs_02-2ab459a.stdout

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,7 @@
305305
(Var 3 a)
306306
(Var 3 a2)
307307
()
308+
()
308309
)
309310
(Print
310311
()

0 commit comments

Comments
 (0)