1#ifndef ROSE_BitPattern_H
2#define ROSE_BitPattern_H
4#include <featureTests.h>
5#ifdef ROSE_ENABLE_BINARY_ANALYSIS
8#include <Rose/StringUtility.h>
57 typedef std::vector<T> Words;
58 typedef std::vector<Words> Alternatives;
60 Alternatives patterns_;
75 BitPattern(
size_t lo_bit,
size_t hi_bit, T pat,
size_t wordnum) {
76 bits(lo_bit, hi_bit, pat, wordnum);
81 for (
size_t i=0; i<patterns_.size(); ++i) {
82 if (patterns_[i].size()!=mask_.size()) {
83 std::cerr <<
"BitPattern::is_consistent failed\n"
84 <<
" mask_.size() = " <<mask_.size() <<
"\n"
85 <<
" patterns_[" <<i <<
"].size() = " <<patterns_[i].size() <<
"\n"
86 <<
" these two vectors should have been the same size\n";
87 std::cerr <<
" this = ";
99 for (
size_t i=0; i<mask_.size(); ++i)
115 assert(mask_.back()!=0);
121 if (wordnum >= mask_.size())
123 return mask_[wordnum];
132 if (msk==0 || wordnum>mask_.size() || patterns_.empty())
133 return std::pair<T, T>(0, 0);
134 T retmsk = msk & mask_[wordnum];
135 T retpat = retmsk & patterns_[0][wordnum];
136 for (
size_t i=1; i<patterns_.size() && retmsk!=0; ++i)
137 retmsk &= ~(retpat ^ patterns_[i][wordnum]);
138 return std::pair<T, T>(retpat & retmsk, retmsk);
143 return patterns_.size();
149 T
conflict(T msk, T pat,
size_t wordnum,
size_t altnum)
const {
150 if (wordnum < mask_.size()) {
151 if (T overlap = mask_[wordnum] & msk) {
152 assert(altnum < patterns_.size());
153 if (T differ = (patterns_[altnum][wordnum] & overlap) ^ (pat & overlap))
164 if (wordnum < mask_.size()) {
166 if (T differ =
conflict(msk, pat, wordnum, altnum))
176 if (0!=msk && wordnum<mask_.size()) {
177 if (T differ =
conflict(msk, pat, wordnum)) {
180 <<
", wordnum=" <<wordnum <<
") conflicts with existing pattern ";
183 assert(!
"new bit pattern conflicts with existing pattern");
194 for (
size_t wordnum=0; wordnum<
nwords(); ++wordnum) {
195 if (mask_[wordnum]!=other.mask_[wordnum])
200 bool are_same =
true;
201 for (
size_t wordnum=0; are_same && wordnum<
nwords(); ++wordnum)
202 are_same = patterns_[a1][wordnum] == other.patterns_[a2][wordnum];
204 if (alternatives!=NULL)
205 *alternatives = std::make_pair(a1, a2);
217 assert(0 == (pat & ~msk));
220 if (wordnum >= mask_.size())
221 mask_.resize(wordnum+1, T(0));
222 mask_[wordnum] |= msk;
223 if (patterns_.empty()) {
225 patterns_[0].resize(wordnum+1, T(0));
226 patterns_[0][wordnum] = pat;
229 if (wordnum >= patterns_[altnum].size())
230 patterns_[altnum].resize(wordnum+1, T(0));
231 patterns_[altnum][wordnum] |= pat;
243 T msk = IntegerOps::genMask<T>(lo_bit, hi_bit);
245 return insert(msk, value, wordnum);
251 if (0==nbits || patterns_.empty())
253 static const size_t word_size = 8*
sizeof(T);
254 size_t need_nbits =
width() + nbits;
255 size_t need_nwords = (need_nbits + word_size - 1) / word_size;
256 size_t word_delta = nbits / word_size;
257 size_t bit_delta_lt = nbits % word_size;
258 size_t bit_delta_rt = word_size - bit_delta_lt;
262 retval.mask_.resize(need_nwords, 0);
263 for (
size_t i=0; i<mask_.size(); ++i) {
265 if (i+word_delta+1<need_nwords)
270 retval.patterns_.resize(patterns_.size());
271 for (
size_t i=0; i<patterns_.size(); ++i) {
272 retval.patterns_[i].resize(need_nwords, 0);
273 for (
size_t j=0; j<patterns_[i].size(); ++j) {
275 if (j+word_delta+1<need_nwords)
292 for (
size_t altnum=0; altnum<other.
nalternatives(); ++altnum) {
293 for (
size_t wordnum=0; wordnum<other.
nwords(); ++wordnum)
294 check_insertion(other.mask_[wordnum], other.patterns_[altnum][wordnum], wordnum);
298 size_t this_nwords = mask_.size();
299 size_t result_nwords = std::max(this_nwords, other.mask_.size());
300 mask_.resize(result_nwords, T(0));
301 for (
size_t wordnum=0; wordnum<other.mask_.size(); ++wordnum)
302 mask_[wordnum] |= other.mask_[wordnum];
306 for (
size_t a1=0; a1<patterns_.size(); ++a1) {
307 for (
size_t a2=0; a2<other.patterns_.size(); ++a2) {
308 retval.push_back(Words(result_nwords, T(0)));
309 for (
size_t i=0; i<this_nwords; ++i)
310 retval.back()[i] = patterns_[a1][i];
311 for (
size_t i=0; i<other.
nwords(); ++i)
312 retval.back()[i] |= other.patterns_[a2][i];
315 for (
size_t a3=0; a3+1<retval.size(); ++a3) {
317 for (
size_t i=0; isdup && i<result_nwords; ++i)
318 isdup = retval[a3][i] == retval.back()[i];
343 for (
size_t wordnum=0; wordnum<
nwords(); ++wordnum)
344 assert(mask_[wordnum]==other.mask_[wordnum]);
348 for (
size_t a2=0; !isdup && a2<na; ++a2) {
350 for (
size_t wordnum=0; isdup && wordnum<
nwords(); ++wordnum)
351 isdup = patterns_[a2][wordnum] == other.patterns_[a1][wordnum];
354 patterns_.push_back(other.patterns_[a1]);
387 bool matches(
const std::vector<T> value_words)
const {
390 if (value_words.size() <
nwords())
394 for (
size_t wordnum=0; eq && wordnum<
nwords(); ++wordnum)
395 eq = (value_words[wordnum] & mask_[wordnum]) == (patterns_[altnum][wordnum] & mask_[wordnum]);
401 bool matches(
const T *value_words,
size_t sz)
const {
403 for (
size_t i=0; i<sz; ++i)
404 vv.push_back(value_words[i]);
414 if ((value & mask_[wordnum]) == (patterns_[altnum][wordnum] & mask_[wordnum]))
421 void print(std::ostream &o,
size_t altnum,
bool with_mask=
true)
const {
424 for (
size_t wordnum=0; wordnum<
nwords(); ++wordnum) {
439 o <<(0==altnum?
"":
" | ");
440 print(o, altnum,
false);
443 o <<
"/" <<(1==
nwords()?
"":
"{");
444 for (
size_t wordnum=0; wordnum<
nwords(); ++wordnum)
Describes a pattern of bits in a finite number of words.
void print(std::ostream &o) const
Print all alternatives of the pattern.
BitPattern(T msk, T pat, size_t wordnum)
Creates a new bit pattern for a single word using a mask and value.
size_t nwords() const
Returns the number of words in the pattern.
bool matches_word(T value, size_t wordnum) const
Returns true if one word of this pattern matches the specified value.
BitPattern & operator&=(const BitPattern &other)
Creates a new BitPattern that is the conjunction of two bit patterns.
void check_insertion(T msk, T pat, size_t wordnum) const
Check that a pattern insertion does not conflict with an existing pattern.
BitPattern(size_t lo_bit, size_t hi_bit, T pat, size_t wordnum)
Create a new bit pattern for a single word using bit offsets.
BitPattern()
Creates a new, empty bit pattern.
size_t nsignificant() const
Returns the number of significant bits.
BitPattern & insert(T msk, T pat, size_t wordnum=0)
Creates a new pattern by adding significant bits to all alternatives of a pattern.
bool matches(const T *value_words, size_t sz) const
Returns true if this pattern matches the specified values.
T conflict(T msk, T pat, size_t wordnum, size_t altnum) const
Determines if the specified bits conflict with a particular pattern alternative.
bool is_consistent() const
Verify internal consistency.
size_t nalternatives() const
Returns the number of alternatives.
BitPattern & disjunction(const BitPattern &other)
Combines this BitPattern with another by forming their disjunction.
BitPattern operator|(const BitPattern &other) const
Creates a new BitPattern that is the inclusive disjunction of two bit patterns.
bool any_same(const BitPattern &other, std::pair< size_t, size_t > *alternatives=NULL) const
Determines whether two patterns can match the same input.
BitPattern shift_left(size_t nbits) const
Return a new BitPattern with the pattern bits shifted left by the indicated amount.
BitPattern operator&(const BitPattern &other) const
Creates a new BitPattern that is the conjunction of two bit patterns.
BitPattern & conjunction(const BitPattern &other)
Combines this BitPattern with another by forming their conjunction.
void print(std::ostream &o, size_t altnum, bool with_mask=true) const
Print one pattern alternative.
BitPattern & operator|=(const BitPattern &other)
Creates a new BitPattern that is the inclusive disjunction of two bit patterns.
std::pair< T, T > invariants(T msk, size_t wordnum)
Returns invariant bits.
bool matches(const std::vector< T > value_words) const
Returns true if this pattern matches the specified values.
BitPattern & bits(size_t lo_bit, size_t hi_bit, T value, size_t wordnum)
Adds significant bits to all alternatives of a pattern.
T mask(size_t wordnum)
Returns the mask for the specified word.
T conflict(T msk, T pat, size_t wordnum) const
Determines if the specified significant bits conflict with any of the existing pattern alternatives.
size_t width() const
Returns the size of the pattern in bits.
boost::optional< size_t > msb_set(T val)
Optionally returns the zero-origin position of the most significant set bit.
size_t countSet(T val)
Counts how many bits are set (one).
T shiftLeft2(T value, size_t count, size_t width=8 *sizeof(T))
Shifts bits of value left by count bits.
T shiftRightLogical2(T value, size_t count, size_t width=8 *sizeof(T))
Shifts bits of value right by count bits without sign extension.
ROSE_UTIL_API std::string addrToString(uint64_t value, size_t nbits=0)
Convert a virtual address to a string.