-
Notifications
You must be signed in to change notification settings - Fork 1.8k
C++: Implement Instruction.isResultConflated #3097
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
This predicate replaces `isChiForAllAliasedMemory`, which was always intended to be temporary. A test is added to `IRSanity.qll` to verify that the new predicate corresponds exactly with (a fixed version of) the old one. The implementation of the new predicate, `Cached::hasConflatedMemoryResult` in `SSAConstruction.qll`, is faster to compute than the old `isChiForAllAliasedMemory` because it uses information that's readily available during SSA construction.
* as originating on the `AliasedDefinitionInstruction` at the entry of the | ||
* function. | ||
*/ | ||
final predicate isResultConflated() { Construction::hasConflatedMemoryResult(this) } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I modelled the naming of this predicate on isResultModeled
, which is right above it.
It might be confusing that this predicate is inverted compared to isResultModeled
: the new predicate holds when the instruction is imprecise, whereas isResultModeled
holds when it's (in a sense) precise. Do we need isResultModeled
? It's currently only used for the pretty-printer, and I think isResultConflated
might be better for pretty-printing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think there will be much use of isResultModeled
. In fact, I believe that your usage is the first outside of the Instruction
class itself.
I like having unmodeled results and operands print out as mu
instead of m
. I do think that isResultConflated
is worth displaying in IR dumps as well, though. I'm not sure what punctuation to use for that, but Emoji open up a world of possibilities:
# 134| m134_4🔀(unknown) = Chi : total:m134_2, partial:m134_3
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Um... yes. I was thinking ma
for results and operands that are conflated but not unmodelled.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
...where the a
is for Aliased.
or | ||
instruction instanceof AliasedDefinitionInstruction | ||
or | ||
instruction.getOpcode() instanceof Opcode::InitializeNonLocal |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All the uses of InitializeNonLocal
can hopefully just go away when we remove that opcode. That means this PR has a semantic conflict with @rdmarsh2's work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the approach. A few comments on the details.
cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll
Outdated
Show resolved
Hide resolved
@@ -65,6 +65,30 @@ private module Cached { | |||
instruction instanceof ChiInstruction // Chis always have modeled results | |||
} | |||
|
|||
cached |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In plain language, this predicate is basically identifying instructions that are either writing to all of aliased memory (AliasedDefinition
, InitializeNonLocal
, certain Chi
s and Phi
s), or are unmodeled, right? If so, I think it can be simplified:
- If the memory location of the result of the old instruction totally overlaps
AliasedVirtualVariable
- If the instruction is a
Chi
, and the virtual variable of the result of the non-Chi
old instruction isAliasedVirtualVariable
. - If the result of the instruction is unmodeled.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that's the definition I have in mind. But it's not clear to me how your alternative implementation can be written down just in terms of predicates that are public in AliasedSSA.qll
and SimpleSSA.qll
. (I cheated and added a few lines to SimpleSSA.qll
to make my implementation work).
csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll
Outdated
Show resolved
Hide resolved
or | ||
exists(Alias::MemoryLocation location | | ||
instruction = Phi(_, location) and | ||
location.getVirtualVariable() instanceof Alias::AliasedVirtualVariable |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I should be possible to have a Phi
for a specific (non-conflated) location that happens to be part of AliasedVirtualVariable
. I'm not sure if we have this specific test case, but in ssa.cpp
, function MergeMustExactlyWithMustTotallyOverlap
shows how this works when the location in question does not escape. You get two Phi
instructions, one for the entire virtual variable, and one for the specific location within that virtual variable. See the QLDoc for the PhiInsertion
module in SSAConstruction.qll
for a bit more detail on the how and why.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What would a test case look like?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps this issue has to do with the test failures.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've written a test case that exhibits the problem you describe.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've just pushed a commit to demonstrate the problem, followed by a commit to fix it.
* as originating on the `AliasedDefinitionInstruction` at the entry of the | ||
* function. | ||
*/ | ||
final predicate isResultConflated() { Construction::hasConflatedMemoryResult(this) } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think there will be much use of isResultModeled
. In fact, I believe that your usage is the first outside of the Instruction
class itself.
I like having unmodeled results and operands print out as mu
instead of m
. I do think that isResultConflated
is worth displaying in IR dumps as well, though. I'm not sure what punctuation to use for that, but Emoji open up a world of possibilities:
# 134| m134_4🔀(unknown) = Chi : total:m134_2, partial:m134_3
cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll
Show resolved
Hide resolved
There are test failures in the sound IR. I hadn't found these tests because I apparently grepped for the wrong thing. I'll investigate. |
not use instanceof EntireAllocationMemoryLocation and | ||
result instanceof MustTotallyOverlap | ||
if def.getAllocation() = use.getAllocation() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this looks right.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The DIL LGTM, and so do the tuple counts on Wireshark.
I had included `InitializeNonLocal` in the recursion because it made everything look better in the presence of a bug that's since been fixed. Taking it out means the sanity test is again aligned with the old `isChiForAllAliasedMemory`.
…memory Conflicts: cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRSanity.qll cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IRSanity.qll cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IRSanity.qll cpp/ql/test/library-tests/ir/ir/aliased_ssa_sanity.expected cpp/ql/test/library-tests/ir/ir/aliased_ssa_sanity_unsound.expected cpp/ql/test/library-tests/ir/ir/raw_sanity.expected cpp/ql/test/library-tests/ir/ir/unaliased_ssa_sanity.expected cpp/ql/test/library-tests/ir/ir/unaliased_ssa_sanity_unsound.expected cpp/ql/test/library-tests/ir/ssa/aliased_ssa_sanity.expected cpp/ql/test/library-tests/ir/ssa/aliased_ssa_sanity_unsound.expected cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_sanity.expected cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_sanity_unsound.expected cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_sanity.expected cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_sanity.expected csharp/ql/src/semmle/code/csharp/ir/implementation/raw/IRSanity.qll csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/IRSanity.qll csharp/ql/test/library-tests/ir/ir/raw_ir_sanity.expected csharp/ql/test/library-tests/ir/ir/unaliased_ssa_sanity.expected
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM now
This predicate replaces
isChiForAllAliasedMemory
, which was always intended to be temporary. A test is added toIRSanity.qll
to verify that the new predicate corresponds exactly with(a fixed version of)the old one.The implementation of the new predicate,
Cached::hasConflatedMemoryResult
inSSAConstruction.qll
, is faster to compute than the oldisChiForAllAliasedMemory
because it uses information that's readily available during SSA construction.EDIT: This PR now also contains a fix for how
EntireAllocationMemoryLocation
is modelled. There were cases before whereInitializeParameterInstruction
appeared to overwrite the result ofAliasedDefinitionInstruction
.