Thanks to visit codestin.com
Credit goes to github.com

Skip to content

C: Fix struct deepcopy #2137

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jul 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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