aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/analyzer/analyzer.h1
-rw-r--r--gcc/analyzer/store.cc54
-rw-r--r--gcc/analyzer/store.h25
3 files changed, 74 insertions, 6 deletions
diff --git a/gcc/analyzer/analyzer.h b/gcc/analyzer/analyzer.h
index 525eb06..f06b68c 100644
--- a/gcc/analyzer/analyzer.h
+++ b/gcc/analyzer/analyzer.h
@@ -142,6 +142,7 @@ public:
typedef offset_int bit_offset_t;
typedef offset_int bit_size_t;
+typedef offset_int byte_offset_t;
typedef offset_int byte_size_t;
extern bool int_size_in_bits (const_tree type, bit_size_t *out);
diff --git a/gcc/analyzer/store.cc b/gcc/analyzer/store.cc
index 3203703..d5f8798 100644
--- a/gcc/analyzer/store.cc
+++ b/gcc/analyzer/store.cc
@@ -241,12 +241,18 @@ binding_key::cmp (const binding_key *k1, const binding_key *k2)
void
bit_range::dump_to_pp (pretty_printer *pp) const
{
- pp_string (pp, "start: ");
- pp_wide_int (pp, m_start_bit_offset, SIGNED);
- pp_string (pp, ", size: ");
- pp_wide_int (pp, m_size_in_bits, SIGNED);
- pp_string (pp, ", next: ");
- pp_wide_int (pp, get_next_bit_offset (), SIGNED);
+ byte_range bytes (0, 0);
+ if (as_byte_range (&bytes))
+ bytes.dump_to_pp (pp);
+ else
+ {
+ pp_string (pp, "start: ");
+ pp_wide_int (pp, m_start_bit_offset, SIGNED);
+ pp_string (pp, ", size: ");
+ pp_wide_int (pp, m_size_in_bits, SIGNED);
+ pp_string (pp, ", next: ");
+ pp_wide_int (pp, get_next_bit_offset (), SIGNED);
+ }
}
/* Dump this object to stderr. */
@@ -329,6 +335,42 @@ bit_range::from_mask (unsigned HOST_WIDE_INT mask, bit_range *out)
return true;
}
+/* Attempt to convert this bit_range to a byte_range.
+ Return true if it is possible, writing the result to *OUT.
+ Otherwise return false. */
+
+bool
+bit_range::as_byte_range (byte_range *out) const
+{
+ if (m_start_bit_offset % BITS_PER_UNIT == 0
+ && m_size_in_bits % BITS_PER_UNIT == 0)
+ {
+ out->m_start_byte_offset = m_start_bit_offset / BITS_PER_UNIT;
+ out->m_size_in_bytes = m_size_in_bits / BITS_PER_UNIT;
+ return true;
+ }
+ return false;
+}
+
+/* Dump this object to PP. */
+
+void
+byte_range::dump_to_pp (pretty_printer *pp) const
+{
+ if (m_size_in_bytes == 1)
+ {
+ pp_string (pp, "byte ");
+ pp_wide_int (pp, m_start_byte_offset, SIGNED);
+ }
+ else
+ {
+ pp_string (pp, "bytes ");
+ pp_wide_int (pp, m_start_byte_offset, SIGNED);
+ pp_string (pp, "-");
+ pp_wide_int (pp, get_last_byte_offset (), SIGNED);
+ }
+}
+
/* class concrete_binding : public binding_key. */
/* Implementation of binding_key::dump_to_pp vfunc for concrete_binding. */
diff --git a/gcc/analyzer/store.h b/gcc/analyzer/store.h
index ca9ff69..e0c60e1 100644
--- a/gcc/analyzer/store.h
+++ b/gcc/analyzer/store.h
@@ -196,6 +196,7 @@ private:
hash_set<const svalue *> m_mutable_at_unknown_call_svals;
};
+class byte_range;
class concrete_binding;
/* An enum for discriminating between "direct" vs "default" levels of
@@ -267,6 +268,8 @@ private:
enum binding_kind m_kind;
};
+/* A concrete range of bits. */
+
struct bit_range
{
bit_range (bit_offset_t start_bit_offset, bit_size_t size_in_bits)
@@ -308,10 +311,32 @@ struct bit_range
static bool from_mask (unsigned HOST_WIDE_INT mask, bit_range *out);
+ bool as_byte_range (byte_range *out) const;
+
bit_offset_t m_start_bit_offset;
bit_size_t m_size_in_bits;
};
+/* A concrete range of bytes. */
+
+struct byte_range
+{
+ byte_range (byte_offset_t start_byte_offset, byte_size_t size_in_bytes)
+ : m_start_byte_offset (start_byte_offset),
+ m_size_in_bytes (size_in_bytes)
+ {}
+
+ void dump_to_pp (pretty_printer *pp) const;
+
+ byte_offset_t get_last_byte_offset () const
+ {
+ return m_start_byte_offset + m_size_in_bytes - 1;
+ }
+
+ byte_offset_t m_start_byte_offset;
+ byte_size_t m_size_in_bytes;
+};
+
/* Concrete subclass of binding_key, for describing a concrete range of
bits within the binding_map (e.g. "bits 8-15"). */