From f0464a051683087c89d711cd9d03c1bbcf31ac43 Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Mon, 20 Apr 2020 16:13:23 -0400 Subject: [PATCH 060/179] FIXME: implement clobbering --- gcc/analyzer/region-model2.cc | 22 +++++++++-- gcc/analyzer/region-model2.h | 1 + gcc/analyzer/store2.cc | 72 ++++++++++++++++++++++++++++++----- gcc/analyzer/store2.h | 13 ++++++- 4 files changed, 94 insertions(+), 14 deletions(-) diff --git a/gcc/analyzer/region-model2.cc b/gcc/analyzer/region-model2.cc index d3b86bb4b28..cf1d2167245 100644 --- a/gcc/analyzer/region-model2.cc +++ b/gcc/analyzer/region-model2.cc @@ -3612,14 +3612,22 @@ region_model2::on_gassign (const supernode */*snode*/, // TODO } break; +#endif case CONSTRUCTOR: { - /* e.g. "x ={v} {CLOBBER};" */ - // TODO + if (TREE_CLOBBER_P (rhs1)) + { + /* e.g. "x ={v} {CLOBBER};" */ + /* TODO: should we remove the value, or replace it with an + "unknown" value? */ + clobber_region (lhs_reg); + } + else + gcc_unreachable (); // TODO } break; - +#if 0 case POINTER_PLUS_EXPR: { /* e.g. "_1 = a_10(D) + 12;" */ @@ -4984,6 +4992,14 @@ region_model2::set_value (tree lhs, tree rhs, region_model2_context *ctxt) set_value (lhs_reg, rhs_sval, ctxt); } +/* FIXME. */ + +void +region_model2::clobber_region (region2 *reg) +{ + m_store.clobber_region (m_mgr->get_store2_manager(), reg); +} + /* Determine what is known about the condition "LHS_SVAL OP RHS_SVAL" within this model. */ diff --git a/gcc/analyzer/region-model2.h b/gcc/analyzer/region-model2.h index 1dae5eca564..d00f207eb41 100644 --- a/gcc/analyzer/region-model2.h +++ b/gcc/analyzer/region-model2.h @@ -1672,6 +1672,7 @@ class region_model2 void set_value (region2 *lhs_reg, svalue2 *rhs_sval, region_model2_context *ctxt); void set_value (tree lhs, tree rhs, region_model2_context *ctxt); + void clobber_region (region2 *reg); svalue2 *set_to_new_unknown_value (region2 *dst_reg, tree type, region_model2_context *ctxt); void copy_region (region2 *dst_reg, region2 *src_reg, diff --git a/gcc/analyzer/store2.cc b/gcc/analyzer/store2.cc index 9aca20b586d..839f4259278 100644 --- a/gcc/analyzer/store2.cc +++ b/gcc/analyzer/store2.cc @@ -195,6 +195,16 @@ binding_cluster2::bind (store2_manager *mgr, m_map.put (binding, val); } +/* FIXME. + Return true if the cluster is now empty of bindings. */ + +bool +binding_cluster2::clobber_region (store2_manager *mgr, region2 *reg) +{ + remove_overlapping_bindings (mgr, reg); + return m_map.elements () == 0; +} + svalue2 * binding_cluster2::get_binding (store2_manager *mgr, region2 *reg, @@ -210,30 +220,53 @@ binding_cluster2::get_binding (store2_manager *mgr, /* Populate OUT with all bindings within this cluster that overlap REG. */ void -binding_cluster2::get_overlapping_bindings (region2 */*reg*/, - auto_vec */*out*/) +binding_cluster2::get_overlapping_bindings (store2_manager *mgr, + 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_key2 *binding + = binding_key2::make (mgr, reg, binding_key2::BK_direct); + if (const concrete_binding2 *ckey = binding->dyn_cast_concrete_binding2 ()) { - //const binding_key2 *key = (*iter).first; - // TODO + for (map_t::iterator iter = m_map.begin (); + iter != m_map.end (); ++iter) + { + const binding_key2 *iter_key = (*iter).first; + if (const concrete_binding2 *iter_ckey + = iter_key->dyn_cast_concrete_binding2 ()) + { + if (ckey->get_bit_offset () == iter_ckey->get_bit_offset ()) + out->safe_push (iter_key); + // TODO: also compare sizes? + } + else + { + gcc_unreachable (); + } + } + } + else + { + gcc_unreachable (); } } /* FIXME. */ void -binding_cluster2::remove_overlapping_bindings (store2_manager */*mgr*/, +binding_cluster2::remove_overlapping_bindings (store2_manager *mgr, region2 *reg) { auto_vec bindings; - get_overlapping_bindings (reg, &bindings); - // TODO - //gcc_unreachable (); + get_overlapping_bindings (mgr, reg, &bindings); + + unsigned i; + const binding_key2 *binding; + FOR_EACH_VEC_ELT (bindings, i, binding) + m_map.remove (binding); } /* class store2_manager. */ @@ -273,7 +306,9 @@ store2::store2 (const store2 &other) ++iter) { const region2 *reg = (*iter).first; + gcc_assert (reg); binding_cluster2 *c = (*iter).second; + gcc_assert (c); m_cluster_map.put (reg, new binding_cluster2 (*c)); } } @@ -382,6 +417,23 @@ store2::set_value (store2_manager *mgr, region2 *lhs_reg, svalue2 *rhs_sval) /* FIXME. */ +void +store2::clobber_region (store2_manager *mgr, region2 *reg) +{ + const region2 *base_reg = reg->get_base_region (); + binding_cluster2 **slot = m_cluster_map.get (base_reg); + if (!slot) + return; + binding_cluster2 *cluster = *slot; + if (cluster->clobber_region (mgr, reg)) + { + delete cluster; + m_cluster_map.remove (base_reg); + } +} + +/* FIXME. */ + void store2::remove_overlapping_bindings (store2_manager *mgr, region2 *reg) { diff --git a/gcc/analyzer/store2.h b/gcc/analyzer/store2.h index b7b086d149b..47f07397fdb 100644 --- a/gcc/analyzer/store2.h +++ b/gcc/analyzer/store2.h @@ -32,6 +32,8 @@ along with GCC; see the file COPYING3. If not see namespace ana { +class concrete_binding2; + /* A binding within a store. */ class binding_key2 @@ -58,6 +60,9 @@ public: static int cmp_ptrs (const void *, const void *); static int cmp (const binding_key2 *, const binding_key2 *); + virtual const concrete_binding2 *dyn_cast_concrete_binding2 () const + { return NULL; } + protected: binding_key2 (const region2 *region, enum kind kind) : m_region (region), m_kind (kind) {} @@ -108,6 +113,9 @@ public: pp_wide_int (pp, m_offset, SIGNED); } + const concrete_binding2 *dyn_cast_concrete_binding2 () const FINAL OVERRIDE + { return this; } + bit_offset_t get_bit_offset () const { return m_offset; } private: @@ -162,13 +170,15 @@ public: const region2 *, const svalue2 *) const; #endif + bool clobber_region (store2_manager *mgr, region2 *reg); + svalue2 *get_binding (store2_manager *mgr, region2 *reg, binding_key2::kind kind) const; void remove_overlapping_bindings (store2_manager *mgr, region2 *reg); private: - void get_overlapping_bindings (region2 *reg, + void get_overlapping_bindings (store2_manager *mgr, region2 *reg, auto_vec *out); typedef hash_map map_t; @@ -200,6 +210,7 @@ public: region2 *reg, binding_key2::kind kind); void set_value (store2_manager *mgr, region2 *lhs_reg, svalue2 *rhs_sval); + void clobber_region (store2_manager *mgr, region2 *reg); private: void remove_overlapping_bindings (store2_manager *mgr, region2 *reg); -- 2.21.0