From 752518cccec50d463f9298eeb80b519822ffd7ab Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Tue, 14 Apr 2020 17:56:27 -0400 Subject: [PATCH 035/179] FIXME: start introducing region_offset --- gcc/analyzer/region-model2.cc | 159 +++++++++++++++++++++++++++++++++- gcc/analyzer/region-model2.h | 41 ++++++++- 2 files changed, 192 insertions(+), 8 deletions(-) diff --git a/gcc/analyzer/region-model2.cc b/gcc/analyzer/region-model2.cc index b4de5a23bdd..edd3ee418a0 100644 --- a/gcc/analyzer/region-model2.cc +++ b/gcc/analyzer/region-model2.cc @@ -694,6 +694,13 @@ region2::kind_to_str (enum kind kind) } } +/* class region2. */ + +region2::~region2 () +{ + delete m_cached_offset; +} + /* FIXME. */ int @@ -702,8 +709,6 @@ region2::cmp_ids (const region2 *reg1, const region2 *reg2) return (long)reg1->get_id () - (long)reg2->get_id (); } -/* class region2. */ - /* Equality operator for region2. After comparing base class fields and kind, the rest of the comparison is handled off to a "compare_fields" member function @@ -838,7 +843,6 @@ region2::get_base_region () const { switch (iter->get_kind ()) { - //case RK_element_region: case RK_FIELD: case RK_ELEMENT: iter = iter->get_parent_region (); @@ -850,6 +854,85 @@ region2::get_base_region () const return iter; } +region_offset +region2::get_offset () +{ + if(!m_cached_offset) + m_cached_offset = new region_offset (calc_offset ()); + return *m_cached_offset; +} + +/* FIXME. */ + +region_offset +region2::calc_offset () const +{ + const region2 *iter_region = this; + region_offset::byte_offset_t byte_offset = 0; + + while (iter_region) + { + switch (iter_region->get_kind ()) + { + case RK_FIELD: + { + const field_region2 *field_region + = (const field_region2 *)iter_region; + iter_region = iter_region->get_parent_region (); + gcc_unreachable (); + //offset += ; + } + continue; + + case RK_ELEMENT: + { + const element_region2 *element_region + = (const element_region2 *)iter_region; + iter_region = iter_region->get_parent_region (); + + if (tree idx_cst + = element_region->get_index ()->maybe_get_constant ()) + { + gcc_assert (TREE_CODE (idx_cst) == INTEGER_CST); + + tree elem_type = element_region->get_type (); + + // FIXME: +#if 0 + /* Arithmetic on void-pointers is a GNU C extension, treating + the size of a void as 1. + https://gcc.gnu.org/onlinedocs/gcc/Pointer-Arith.html */ + if (TREE_CODE (elem_type) == VOID_TYPE) + return offset_sid; +#endif + + HOST_WIDE_INT hwi_idx_cst = tree_to_shwi (idx_cst); + + /* First, use int_size_in_bytes, to reject the case where we + have an incomplete type, or a non-constant value. */ + HOST_WIDE_INT hwi_byte_size = int_size_in_bytes (elem_type); + if (hwi_byte_size > 0) + { + HOST_WIDE_INT hwi_element_byte_offset + = hwi_idx_cst * hwi_byte_size; + byte_offset += hwi_element_byte_offset; + } + else + gcc_unreachable (); + } + else + { + gcc_unreachable (); + } + //offset += ; + } + continue; + + default: + return region_offset (iter_region, byte_offset); + } + } +} /* Set this region2's value to RHS_SVAL (or potentially a variant of it, for some kinds of casts). */ @@ -1337,7 +1420,7 @@ region2::get_view (tree type, region_model2 *model) const /* region2's ctor. */ region2::region2 (unsigned id, region2 *parent, tree type) -: m_id (id), m_parent (parent), m_type (type) +: m_id (id), m_parent (parent), m_type (type), m_cached_offset (NULL) { gcc_assert (type == NULL_TREE || TYPE_P (type)); } @@ -2897,6 +2980,35 @@ binding_cluster::get_binding (region_model2_manager *mgr, region2 *reg) const return NULL; } +/* Populate OUT with all bindings within this cluster that overlap REG. */ + +void +binding_cluster::get_overlapping_bindings (region2 *reg, + auto_vec *out) +{ + /* Get the size of REG. */ + // TODO + + for (map_t::iterator iter = m_map.begin (); + iter != m_map.end (); ++iter) + { + const binding_key *key = (*iter).first; + // TODO + } +} + +/* FIXME. */ + +void +binding_cluster::remove_overlapping_bindings (region_model2_manager *mgr, + region2 *reg) +{ + auto_vec bindings; + get_overlapping_bindings (reg, &bindings); + // TODO + //gcc_unreachable (); +} + /* class region_model2_manager. */ region_model2_manager::region_model2_manager () @@ -5011,6 +5123,8 @@ region_model2::set_value (region_model2_manager *mgr, gcc_assert (rhs_sval); #if 1 + remove_overlapping_bindings (mgr, lhs_reg); + const region2 *base_reg = lhs_reg->get_base_region (); binding_cluster *cluster = NULL; binding_cluster **slot = m_cluster_map.get (base_reg); @@ -5028,6 +5142,23 @@ region_model2::set_value (region_model2_manager *mgr, #endif } +/* FIXME. */ + +void +region_model2::remove_overlapping_bindings (region_model2_manager *mgr, + region2 *reg) +{ + const region2 *base_reg = reg->get_base_region (); + if (reg == base_reg) + { + /* Remove whole cluster (if any). */ + m_cluster_map.remove (base_reg); + return; + } + if (binding_cluster **cluster_slot = m_cluster_map.get (base_reg)) + (*cluster_slot)->remove_overlapping_bindings (mgr, reg); +} + /* Set the value of the region2 given by LHS to the value given by RHS. */ @@ -8195,6 +8326,26 @@ test_array () ASSERT_EQ (model.get_rvalue (&mgr, arr_1, NULL), model.get_rvalue (&mgr, int_m3, NULL)); + /* Verify get_offset for "arr[0]". */ + { + region2 *arr_0_reg = model.get_lvalue (&mgr, arr_0, NULL); + region_offset offset = arr_0_reg->get_offset (); + ASSERT_EQ (offset.get_base_region (), model.get_lvalue (&mgr, arr, NULL)); + ASSERT_EQ (offset.get_byte_offset (), 0); + } + + /* Verify get_offset for "arr[1]". */ + { + region2 *arr_1_reg = model.get_lvalue (&mgr, arr_1, NULL); + region_offset offset = arr_1_reg->get_offset (); + ASSERT_EQ (offset.get_base_region (), model.get_lvalue (&mgr, arr, NULL)); + ASSERT_EQ (offset.get_byte_offset (), 4); + // FIXME: this assumes sizeof(int) == 4 on the target + } + + // etc + + #if 0 /* "arr[i] = i;" - this should remove the earlier bindings. */ model.set_value (&mgr, arr_i, i, NULL); diff --git a/gcc/analyzer/region-model2.h b/gcc/analyzer/region-model2.h index 66db7d71aa7..b55b6e4183c 100644 --- a/gcc/analyzer/region-model2.h +++ b/gcc/analyzer/region-model2.h @@ -489,6 +489,27 @@ public: setjmp_record m_setjmp_record; }; +/* The location of a region expressesd as an offset relative to a + base region. */ + +class region_offset +{ +public: + typedef int byte_offset_t; // FIXME + + region_offset (const region2 *base_region, byte_offset_t offset) + : m_base_region (base_region), m_offset (offset) + {} + + const region2 *get_base_region () const { return m_base_region; } + byte_offset_t get_byte_offset () const { return m_offset; } + +private: + const region2 *m_base_region; + byte_offset_t m_offset; + // FIXME: also need a "symbolic" value +}; + /* Region and its subclasses. The class hierarchy looks like this (using indentation to show @@ -510,8 +531,8 @@ public: root_region (RK_ROOT) label_region (RK_FUNCTION) symbolic_region (RK_SYMBOLIC) - field_region (RK_FIELD) - element_region (RK_ELEMENT). */ + field_region2 (RK_FIELD) + element_region2 (RK_ELEMENT). */ /* Abstract base class representing a chunk of memory. @@ -547,7 +568,7 @@ public: }; static const char *kind_to_str (enum kind); - virtual ~region2 () {} + virtual ~region2 (); bool operator== (const region2 &other) const; bool operator!= (const region2 &other) const { return !(*this == other); } @@ -617,6 +638,8 @@ public: static int cmp_ptrs (const void *, const void *); + region_offset get_offset (); + protected: region2 (unsigned id, region2 *parent, tree type); @@ -632,10 +655,13 @@ public: void deactivate_any_active_view (region_model2 &model); void deactivate_view (region_model2 &model, region_id this_view_rid); #endif + region_offset calc_offset () const; unsigned m_id; // purely for deterministic sorting at this stage, for dumps region2 *m_parent; tree m_type; + + region_offset *m_cached_offset; }; } // namespace ana @@ -1359,7 +1385,12 @@ public: svalue2 *get_binding (region_model2_manager *mgr, region2 *reg) const; + void remove_overlapping_bindings (region_model2_manager *mgr, region2 *reg); + private: + void get_overlapping_bindings (region2 *reg, + auto_vec *out); + map_t m_map; }; @@ -1631,6 +1662,8 @@ class region_model2 region_model2_context *ctxt); svalue2 *get_store_value (region_model2_manager *mgr, region2 *reg); + void remove_overlapping_bindings (region_model2_manager *mgr, region2 *reg); + #if 0 void copy_struct_region2 (region2_id dst_rid, struct_region2 *dst_reg, struct_region2 *src_reg, region_model2_context *ctxt); @@ -1654,7 +1687,7 @@ class region_model2 tree rhs, const gcall *call, region_model2_context *ctxt); -#endif +#endif void update_for_call_superedge (region_model2_manager *mgr, const call_superedge &call_edge, region_model2_context *ctxt); -- 2.21.0