[gcc(refs/users/mikael/heads/refactor_descriptor_v05)] gimple-exec: implementation memcpy et correction gestion mémoire
Mikael Morin
mikael@gcc.gnu.org
Wed Jun 11 09:49:45 GMT 2025
https://gcc.gnu.org/g:f6788211809dab7ba4568bcefe620ca11f448a32
commit f6788211809dab7ba4568bcefe620ca11f448a32
Author: Mikael Morin <mikael@gcc.gnu.org>
Date: Wed Jun 11 11:24:05 2025 +0200
gimple-exec: implementation memcpy et correction gestion mémoire
Diff:
---
gcc/cgraphunit.cc | 262 +++++++++++++++++++++++++++++++++++++++++++++---------
1 file changed, 221 insertions(+), 41 deletions(-)
diff --git a/gcc/cgraphunit.cc b/gcc/cgraphunit.cc
index 268e4d66a419..2a50ea931b44 100644
--- a/gcc/cgraphunit.cc
+++ b/gcc/cgraphunit.cc
@@ -2450,6 +2450,7 @@ namespace selftest
void exec_context_evaluate_unary_tests ();
void exec_context_evaluate_binary_tests ();
void exec_context_execute_assign_tests ();
+ void exec_context_print_call_tests ();
void exec_context_execute_call_tests ();
void exec_context_allocate_tests ();
void exec_context_evaluate_condition_tests ();
@@ -2462,7 +2463,7 @@ class data_value
wide_int constant_mask;
wide_int address_mask;
wide_int constant_value;
- vec<stored_address> addresses;
+ auto_vec<stored_address> addresses;
void set_cst_at (unsigned dest_offset, unsigned value_width,
const wide_int &val, unsigned src_offset);
stored_address *find_address (HOST_WIDE_INT offset) const;
@@ -2583,6 +2584,7 @@ class context_printer
friend void selftest::context_printer_print_tests ();
friend void selftest::context_printer_print_first_data_ref_part_tests ();
friend void selftest::context_printer_print_value_update_tests ();
+ friend void selftest::exec_context_print_call_tests ();
public:
context_printer ();
@@ -2595,7 +2597,9 @@ public:
void print_function_exit (struct function * func);
void print_bb_jump (edge e);
void print_bb_entry (basic_block bb);
- tree print_first_data_ref_part (exec_context & context, tree data_ref, unsigned offset, int * ignored_bits);
+ tree print_first_data_ref_part (exec_context & context, tree data_ref,
+ unsigned offset, int * ignored_bits,
+ enum value_type);
void print_ignored_stmt ();
void print_value_update (exec_context & context, tree, const data_value &);
void end_stmt (gimple *);
@@ -2976,7 +2980,8 @@ context_printer::print_bb_entry (basic_block bb)
static tree
-pick_subref_at (tree var_ref, unsigned offset, int * ignored_bits)
+pick_subref_at (tree var_ref, unsigned offset, int * ignored_bits,
+ unsigned min_size)
{
tree ref = var_ref;
unsigned remaining_offset = offset;
@@ -2988,11 +2993,15 @@ pick_subref_at (tree var_ref, unsigned offset, int * ignored_bits)
tree elt_type = TREE_TYPE (var_type);
unsigned elt_width;
gcc_assert (get_constant_type_size (elt_type, elt_width));
+ if (elt_width < min_size)
+ return NULL_TREE;
unsigned HOST_WIDE_INT hw_idx = remaining_offset / elt_width;
tree t_idx = build_int_cst (integer_type_node, hw_idx);
ref = build4 (ARRAY_REF, elt_type, ref,
t_idx, NULL_TREE, NULL_TREE);
remaining_offset -= hw_idx * elt_width;
+ if (elt_width == min_size)
+ break;
}
else if (TREE_CODE (var_type) == RECORD_TYPE)
{
@@ -3029,7 +3038,15 @@ pick_subref_at (tree var_ref, unsigned offset, int * ignored_bits)
gcc_assert (field != NULL_TREE
&& field_position >= 0);
- ref = build3 (COMPONENT_REF, TREE_TYPE (field),
+ tree field_type = TREE_TYPE (field);
+
+ unsigned field_width;
+ if (!get_constant_type_size (field_type, field_width))
+ gcc_unreachable ();
+ else if (field_width < min_size)
+ return NULL_TREE;
+
+ ref = build3 (COMPONENT_REF, field_type,
ref, field, NULL_TREE);
if (field_position > remaining_offset)
{
@@ -3039,6 +3056,9 @@ pick_subref_at (tree var_ref, unsigned offset, int * ignored_bits)
}
else
remaining_offset -= field_position;
+
+ if (field_width == min_size)
+ break;
}
else
break;
@@ -3057,7 +3077,7 @@ pick_subref_at (tree var_ref, unsigned offset, int * ignored_bits)
static tree
find_mem_ref_replacement (exec_context & context, tree data_ref,
- unsigned offset)
+ unsigned offset, unsigned min_size)
{
tree ptr = TREE_OPERAND (data_ref, 0);
data_value ptr_val = context.evaluate (ptr);
@@ -3076,42 +3096,76 @@ find_mem_ref_replacement (exec_context & context, tree data_ref,
if (var_type == access_type)
return var_ref;
else
- {
- tree access_offset = TREE_OPERAND (data_ref, 1);
- gcc_assert (TREE_CONSTANT (access_offset));
- gcc_assert (tree_fits_shwi_p (access_offset));
- HOST_WIDE_INT shwi_offset = tree_to_shwi (access_offset);
- gcc_assert (offset < UINT_MAX - shwi_offset);
- HOST_WIDE_INT remaining_offset = shwi_offset * CHAR_BIT
- + offset + ptr_address->offset;
-
- return pick_subref_at (var_ref, remaining_offset, nullptr);
- }
+ {
+ tree access_offset = TREE_OPERAND (data_ref, 1);
+ gcc_assert (TREE_CONSTANT (access_offset));
+ gcc_assert (tree_fits_shwi_p (access_offset));
+ HOST_WIDE_INT shwi_offset = tree_to_shwi (access_offset);
+ gcc_assert (offset < UINT_MAX - shwi_offset);
+ HOST_WIDE_INT remaining_offset = shwi_offset * CHAR_BIT
+ + offset + ptr_address->offset;
+
+ return pick_subref_at (var_ref, remaining_offset, nullptr, min_size);
+ }
}
tree
-context_printer::print_first_data_ref_part (exec_context & context, tree data_ref, unsigned offset, int * ignored_bits)
-{
+context_printer::print_first_data_ref_part (exec_context & context,
+ tree data_ref, unsigned offset,
+ int * ignored_bits,
+ enum value_type val_type)
+{
+ unsigned min_size;
+ if (val_type == VAL_ADDRESS)
+ min_size = HOST_BITS_PER_PTR;
+ else
+ min_size = CHAR_BIT;
+
+ tree default_ref = NULL_TREE;
switch (TREE_CODE (data_ref))
{
case MEM_REF:
{
tree mem_replacement = find_mem_ref_replacement (context, data_ref,
- offset);
+ offset, min_size);
if (mem_replacement != NULL_TREE)
- return print_first_data_ref_part (context, mem_replacement, 0, ignored_bits);
+ return print_first_data_ref_part (context, mem_replacement, 0, ignored_bits,
+ val_type);
+
+ unsigned orig_type_size;
+ if (!get_constant_type_size (TREE_TYPE (data_ref), orig_type_size))
+ gcc_unreachable ();
+ else if (min_size < orig_type_size)
+ {
+ tree elt_type;
+ if (val_type == VAL_ADDRESS)
+ elt_type = ptr_type_node;
+ else
+ elt_type = char_type_node;
+
+ gcc_assert (offset % CHAR_BIT == 0);
+ tree ptr_type = build_pointer_type (elt_type);
+ default_ref = build2 (MEM_REF, elt_type,
+ TREE_OPERAND (data_ref, 0),
+ build_int_cst (ptr_type, offset / CHAR_BIT));
+ }
+ else
+ gcc_assert (min_size == orig_type_size);
}
/* Fall through. */
default:
- tree ref = pick_subref_at (data_ref, offset, ignored_bits);
+ tree ref = pick_subref_at (data_ref, offset, ignored_bits, min_size);
if (ref == NULL_TREE)
{
- gcc_assert (ignored_bits != nullptr
- && *ignored_bits > 0);
- return NULL_TREE;
+ if (ignored_bits != nullptr && *ignored_bits > 0)
+ return NULL_TREE;
+
+ ref = default_ref;
+ if (ref == NULL_TREE)
+ ref = data_ref;
}
pp_indent (&pp);
@@ -3139,10 +3193,10 @@ context_printer::print_value_update (exec_context & context, tree lhs, const dat
unsigned width = get_constant_type_size (TREE_TYPE (lhs));
while (previously_done < width)
{
+ enum value_type val_type = value.classify (previously_done, 1);
int ignored_bits = 0;
- tree type_done = print_first_data_ref_part (context, lhs,
- previously_done,
- &ignored_bits);
+ tree type_done = print_first_data_ref_part (context, lhs, previously_done,
+ &ignored_bits, val_type);
if (type_done == NULL_TREE)
{
gcc_assert (ignored_bits > 0);
@@ -3221,7 +3275,7 @@ data_value::data_value (const data_value & other)
constant_mask (other.constant_mask),
address_mask (other.address_mask),
constant_value (other.constant_value),
- addresses (other.addresses)
+ addresses (other.addresses.copy ())
{}
@@ -4442,10 +4496,17 @@ exec_context::execute_call (gcall *g)
data_storage & storage1 = addr1.storage.get ();
data_value src = storage1.get_value ();
wide_int wi_len2 = len2.get_cst ();
+ gcc_assert (wi::fits_shwi_p (wi_len2));
+ HOST_WIDE_INT hwi_len2 = wi_len2.to_shwi ();
+ tree array_len2 = build_array_type_nelts (char_type_node, hwi_len2);
+ tree data_target = build2 (MEM_REF, array_len2, arg0,
+ build_zero_cst (ptr_type_node));
wi_len2 *= CHAR_BIT;
gcc_assert (wi::fits_uhwi_p (wi_len2));
- dest_val.set_at (0, wi_len2.to_uhwi (),
- src, addr1.offset);
+ unsigned HOST_WIDE_INT uhwi_len2 = wi_len2.to_uhwi ();
+ data_value data_src = src.get_at (addr1.offset, uhwi_len2);
+ printer.print_value_update (*this, data_target, data_src);
+ dest_val.set_at (0, uhwi_len2, src, addr1.offset);
storage0.set (dest_val);
}
else if (gimple_call_builtin_p (g, BUILT_IN_MEMSET))
@@ -6078,7 +6139,8 @@ context_printer_print_first_data_ref_part_tests ()
pretty_printer & pp1 = printer1.pp;
exec_context ctx1 = context_builder ().build (mem1, printer1);
- tree res1 = printer1.print_first_data_ref_part (ctx1, var2i, 0, nullptr);
+ tree res1 = printer1.print_first_data_ref_part (ctx1, var2i, 0, nullptr,
+ VAL_UNDEFINED);
ASSERT_EQ (res1, integer_type_node);
const char * str1 = pp_formatted_text (&pp1);
@@ -6099,7 +6161,8 @@ context_printer_print_first_data_ref_part_tests ()
build1 (ADDR_EXPR, ptr_type_node, var2i),
build_zero_cst (ptr_type_node));
- tree res2 = printer2.print_first_data_ref_part (ctx2, mem_var2i, 0, nullptr);
+ tree res2 = printer2.print_first_data_ref_part (ctx2, mem_var2i, 0, nullptr,
+ VAL_UNDEFINED);
ASSERT_EQ (res2, integer_type_node);
const char * str2 = pp_formatted_text (&pp2);
@@ -6117,7 +6180,8 @@ context_printer_print_first_data_ref_part_tests ()
build1 (ADDR_EXPR, ptr_type_node, var2i),
build_zero_cst (ptr_type_node));
- tree res3 = printer3.print_first_data_ref_part (ctx3, long_var2i, 0, nullptr);
+ tree res3 = printer3.print_first_data_ref_part (ctx3, long_var2i, 0, nullptr,
+ VAL_UNDEFINED);
ASSERT_EQ (res3, integer_type_node);
const char * str3 = pp_formatted_text (&pp3);
@@ -6167,7 +6231,8 @@ context_printer_print_first_data_ref_part_tests ()
build1 (ADDR_EXPR, ptr_type_node, var1d1i),
build_zero_cst (ptr_type_node));
- tree res4 = printer4.print_first_data_ref_part (ctx4, mem_var1d1i, 0, nullptr);
+ tree res4 = printer4.print_first_data_ref_part (ctx4, mem_var1d1i, 0, nullptr,
+ VAL_UNDEFINED);
ASSERT_EQ (res4, short_integer_type_node);
const char * str4 = pp_formatted_text (&pp4);
@@ -6186,7 +6251,8 @@ context_printer_print_first_data_ref_part_tests ()
build_int_cst (ptr_type_node,
sizeof (short)));
- tree res5 = printer5.print_first_data_ref_part (ctx5, mem_var1d1i_s2, 0, nullptr);
+ tree res5 = printer5.print_first_data_ref_part (ctx5, mem_var1d1i_s2, 0, nullptr,
+ VAL_UNDEFINED);
ASSERT_EQ (res5, short_integer_type_node);
const char * str5 = pp_formatted_text (&pp5);
@@ -6233,7 +6299,8 @@ context_printer_print_first_data_ref_part_tests ()
build1 (ADDR_EXPR, ptr_type_node, var4c),
build_int_cst (ptr_type_node, 2));
- tree res6 = printer6.print_first_data_ref_part (ctx6, mem_var4c, 0, nullptr);
+ tree res6 = printer6.print_first_data_ref_part (ctx6, mem_var4c, 0, nullptr,
+ VAL_UNDEFINED);
ASSERT_EQ (res6, char_type_node);
const char * str6 = pp_formatted_text (&pp6);
@@ -6271,7 +6338,8 @@ context_printer_print_first_data_ref_part_tests ()
build_int_cst (ptr_type_node,
sizeof (int) + 1));
- tree res7 = printer7.print_first_data_ref_part (ctx7, mem_var1i1d, 0, nullptr);
+ tree res7 = printer7.print_first_data_ref_part (ctx7, mem_var1i1d, 0, nullptr,
+ VAL_UNDEFINED);
ASSERT_EQ (res7, char_type_node);
const char * str7 = pp_formatted_text (&pp7);
@@ -6297,7 +6365,8 @@ context_printer_print_first_data_ref_part_tests ()
build_int_cst (ptr_type_node,
3 * sizeof (int)));
- tree res8 = printer8.print_first_data_ref_part (ctx8, mem_var_i5, 0, nullptr);
+ tree res8 = printer8.print_first_data_ref_part (ctx8, mem_var_i5, 0, nullptr,
+ VAL_UNDEFINED);
ASSERT_EQ (res8, integer_type_node);
const char * str8 = pp_formatted_text (&pp8);
@@ -6317,7 +6386,8 @@ context_printer_print_first_data_ref_part_tests ()
sizeof (int)));
tree res9 = printer9.print_first_data_ref_part (ctx9, mem2_var_i5,
- HOST_BITS_PER_INT, nullptr);
+ HOST_BITS_PER_INT, nullptr,
+ VAL_UNDEFINED);
ASSERT_EQ (res9, integer_type_node);
const char * str9 = pp_formatted_text (&pp9);
@@ -6357,7 +6427,8 @@ context_printer_print_first_data_ref_part_tests ()
build_int_cst (ptr_type_node,
sizeof (int) + 13));
- tree res10 = printer10.print_first_data_ref_part (ctx10, mem_var_d1i1a5d, 0, nullptr);
+ tree res10 = printer10.print_first_data_ref_part (ctx10, mem_var_d1i1a5d, 0,
+ nullptr, VAL_UNDEFINED);
ASSERT_EQ (res10, char_type_node);
const char * str10 = pp_formatted_text (&pp10);
@@ -6390,7 +6461,8 @@ context_printer_print_first_data_ref_part_tests ()
tree ref_ptr = build2 (MEM_REF, integer_type_node, ptr,
build_zero_cst (ptr_type_node));
- tree res11 = printer11.print_first_data_ref_part (ctx11, ref_ptr, 0, nullptr);
+ tree res11 = printer11.print_first_data_ref_part (ctx11, ref_ptr, 0, nullptr,
+ VAL_UNDEFINED);
ASSERT_EQ (res11, integer_type_node);
const char * str11 = pp_formatted_text (&pp11);
@@ -6678,6 +6750,53 @@ context_printer_print_value_update_tests ()
printer8.print_value_update (ctx8, ref8, val8_17);
const char *str8 = pp_formatted_text (&pp8);
ASSERT_STREQ (str8, "# v5c[1] = 17\n");
+
+
+ heap_memory mem9;
+ context_printer printer9;
+ pretty_printer & pp9 = printer9.pp;
+ pp_buffer (&pp9)->m_flush_p = false;
+
+ tree a17c_9 = build_array_type_nelts (char_type_node, 17);
+ tree v17c_9 = create_var (a17c_9, "v17c");
+ tree p_9 = create_var (ptr_type_node, "p");
+ tree i_9 = create_var (integer_type_node, "i");
+
+ vec<tree> decls9{};
+ decls9.safe_push (v17c_9);
+ decls9.safe_push (p_9);
+ decls9.safe_push (i_9);
+
+ context_builder builder9;
+ builder9.add_decls (&decls9);
+ exec_context ctx9 = builder9.build (mem9, printer9);
+
+ data_storage *strg9_i = ctx9.find_reachable_var (i_9);
+ gcc_assert (strg9_i != nullptr);
+ storage_address addr9_i (strg9_i->get_ref (), 0);
+
+ data_value val9_addr_i (ptr_type_node);
+ val9_addr_i.set_address (addr9_i);
+
+ data_storage *strg9_v17c = ctx9.find_reachable_var (v17c_9);
+ gcc_assert (strg9_v17c != nullptr);
+ storage_address addr9_v17c (strg9_v17c->get_ref (), HOST_BITS_PER_PTR);
+
+ data_value val9_addr_v17c (ptr_type_node);
+ val9_addr_v17c.set_address (addr9_v17c);
+
+ data_storage *strg9_p = ctx9.find_reachable_var (p_9);
+ gcc_assert (strg9_p != nullptr);
+ strg9_p->set (val9_addr_v17c);
+
+ tree a8c = build_array_type_nelts (char_type_node,
+ HOST_BITS_PER_PTR / CHAR_BIT);
+ tree ref9 = build2 (MEM_REF, a8c, p_9,
+ build_zero_cst (build_pointer_type (ptr_type_node)));
+
+ printer9.print_value_update (ctx9, ref9, val9_addr_i);
+ const char *str9 = pp_formatted_text (&pp9);
+ ASSERT_STREQ (str9, "# v17c[8B:+8B] = &i\n");
}
@@ -8488,6 +8607,66 @@ exec_context_execute_assign_tests ()
ASSERT_EQ (wi10.to_shwi (), 23);
}
+void
+exec_context_print_call_tests ()
+{
+ heap_memory mem1;
+ context_printer printer1;
+ pretty_printer & pp1 = printer1.pp;
+ pp_buffer (&pp1)->m_flush_p = false;
+
+ tree ac5_1 = build_array_type_nelts (char_type_node, 5);
+ tree v5c_1 = create_var (ac5_1, "v5c");
+ tree si_1 = create_var (short_integer_type_node, "s1");
+ tree p_1 = create_var (ptr_type_node, "p");
+
+ vec<tree> decls1{};
+ decls1.safe_push (v5c_1);
+ decls1.safe_push (si_1);
+ decls1.safe_push (p_1);
+
+ context_builder builder1;
+ builder1.add_decls (&decls1);
+ exec_context ctx1 = builder1.build (mem1, printer1);
+
+ wide_int wi3113_1 = wi::shwi (13 * 256 + 31, TYPE_PRECISION (short_integer_type_node));
+
+ data_value val3113_1 (short_integer_type_node);
+ val3113_1.set_cst (wi3113_1);
+
+ data_storage *strg1_si = ctx1.find_reachable_var (si_1);
+ gcc_assert (strg1_si != nullptr);
+ strg1_si->set (val3113_1);
+
+ data_storage *strg1_v5c = ctx1.find_reachable_var (v5c_1);
+ gcc_assert (strg1_v5c != nullptr);
+ storage_address addr1_v5cp1 (strg1_v5c->get_ref (), CHAR_BIT);
+
+ data_value val_v5cp1_1 (ptr_type_node);
+ val_v5cp1_1.set_address (addr1_v5cp1);
+
+ data_storage *strg1_p = ctx1.find_reachable_var (p_1);
+ gcc_assert (strg1_p != nullptr);
+ strg1_p->set (val_v5cp1_1);
+
+ tree addr_si_1 = build1 (ADDR_EXPR, ptr_type_node, si_1);
+
+ tree memcpy_fn = builtin_decl_explicit (BUILT_IN_MEMCPY);
+ set_decl_built_in_function (memcpy_fn, BUILT_IN_NORMAL, BUILT_IN_MEMCPY);
+ gcall * memcpy_call1 = gimple_build_call (memcpy_fn, 3, p_1, addr_si_1,
+ build_int_cst (size_type_node, 2));
+
+ ctx1.execute (memcpy_call1);
+
+ const char *str1 = pp_formatted_text (&pp1);
+ ASSERT_STR_STARTSWITH (str1, "__builtin_memcpy (");
+ const char *line_end = ");\n";
+ ASSERT_STR_CONTAINS (str1, line_end);
+ const char *sub1 = strstr (str1, line_end);
+ ASSERT_NE (sub1, nullptr);
+ ASSERT_STREQ (sub1 + strlen (line_end), " # v5c[1] = 31\n # v5c[2] = 13\n");
+}
+
void
exec_context_execute_call_tests ()
{
@@ -9006,6 +9185,7 @@ gimple_exec_cc_tests ()
exec_context_evaluate_binary_tests ();
exec_context_evaluate_condition_tests ();
exec_context_execute_assign_tests ();
+ exec_context_print_call_tests ();
exec_context_execute_call_tests ();
exec_context_allocate_tests ();
}
More information about the Gcc-cvs
mailing list