Skip to content

Commit

Permalink
Merge pull request #2137 from Smit-create/i-2125
Browse files Browse the repository at this point in the history
C: Fix struct deepcopy
  • Loading branch information
Smit-create committed Jul 10, 2023
2 parents 230c97f + 054b93f commit c6628be
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 6 deletions.
1 change: 1 addition & 0 deletions integration_tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,7 @@ RUN(NAME structs_29 LABELS cpython llvm)
RUN(NAME structs_30 LABELS cpython llvm c)
RUN(NAME structs_31 LABELS cpython llvm c)
RUN(NAME structs_32 LABELS cpython llvm c)
RUN(NAME structs_33 LABELS cpython llvm c)

RUN(NAME symbolics_01 LABELS cpython_sym c_sym)
RUN(NAME symbolics_02 LABELS cpython_sym c_sym)
Expand Down
24 changes: 24 additions & 0 deletions integration_tests/structs_33.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from lpython import packed, dataclass, i32, ccallback, CPtr, ccall

# test issue 2125

@packed
@dataclass
class inner_struct:
inner_field: i32 = 0


@packed
@dataclass
class outer_struct:
inner_s : inner_struct = inner_struct()


def check() -> None:
outer_struct_instance : outer_struct = outer_struct(inner_struct(5))
outer_struct_instance2 : outer_struct = outer_struct_instance
inner_struct_instance : inner_struct = outer_struct_instance2.inner_s
assert inner_struct_instance.inner_field == 5


check()
13 changes: 7 additions & 6 deletions src/libasr/codegen/c_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -842,32 +842,33 @@ class CCPPDSUtils {
+ struct_type_str + "* src, "
+ struct_type_str + "* dest)";
func_decls += "inline " + signature + ";\n";
generated_code += indent + signature + " {\n";
std::string tmp_generated = indent + signature + " {\n";
for(size_t i=0; i < struct_type_t->n_members; i++) {
std::string mem_name = std::string(struct_type_t->m_members[i]);
ASR::symbol_t* member = struct_type_t->m_symtab->get_symbol(mem_name);
ASR::ttype_t* member_type_asr = ASRUtils::symbol_type(member);
if( CUtils::is_non_primitive_DT(member_type_asr) ||
ASR::is_a<ASR::Character_t>(*member_type_asr) ) {
generated_code += indent + tab + get_deepcopy(member_type_asr, "&(src->" + mem_name + ")",
tmp_generated += indent + tab + get_deepcopy(member_type_asr, "&(src->" + mem_name + ")",
"&(dest->" + mem_name + ")") + ";\n";
} else if( ASRUtils::is_array(member_type_asr) ) {
ASR::dimension_t* m_dims = nullptr;
size_t n_dims = ASRUtils::extract_dimensions_from_ttype(member_type_asr, m_dims);
if( ASRUtils::is_fixed_size_array(m_dims, n_dims) ) {
std::string array_size = std::to_string(ASRUtils::get_fixed_size_of_array(m_dims, n_dims));
array_size += "*sizeof(" + CUtils::get_c_type_from_ttype_t(member_type_asr) + ")";
generated_code += indent + tab + "memcpy(dest->" + mem_name + ", src->" + mem_name +
tmp_generated += indent + tab + "memcpy(dest->" + mem_name + ", src->" + mem_name +
", " + array_size + ");\n";
} else {
generated_code += indent + tab + get_deepcopy(member_type_asr, "src->" + mem_name,
tmp_generated += indent + tab + get_deepcopy(member_type_asr, "src->" + mem_name,
"dest->" + mem_name) + ";\n";
}
} else {
generated_code += indent + tab + "dest->" + mem_name + " = " + " src->" + mem_name + ";\n";
tmp_generated += indent + tab + "dest->" + mem_name + " = " + " src->" + mem_name + ";\n";
}
}
generated_code += indent + "}\n\n";
tmp_generated += indent + "}\n\n";
generated_code += tmp_generated;
}

void list_deepcopy(std::string list_struct_type,
Expand Down
13 changes: 13 additions & 0 deletions tests/reference/c-structs_33-4a3339f.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"basename": "c-structs_33-4a3339f",
"cmd": "lpython --no-color --show-c {infile}",
"infile": "tests/../integration_tests/structs_33.py",
"infile_hash": "15fdcb483c864b6322ebcf6c495e635bbe917f1d8b407ccf4dc3e2ee",
"outfile": null,
"outfile_hash": null,
"stdout": "c-structs_33-4a3339f.stdout",
"stdout_hash": "425a22068f547e15ba187e2974220f28f0af3a70305b67cfd4a6a655",
"stderr": null,
"stderr_hash": null,
"returncode": 0
}
61 changes: 61 additions & 0 deletions tests/reference/c-structs_33-4a3339f.stdout
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#include <inttypes.h>

#include <stdlib.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <lfortran_intrinsics.h>

struct dimension_descriptor
{
int32_t lower_bound, length;
};
struct __attribute__((packed)) inner_struct {
int32_t inner_field;
};

struct __attribute__((packed)) outer_struct {
struct inner_struct inner_s;
};


inline void struct_deepcopy_outer_struct(struct outer_struct* src, struct outer_struct* dest);
inline void struct_deepcopy_inner_struct(struct inner_struct* src, struct inner_struct* dest);


// Implementations
void check()
{
struct inner_struct inner_struct_instance_value;
struct inner_struct* inner_struct_instance = &inner_struct_instance_value;
struct outer_struct outer_struct_instance_value;
struct outer_struct* outer_struct_instance = &outer_struct_instance_value;
struct outer_struct outer_struct_instance2_value;
struct outer_struct* outer_struct_instance2 = &outer_struct_instance2_value;
outer_struct_instance->inner_s.inner_field = 5;
struct_deepcopy_outer_struct(outer_struct_instance, outer_struct_instance2);
struct_deepcopy_inner_struct(&outer_struct_instance2->inner_s, inner_struct_instance);
ASSERT(inner_struct_instance->inner_field == 5);
}

void _lpython_main_program()
{
check();
}

int main(int argc, char* argv[])
{
_lpython_set_argv(argc, argv);
_lpython_main_program();
return 0;
}

void struct_deepcopy_inner_struct(struct inner_struct* src, struct inner_struct* dest) {
dest->inner_field = src->inner_field;
}

void struct_deepcopy_outer_struct(struct outer_struct* src, struct outer_struct* dest) {
struct_deepcopy_inner_struct(&(src->inner_s), &(dest->inner_s));;
}


4 changes: 4 additions & 0 deletions tests/tests.toml
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,10 @@ asr = true
filename = "../integration_tests/structs_05.py"
asr = true

[[test]]
filename = "../integration_tests/structs_33.py"
c = true

[[test]]
filename = "../integration_tests/callback_01.py"
asr = true
Expand Down

0 comments on commit c6628be

Please sign in to comment.