Skip to content

C++: Refactor isDef and isUse in preparation for iterator flow#11543

Merged
MathiasVP merged 6 commits into
github:mathiasvp/replace-ast-with-ir-use-usedataflowfrom
MathiasVP:refactor-isdef-isuse
Dec 8, 2022
Merged

C++: Refactor isDef and isUse in preparation for iterator flow#11543
MathiasVP merged 6 commits into
github:mathiasvp/replace-ast-with-ir-use-usedataflowfrom
MathiasVP:refactor-isdef-isuse

Conversation

@MathiasVP
Copy link
Copy Markdown
Contributor

@MathiasVP MathiasVP commented Dec 2, 2022

Note: The first two commits are from #11541 and should not be reviewed as part of this PR. <--- This has been force-pushed away now.

This PR performs two refactorings:

  • 589f7bd makes it more explicit which instructions can serve as the "base" address of an SSA definition and use.
  • 68f0997 generalizes the concept of a LoadInstruction and StoreInstruction to an abstract class. This will be the basis of recognizing iterator reads and writes in a later PR.

@MathiasVP MathiasVP requested a review from a team as a code owner December 2, 2022 11:28
@github-actions github-actions Bot added the C++ label Dec 2, 2022
@MathiasVP MathiasVP added the no-change-note-required This PR does not need a change note label Dec 2, 2022
@MathiasVP MathiasVP force-pushed the refactor-isdef-isuse branch 2 times, most recently from b953bb0 to 34f2db1 Compare December 6, 2022 13:30
@jketema
Copy link
Copy Markdown
Contributor

jketema commented Dec 6, 2022

The DCA experiment seems to show quite some slowdown.

@MathiasVP
Copy link
Copy Markdown
Contributor Author

The DCA experiment seems to show quite some slowdown.

Oops. You're right. Let me take a look at that. Thanks for the heads up 😨.

@MathiasVP MathiasVP force-pushed the refactor-isdef-isuse branch from 34f2db1 to 9f85175 Compare December 7, 2022 22:35
@MathiasVP
Copy link
Copy Markdown
Contributor Author

The DCA experiment seems to show quite some slowdown.

Oops. You're right. Let me take a look at that. Thanks for the heads up 😨.

9f85175 should fix the performance regression. Upon investigating this I realized that #11537 broke the use-use flow branch (we lost 4 taint results in a library test), and this PR will most likely show these as missing results.

These will be fixed once:

  1. C++: Reintroduce StdBasicStringIterator #11601 is merged into main
  2. main is merged into the feature branch
  3. The feature branch is merged into this PR

Comment thread cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/ssa0/SsaInternals.qll Outdated
override Type getBaseType() { result = PointerOrReferenceType.super.getBaseType() }
}

predicate isDereference(Instruction deref, Operand address) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a specific reason why we're not modelling LoadInstructions and have a getSourceAddressOperand predicate as a member of Indirection?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, there actually is. Since the Indirection class is defined by extending Type it means that every isAdditionalDereference that's implemented must ensure to also bind this to avoid duplicating the work across many Indirection classes. For example, let's suppose we implemented loading from a LoadInstruction by implementing the isAdditionalDereference class in PointerOrReferenceTypeIndirection like:

override predicate isAdditionalDereference(Instruction deref, Operand address) {
  deref.(LoadInstruction).getSourceAddressOperand() = address
}

this would definitely work, but since this doesn't bind this we'd have a cartesian product between all PointerOrReferenceTypes and the columns in this predicate.

I think we could fix this by implementing the predicate like this instead:

override predicate isAdditionalDereference(Instruction deref, Operand address) {
  address.getType() = this and // now we bind this so that every `Indirection` instance contributes a disjoint set of cases.
  deref.(LoadInstruction).getSourceAddressOperand() = address
}

but since we do actually want all LoadInstruction to be considered dereferences, I figured it was simplest to just implement this case outside the Indirection class.

A third option would be to avoid extending Type, and instead extend an IPA type. This IPA type would then have a branch for each Indirection we care about (the next PR will add an implementation of Indirection for iterators, for example), and we could implement PointerOrReferenceTypeIndirection by extending a unit branch of this IPA type to avoid the cartesian product between PointerOrReferenceType and the columns of isAdditionalDereference.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see the problem now.

It seems that the IPA solution would require us to extend the IPA type every time we want to add a type of indirection, right? If so, that makes it more difficult for users to add additional indirection types (in the unlikely case they start digging this deeply), which is not ideal.

So lets leave this as it is.

Copy link
Copy Markdown
Contributor

@jketema jketema left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two comments (see above). Otherwise this LGTM.

@MathiasVP MathiasVP merged commit 7c6918d into github:mathiasvp/replace-ast-with-ir-use-usedataflow Dec 8, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

C++ no-change-note-required This PR does not need a change note

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants