https://gcc.gnu.org/g:f08f78bfbc9244f6274bd6811761d2fc9b52b192

commit f08f78bfbc9244f6274bd6811761d2fc9b52b192
Author: Mikael Morin <mik...@gcc.gnu.org>
Date:   Wed Mar 5 10:55:56 2025 +0100

    Prise en charge POINTER_PLUS_EXPR

Diff:
---
 gcc/cgraphunit.cc | 165 ++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 153 insertions(+), 12 deletions(-)

diff --git a/gcc/cgraphunit.cc b/gcc/cgraphunit.cc
index c5907e55055e..b556626adab5 100644
--- a/gcc/cgraphunit.cc
+++ b/gcc/cgraphunit.cc
@@ -3114,9 +3114,6 @@ data_value::set_address_at (storage_address & address, 
unsigned offset)
   wide_int mask = wi::shifted_mask (offset, HOST_BITS_PER_PTR, false,
                                    bit_width);
   enum value_type type = classify (offset, HOST_BITS_PER_PTR);
-  /* Assume we don't store both regular integers and address
-     in the same variable over time.  */
-  gcc_assert (type == VAL_ADDRESS || type == VAL_UNDEFINED);
 
   if (type == VAL_ADDRESS)
     {
@@ -3841,20 +3838,57 @@ exec_context::evaluate_binary (enum tree_code code, 
tree type, tree lhs, tree rh
              || (TREE_CODE (rhs) == INTEGER_CST
                  && TREE_CODE (TREE_TYPE (lhs)) == INTEGER_TYPE
                  && TYPE_PRECISION (TREE_TYPE (lhs)) == TYPE_PRECISION 
(TREE_TYPE (rhs))
-                 && TYPE_UNSIGNED (TREE_TYPE (lhs)) == TYPE_UNSIGNED 
(TREE_TYPE (rhs))));
+                 && TYPE_UNSIGNED (TREE_TYPE (lhs)) == TYPE_UNSIGNED 
(TREE_TYPE (rhs)))
+             || code == POINTER_PLUS_EXPR);
   switch (code)
     {
     default:
       {
        gcc_assert (TREE_CODE (type) == INTEGER_TYPE
-                   || TREE_CODE (type) == BOOLEAN_TYPE);
-       tree lval = evaluate (lhs).to_tree (TREE_TYPE (lhs));
-       tree rval = evaluate (rhs).to_tree (TREE_TYPE (rhs));
-       tree t = fold_binary (code, type, lval, rval);
-       gcc_assert (t != NULL_TREE);
-       data_value result (type);
-       result.set_cst (wi::to_wide (t));
-       return result;
+                   || TREE_CODE (type) == BOOLEAN_TYPE
+                   || TREE_CODE (type) == POINTER_TYPE);
+       data_value val_lhs = evaluate (lhs);
+       data_value val_rhs = evaluate (rhs);
+       enum value_type lhs_type = val_lhs.classify ();
+       enum value_type rhs_type = val_rhs.classify ();
+       if (lhs_type == VAL_CONSTANT && rhs_type == VAL_CONSTANT)
+         {
+           tree lval = val_lhs.to_tree (TREE_TYPE (lhs));
+           tree rval = val_rhs.to_tree (TREE_TYPE (rhs));
+           tree t = fold_binary (code, type, lval, rval);
+           gcc_assert (t != NULL_TREE);
+           data_value result (type);
+           result.set_cst (wi::to_wide (t));
+           return result;
+         }
+       else
+         {
+           data_value *val_address = nullptr, *val_offset = nullptr;
+           if (lhs_type == VAL_ADDRESS && rhs_type == VAL_CONSTANT)
+             {
+               val_address = &val_lhs;
+               val_offset = &val_rhs;
+             }
+           else if (lhs_type == VAL_CONSTANT && rhs_type == VAL_ADDRESS)
+             {
+               val_address = &val_rhs;
+               val_offset = &val_lhs;
+             }
+           else
+             gcc_unreachable ();
+
+           storage_address *address = val_address->get_address ();
+           gcc_assert (address != nullptr);
+           wide_int offset = val_offset->get_cst ();
+           wide_int bit_offset = offset * CHAR_BIT;
+           wide_int total_offset = address->offset + bit_offset;
+           gcc_assert (wi::fits_uhwi_p (total_offset));
+           storage_address final_address (address->storage,
+                                          total_offset.to_uhwi ());
+           data_value result (type);
+           result.set_address (final_address);
+           return result;
+         }
       }
     }
 }
@@ -6219,6 +6253,113 @@ exec_context_evaluate_binary_tests ()
   wide_int wi_val2 = val2.get_cst ();
   ASSERT_PRED1 (wi::fits_uhwi_p, wi_val2);
   ASSERT_EQ (wi_val2.to_uhwi (), 1);
+
+
+  tree a12c = build_array_type_nelts (char_type_node, 12);
+  tree v12c = create_var (a12c, "v12c");
+  tree p = create_var (ptr_type_node, "p");
+  tree i = create_var (pointer_sized_int_node, "i");
+  tree o = create_var (pointer_sized_int_node, "o");
+
+  vec<tree> decls3{};
+  decls3.safe_push (v12c);
+  decls3.safe_push (p);
+  decls3.safe_push (i);
+  decls3.safe_push (o);
+
+  context_builder builder3 {};
+  builder3.add_decls (&decls3);
+  exec_context ctx3 = builder3.build (mem, printer);
+
+  data_storage *v12_storage = ctx3.find_reachable_var (v12c);
+  gcc_assert (v12_storage != nullptr);
+  storage_address v12_address (v12_storage->get_ref (), 0);
+
+  data_value pv12 (ptr_type_node);
+  pv12.set_address (v12_address);
+
+  data_storage *p_storage = ctx3.find_reachable_var (p);
+  gcc_assert (p_storage != nullptr);
+  p_storage->set (pv12);
+
+  data_storage *i_storage = ctx3.find_reachable_var (i);
+  gcc_assert (i_storage != nullptr);
+  i_storage->set (pv12);
+
+  tree addr_v12 = build1 (ADDR_EXPR, ptr_type_node, v12c);
+  tree cst3 = build_int_cst (size_type_node, 3);
+
+  data_value val_addr_p3 = ctx3.evaluate_binary (POINTER_PLUS_EXPR,
+                                                ptr_type_node,
+                                                addr_v12, cst3);
+
+  ASSERT_EQ (val_addr_p3.classify (), VAL_ADDRESS);
+  storage_address *addr_p3 = val_addr_p3.get_address ();
+  ASSERT_NE (addr_p3, nullptr);
+  ASSERT_EQ (&addr_p3->storage.get (), v12_storage);
+  ASSERT_EQ (addr_p3->offset, 24);
+
+  data_value val_ptr_p3 = ctx3.evaluate_binary (POINTER_PLUS_EXPR,
+                                               ptr_type_node,
+                                               p, cst3);
+
+  ASSERT_EQ (val_ptr_p3.classify (), VAL_ADDRESS);
+  storage_address *ptr_p3 = val_ptr_p3.get_address ();
+  ASSERT_EQ (&ptr_p3->storage.get (), v12_storage);
+  ASSERT_EQ (ptr_p3->offset, 24);
+
+  tree ip7 = build_int_cst (pointer_sized_int_node, 7);
+  data_value val_i_p7 = ctx3.evaluate_binary (PLUS_EXPR,
+                                             pointer_sized_int_node,
+                                             i, ip7);
+
+  ASSERT_EQ (val_i_p7.classify (), VAL_ADDRESS);
+  storage_address *i_p7 = val_i_p7.get_address ();
+  ASSERT_EQ (&i_p7->storage.get (), v12_storage);
+  ASSERT_EQ (i_p7->offset, 56);
+
+  storage_address addr_v12_p5 (v12_address.storage, 40);
+  data_value v12_p5 (ptr_type_node);
+  v12_p5.set_address (addr_v12_p5);
+
+  p_storage->set (v12_p5);
+  i_storage->set (v12_p5);
+
+  tree cst4 = build_int_cst (size_type_node, 4);
+  data_value val_ptr_p9 = ctx3.evaluate_binary (POINTER_PLUS_EXPR,
+                                               ptr_type_node,
+                                               p, cst4);
+
+  ASSERT_EQ (val_ptr_p9.classify (), VAL_ADDRESS);
+  storage_address *ptr_p9 = val_ptr_p9.get_address ();
+  ASSERT_EQ (&ptr_p9->storage.get (), v12_storage);
+  ASSERT_EQ (ptr_p9->offset, 72);
+
+  tree cst6 = build_int_cst (pointer_sized_int_node, 6);
+  data_value val_i_p11 = ctx3.evaluate_binary (PLUS_EXPR,
+                                              pointer_sized_int_node,
+                                              i, cst6);
+
+  ASSERT_EQ (val_i_p11.classify (), VAL_ADDRESS);
+  storage_address *i_p11 = val_i_p11.get_address ();
+  ASSERT_EQ (&i_p11->storage.get (), v12_storage);
+  ASSERT_EQ (i_p11->offset, 88);
+
+  wide_int wi1 = wi::shwi (1, HOST_BITS_PER_PTR);
+  data_value cst1 (pointer_sized_int_node);
+  cst1.set_cst (wi1);
+  data_storage *o_storage = ctx3.find_reachable_var (o);
+  gcc_assert (o_storage != nullptr);
+  o_storage->set (cst1);
+
+  data_value val_i_p6 = ctx3.evaluate_binary (PLUS_EXPR,
+                                             pointer_sized_int_node,
+                                             o, i);
+
+  ASSERT_EQ (val_i_p6.classify (), VAL_ADDRESS);
+  storage_address *i_p6 = val_i_p6.get_address ();
+  ASSERT_EQ (&i_p6->storage.get (), v12_storage);
+  ASSERT_EQ (i_p6->offset, 48);
 }

Reply via email to