Fix a bug in the LLVM memory model (with SMT array backed allocations) #603
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Most of this commit is additional comments that try to clarify some of the
things that came up while diagnosing the bug. The actual fix is in
writeMemWithAllocationCheck
.The observed behavior was that a test case (in another repository) generated
formulas where reads and writes to SMT array-backed allocations did not refer to
the same byte offsets, when they should have. Specifically, the scenario was
that the test case has a single large allocation backed by an SMT array. The
function exhibiting the problem started with a pointer to the middle of that
allocation. Some of the reads and writes were properly in the middle of the
allocation (with a large offset appearing in SMT array
select
operations),while others were using inappropriate low offsets (around zero).
The problem was a bug in the optimization in the memory model that coalesces
writes to SMT array backed allocations (which reduces the number of muxes
generated in many cases). The goal of this optimization (which is now
documented) is to turn sequential updates to an SMT array backed allocation into
a single entry in the write log by pretending that the small write actually
overwrites the entire SMT array with new values (which are the original contents
of the SMT array plus the new values just written, expressed as an SMT array
update
).To do this correctly, the updated array must overwrite the entire
allocation (i.e., starting at offset 0 within the block). The bug was that the
array was being written at the offset in the pointer to the start of the new
write. In the case outlined above, this meant that the new array was spliced
over the old one halfway through the allocation. This had a few consequences:
writes (due to the intricacies of how read offsets are calculated in SMT array
allocations)
looked like they spanned two different array allocations
update
operations in them at allbecause the reads looked independent of all of the writes (due to the
misalignment)