https://gcc.gnu.org/g:607c0e0bb8dcff4d700d4181e0ac74738e4a7e24

commit 607c0e0bb8dcff4d700d4181e0ac74738e4a7e24
Author: Mikael Morin <mik...@gcc.gnu.org>
Date:   Fri Apr 18 15:15:42 2025 +0200

    gimple-exec: prise en charge addresses de composant de variable

Diff:
---
 gcc/cgraphunit.cc | 183 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 178 insertions(+), 5 deletions(-)

diff --git a/gcc/cgraphunit.cc b/gcc/cgraphunit.cc
index 6a4fb44af889..0475f277875a 100644
--- a/gcc/cgraphunit.cc
+++ b/gcc/cgraphunit.cc
@@ -213,6 +213,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "wide-int.h"
 #include "selftest.h"
 #include "tree-ssanames.h"
+#include "tree-dfa.h"
 
 /* Queue of cgraph nodes scheduled to be added into cgraph.  This is a
    secondary queue used during optimization to accommodate passes that
@@ -3903,10 +3904,37 @@ exec_context::evaluate (tree expr) const
          }
        else
          {
-           data_storage *strg = find_reachable_var (TREE_OPERAND (expr, 0));
-           gcc_assert (strg != nullptr);
-           storage_address address (strg->get_ref (), 0);
-           result.set_address (address);
+           poly_int64 offset;
+           tree var = get_addr_base_and_unit_offset (TREE_OPERAND (expr, 0),
+                                                     &offset);
+
+           HOST_WIDE_INT off;
+           bool is_constant = offset.is_constant (&off);
+           gcc_assert (is_constant && off >= 0);
+           unsigned off_bits = off * CHAR_BIT;
+
+           if (TREE_CODE (var) == VAR_DECL)
+             {
+               data_storage *strg = find_reachable_var (var);
+               gcc_assert (strg != nullptr);
+               storage_address address (strg->get_ref (), off_bits);
+               result.set_address (address);
+             }
+           else if (TREE_CODE (var) == INDIRECT_REF
+                    || TREE_CODE (var) == MEM_REF)
+             {
+               gcc_assert (TREE_CODE (var) == INDIRECT_REF
+                           || integer_zerop (TREE_OPERAND (var, 1)));
+               data_value root_val = evaluate (TREE_OPERAND (var, 0));
+               gcc_assert (root_val.classify () == VAL_ADDRESS);
+               storage_address *root_addr = root_val.get_address ();
+               gcc_assert (root_addr != nullptr);
+               gcc_assert (root_addr->offset == 0);
+               storage_address address (root_addr->storage, off_bits);
+               result.set_address (address);
+             }
+           else
+             gcc_unreachable ();
          }
        return result;
       }
@@ -4047,7 +4075,7 @@ data_value
 exec_context::evaluate_binary (enum tree_code code, tree type, tree lhs, tree 
rhs) const
 {
   gcc_assert (TREE_TYPE (lhs) == TREE_TYPE (rhs)
-             || (TREE_CODE (rhs) == INTEGER_CST
+             || (TREE_CODE (TREE_TYPE (rhs)) == INTEGER_TYPE
                  && 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)))
@@ -4065,6 +4093,11 @@ exec_context::evaluate_binary (enum tree_code code, tree 
type, tree lhs, tree rh
        enum value_type rhs_type = val_rhs.classify ();
        if (lhs_type == VAL_CONSTANT && rhs_type == VAL_CONSTANT)
          {
+           gcc_assert (TREE_TYPE (lhs) == TREE_TYPE (rhs)
+                       || (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))));
            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);
@@ -6801,6 +6834,146 @@ exec_context_evaluate_literal_tests ()
   ASSERT_PRED1 (wi::fits_shwi_p, wi_value);
   int int_value = wi_value.to_shwi ();
   ASSERT_EQ (int_value, 13);
+
+  heap_memory mem2;
+  context_printer printer2;
+
+  tree derived = make_node (RECORD_TYPE);
+  tree field2 = build_decl (input_location, FIELD_DECL,
+                           get_identifier ("field2"), integer_type_node);
+  DECL_CONTEXT (field2) = derived;
+  DECL_CHAIN (field2) = NULL_TREE;
+  tree field1 = build_decl (input_location, FIELD_DECL,
+                           get_identifier ("field1"), integer_type_node);
+  DECL_CONTEXT (field1) = derived;
+  DECL_CHAIN (field1) = field2;
+  TYPE_FIELDS (derived) = field1;
+  layout_type (derived);
+
+  tree d = create_var (derived, "d");
+
+  vec<tree> decls2{};
+  decls2.safe_push (d);
+
+  context_builder builder2 {};
+  builder2.add_decls (&decls2);
+  exec_context ctx2 = builder2.build (mem2, printer2);
+
+  tree comp = fold_build3_loc (input_location, COMPONENT_REF,
+                              integer_type_node, d, field2, NULL_TREE);
+  tree int_ptr = build_pointer_type (integer_type_node);
+  tree comp_addr = build1 (ADDR_EXPR, int_ptr, comp);
+
+  data_value val2 = ctx2.evaluate (comp_addr);
+  ASSERT_EQ (val2.classify (), VAL_ADDRESS);
+  storage_address *ptr_addr2 = val2.get_address ();
+  ASSERT_NE (ptr_addr2, nullptr);
+  data_storage &strg_ptr2 = ptr_addr2->storage.get ();
+  ASSERT_PRED1 (strg_ptr2.matches, d);
+  ASSERT_EQ (ptr_addr2->offset, HOST_BITS_PER_INT);
+
+  heap_memory mem3;
+  context_printer printer3;
+
+  tree derived3 = make_node (RECORD_TYPE);
+  tree d3_field2 = build_decl (input_location, FIELD_DECL,
+                              get_identifier ("field2"), integer_type_node);
+  DECL_CONTEXT (d3_field2) = derived3;
+  DECL_CHAIN (d3_field2) = NULL_TREE;
+  tree d3_field1 = build_decl (input_location, FIELD_DECL,
+                              get_identifier ("field1"), integer_type_node);
+  DECL_CONTEXT (d3_field1) = derived3;
+  DECL_CHAIN (d3_field1) = d3_field2;
+  TYPE_FIELDS (derived3) = d3_field1;
+  layout_type (derived3);
+
+  tree d3 = create_var (derived3, "d3");
+  tree ptr_d3 = build_pointer_type (derived3);
+  tree p3 = create_var (ptr_d3, "p3");
+
+  vec<tree> decls3{};
+  decls3.safe_push (d3);
+  decls3.safe_push (p3);
+
+  context_builder builder3 {};
+  builder3.add_decls (&decls3);
+  exec_context ctx3 = builder3.build (mem3, printer3);
+
+  data_storage *strg_d3 = ctx3.find_reachable_var (d3);
+  gcc_assert (strg_d3 != nullptr);
+  data_storage *strg_p3 = ctx3.find_reachable_var (p3);
+  gcc_assert (strg_p3 != nullptr);
+  storage_address addr_d3 (strg_d3->get_ref (), 0);
+  data_value val_p3 (ptr_d3);
+  val_p3.set_address (addr_d3);
+  strg_p3->set (val_p3);
+
+  tree deref_p3 = build_fold_indirect_ref_loc (input_location, p3);
+  tree comp3 = fold_build3_loc (input_location, COMPONENT_REF,
+                               integer_type_node, deref_p3, d3_field2,
+                               NULL_TREE);
+  tree int_ptr3 = build_pointer_type (integer_type_node);
+  tree comp_addr3 = build1 (ADDR_EXPR, int_ptr3, comp3);
+
+  data_value val3 = ctx3.evaluate (comp_addr3);
+  ASSERT_EQ (val3.classify (), VAL_ADDRESS);
+  storage_address *ptr_addr3 = val3.get_address ();
+  ASSERT_NE (ptr_addr3, nullptr);
+  data_storage &strg_ptr3 = ptr_addr3->storage.get ();
+  ASSERT_PRED1 (strg_ptr3.matches, d3);
+  ASSERT_EQ (ptr_addr3->offset, HOST_BITS_PER_INT);
+
+  heap_memory mem4;
+  context_printer printer4;
+
+  tree derived4 = make_node (RECORD_TYPE);
+  tree d4_field2 = build_decl (input_location, FIELD_DECL,
+                              get_identifier ("field2"), integer_type_node);
+  DECL_CONTEXT (d4_field2) = derived4;
+  DECL_CHAIN (d4_field2) = NULL_TREE;
+  tree d4_field1 = build_decl (input_location, FIELD_DECL,
+                              get_identifier ("field1"), integer_type_node);
+  DECL_CONTEXT (d4_field1) = derived4;
+  DECL_CHAIN (d4_field1) = d4_field2;
+  TYPE_FIELDS (derived4) = d4_field1;
+  layout_type (derived4);
+
+  tree d4 = create_var (derived4, "d4");
+  tree ptr_d4 = build_pointer_type (derived4);
+  tree p4 = create_var (ptr_d4, "p4");
+
+  vec<tree> decls4{};
+  decls4.safe_push (d4);
+  decls4.safe_push (p4);
+
+  context_builder builder4 {};
+  builder4.add_decls (&decls4);
+  exec_context ctx4 = builder4.build (mem4, printer4);
+
+  data_storage *strg_d4 = ctx4.find_reachable_var (d4);
+  gcc_assert (strg_d4 != nullptr);
+  data_storage *strg_p4 = ctx4.find_reachable_var (p4);
+  gcc_assert (strg_p4 != nullptr);
+  storage_address addr_d4 (strg_d4->get_ref (), 0);
+  data_value val_p4 (ptr_d4);
+  val_p4.set_address (addr_d4);
+  strg_p4->set (val_p4);
+
+  tree mem_p4 = fold_build2_loc (input_location, MEM_REF,
+                                derived4, p4, build_int_cst (ptr_d4, 0));
+  tree comp4 = fold_build3_loc (input_location, COMPONENT_REF,
+                               integer_type_node, mem_p4, d4_field2,
+                               NULL_TREE);
+  tree int_ptr4 = build_pointer_type (integer_type_node);
+  tree comp_addr4 = build1 (ADDR_EXPR, int_ptr4, comp4);
+
+  data_value val4 = ctx4.evaluate (comp_addr4);
+  ASSERT_EQ (val4.classify (), VAL_ADDRESS);
+  storage_address *ptr_addr4 = val4.get_address ();
+  ASSERT_NE (ptr_addr4, nullptr);
+  data_storage &strg_ptr4 = ptr_addr4->storage.get ();
+  ASSERT_PRED1 (strg_ptr4.matches, d4);
+  ASSERT_EQ (ptr_addr4->offset, HOST_BITS_PER_INT);
 }
 
 void

Reply via email to