@@ -1747,6 +1747,10 @@ Memory::mkFnRet(const char *name0, const vector<PtrInput> &ptr_inputs,
17471747 return { std::move (p).release (), {} };
17481748}
17491749
1750+ expr Memory::CallState::writes (unsigned idx) const {
1751+ return writes_block.extract (idx, idx) == 1 ;
1752+ }
1753+
17501754Memory::CallState Memory::CallState::mkIf (const expr &cond,
17511755 const CallState &then,
17521756 const CallState &els) {
@@ -1764,22 +1768,24 @@ Memory::CallState Memory::CallState::mkIf(const expr &cond,
17641768 els.non_local_block_val [i]));
17651769 }
17661770 }
1771+ ret.writes_block = expr::mkIf (cond, then.writes_block , els.writes_block );
17671772 ret.writes_args = expr::mkIf (cond, then.writes_args , els.writes_args );
17681773 ret.non_local_liveness = expr::mkIf (cond, then.non_local_liveness ,
17691774 els.non_local_liveness );
17701775 return ret;
17711776}
17721777
17731778expr Memory::CallState::operator ==(const CallState &rhs) const {
1774- if (empty != rhs.empty )
1779+ if (non_local_liveness. isValid () != rhs.non_local_liveness . isValid () )
17751780 return false ;
1776- if (empty )
1781+ if (!non_local_liveness. isValid () )
17771782 return true ;
17781783
17791784 expr ret = non_local_liveness == rhs.non_local_liveness ;
17801785 for (unsigned i = 0 , e = non_local_block_val.size (); i != e; ++i) {
17811786 ret &= non_local_block_val[i] == rhs.non_local_block_val [i];
17821787 }
1788+ ret &= writes_block == rhs.writes_block ;
17831789 if (writes_args.isValid ())
17841790 ret &= writes_args == rhs.writes_args ;
17851791 return ret;
@@ -1790,7 +1796,21 @@ Memory::mkCallState(const string &fnname, bool nofree, unsigned num_ptr_args,
17901796 const SMTMemoryAccess &access) {
17911797 assert (has_fncall);
17921798 CallState st;
1793- st.empty = false ;
1799+
1800+ {
1801+ unsigned num_blocks = 1 ;
1802+ unsigned limit = num_nonlocals_src - num_inaccessiblememonly_fns;
1803+ for (unsigned i = 0 ; i < limit; ++i) {
1804+ if (!always_nowrite (i, true , true ))
1805+ ++num_blocks;
1806+ }
1807+ st.writes_block = expr::mkUInt (0 , num_blocks);
1808+ }
1809+
1810+ if (access.canWriteSomething ().isFalse ()) {
1811+ st.writes_args = expr::mkUInt (0 , num_ptr_args);
1812+ return st;
1813+ }
17941814
17951815 // TODO: handle havoc of local blocks
17961816
@@ -1809,6 +1829,15 @@ Memory::mkCallState(const string &fnname, bool nofree, unsigned num_ptr_args,
18091829 st.non_local_block_val .emplace_back (
18101830 expr::mkFreshVar (" blk_val" , mk_block_val_array (i)));
18111831 }
1832+ st.writes_block = expr::mkFreshVar (" writes_block" , st.writes_block );
1833+ assert (st.writes_block .bits () == st.non_local_block_val .size ());
1834+ }
1835+ else if (!only_write_inaccess.isFalse ()) {
1836+ auto var = expr::mkFreshVar (" writes_block" , expr::mkUInt (0 , 1 ));
1837+ if (st.writes_block .bits () > 1 )
1838+ st.writes_block = expr::mkUInt (0 , st.writes_block .bits ()-1 ).concat (var);
1839+ else
1840+ st.writes_block = std::move (var);
18121841 }
18131842
18141843 st.writes_args
@@ -1844,8 +1873,8 @@ void Memory::setState(const Memory::CallState &st,
18441873 assert (is_fncall_mem (bid));
18451874 assert (non_local_block_val[bid].undef .empty ());
18461875 auto &cur_val = non_local_block_val[bid].val ;
1847- cur_val
1848- = mk_block_if (only_write_inaccess, st.non_local_block_val [0 ], cur_val);
1876+ cur_val = mk_block_if (only_write_inaccess && st. writes ( 0 ),
1877+ st.non_local_block_val [0 ], cur_val);
18491878 }
18501879
18511880 // TODO: MemoryAccess::Errno
@@ -1858,7 +1887,7 @@ void Memory::setState(const Memory::CallState &st,
18581887 if (always_nowrite (bid, true , true ))
18591888 continue ;
18601889
1861- expr modifies = access.canWrite (MemoryAccess::Other);
1890+ expr modifies = access.canWrite (MemoryAccess::Other) && st. writes (idx) ;
18621891
18631892 if (!is_fncall_mem (bid)) {
18641893 unsigned arg_idx = 0 ;
@@ -1870,8 +1899,10 @@ void Memory::setState(const Memory::CallState &st,
18701899 access.canWrite (MemoryAccess::Args) &&
18711900 writes;
18721901
1902+ Pointer ptr (*this , ptr_in.val .value );
18731903 modifies |= cond &&
1874- Pointer (*this , ptr_in.val .value ).getBid () == bid;
1904+ !ptr.isNull () &&
1905+ ptr.getBid () == bid;
18751906 state->addUB (cond.implies (ptr_in.val .non_poison ));
18761907 state->addUB (ptr_in.nowrite .implies (!writes));
18771908 ++arg_idx;
0 commit comments