C++: IR translation for static local initializers#12900
C++: IR translation for static local initializers#12900MathiasVP merged 9 commits intogithub:mainfrom
Conversation
2c4d90c to
9f22a10
Compare
|
I don't think we should add a change note for this until we've added the dataflow component as well. |
9f22a10 to
7cec237
Compare
7cec237 to
3f03cc2
Compare
cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll
Show resolved
Hide resolved
|
Wireshark DCA results show quite a significant increase on |
|
Looking at the DCA results, the performance of kamailio also seems to have regressed somewhat. Do we know why? |
Ouch. I missed that one completely (in my defence, it's all the way to the right of the window 😂). I'll take a look at this. |
Yeah, I think I know why now 😄: https://gist.github.com/MathiasVP/9a947427b9f4f37ad025efed208554f9. Will fix! Edit: Fixed in 60aab20 |
Before:
```
Evaluated non-recursive predicate TranslatedElement#ea057665::TranslatedElement::getInstructionVariable#1#dispred#fff@146210id in 201548ms (size: 3469729).
Evaluated relational algebra for predicate TranslatedElement#ea057665::TranslatedElement::getInstructionVariable#1#dispred#fff@146210id with tuple counts:
...
1812768 ~3% {3} r65 = JOIN num#InstructionTag#c9183db3::OnlyInstructionTag#f WITH TranslatedExpr#043317a1::TranslatedNonFieldVariableAccess#ff CARTESIAN PRODUCT OUTPUT Rhs.1, Lhs.0, Rhs.0
1812767 ~0% {4} r66 = JOIN r65 WITH Access#8878f617::Access::getTarget#0#dispred#ff ON FIRST 1 OUTPUT Rhs.1, Lhs.1, Lhs.2, Lhs.0
3996407117 ~3% {5} r67 = JOIN r66 WITH TranslatedElement#ea057665::getIRUserVariable#2#fff_102#join_rhs ON FIRST 1 OUTPUT Lhs.3, Rhs.1, Lhs.1, Lhs.2, Rhs.2
1815194 ~0% {3} r68 = JOIN r67 WITH TranslatedExpr#043317a1::getEnclosingDeclaration#1#ff ON FIRST 2 OUTPUT Lhs.3, Lhs.2, Lhs.4
...
```
After:
```
Evaluated non-recursive predicate TranslatedExpr#043317a1::accessHasEnclosingDeclarationAndVariable#3#fff@665ccb8o in 865ms (size: 2769549).
Evaluated relational algebra for predicate TranslatedExpr#043317a1::accessHasEnclosingDeclarationAndVariable#3#fff@665ccb8o with tuple counts:
2769549 ~1% {3} r1 = JOIN Access#8878f617::Access::getTarget#0#dispred#ff WITH TranslatedExpr#043317a1::getEnclosingDeclaration#1#ff ON FIRST 1 OUTPUT Rhs.1, Lhs.1, Lhs.0
return r1
...
Evaluated non-recursive predicate TranslatedElement#ea057665::TranslatedElement::getInstructionVariable#1#dispred#fff@7d4d33to in 805ms (size: 3469729).
Evaluated relational algebra for predicate TranslatedElement#ea057665::TranslatedElement::getInstructionVariable#1#dispred#fff@7d4d33to with tuple counts:
...
1963209 ~0% {2} r34 = JOIN TranslatedElement#ea057665::getIRUserVariable#2#fff WITH TranslatedExpr#043317a1::accessHasEnclosingDeclarationAndVariable#3#fff ON FIRST 2 OUTPUT Rhs.2, Lhs.2
1815194 ~2% {2} r35 = JOIN r34 WITH TranslatedExpr#043317a1::TranslatedNonFieldVariableAccess#ff_10#join_rhs ON FIRST 1 OUTPUT Lhs.1, Rhs.1
1815194 ~0% {3} r36 = JOIN r35 WITH num#InstructionTag#c9183db3::OnlyInstructionTag#f CARTESIAN PRODUCT OUTPUT Lhs.1, Rhs.0, Lhs.0
...
```
8e7648d to
60aab20
Compare
I can't say that I understand the issue yet, but they all seem to reduce to the testcase I've added in 1dcac76. The large number of new inconsistencies is simply because it appears so many times in those very large static initializers. The printed IR is also very strange (which I guess is expected given inconsistencies): 7| void regression_test()
7| Block 0
7| v7_1(void) = EnterFunction :
7| m7_2(unknown) = AliasedDefinition :
7| m7_3(unknown) = InitializeNonLocal :
7| m7_4(unknown) = Chi : total:m7_2, partial:m7_3
10| v10_1(void) = NoOp :
7| v7_5(void) = ReturnVoid :
7| v7_6(void) = AliasedUse : m7_3
7| v7_7(void) = ExitFunction :
9| const void *[] a
9| Block 0
9| v9_1(void) = EnterFunction :
9| m9_2(unknown) = AliasedDefinition :
9| r9_3(glval<void *[]>) = VariableAddress[a] :
9| r9_4(int) = Constant[0] :
9| r9_5(glval<void *>) = PointerAdd[8] : r9_3, r9_4
9| r9_6(int) = Constant[0] :
| False -> Block 1
9| Block 1
9| r9_7(glval<_A[]>) = VariableAddress[as] :
9| r9_8(_A *) = Convert : r9_7
9| r9_9(glval<_A *>) = VariableAddress[#temp9:31] :
9| m9_10(_A *) = Store[#temp9:31] : &:r9_9, r9_8
9| r9_11(glval<_A *>) = VariableAddress[#temp9:31] :
9| r9_12(_A *) = Load[#temp9:31] : &:r9_11, m9_10
9| r9_13(void *) = Convert : r9_12
9| m9_14(void *) = Store[?] : &:r9_5, r9_13
9| m9_15(unknown) = Chi : total:m9_2, partial:m9_14
9| v9_16(void) = ReturnVoid :
9| v9_17(void) = AliasedUse : ~m9_15
9| v9_18(void) = ExitFunction :The search continues! Edit: Fixed in b18e096 🎉 |
| override TranslatedElement getChild(int id) { none() } | ||
|
|
||
| override Function getFunction() { result = getParent().getFunction() } | ||
| override Declaration getFunction() { result = getParent().getFunction() } |
There was a problem hiding this comment.
This wasn't actually necessary to fix the inconsistency, but it was the only remaining getFunction implementation where:
- The return type was specified to be
Function, and - where result value wasn't obviously a
Function.
cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll
Fixed
Show fixed
Hide fixed
|
@jketema DCA looks good now: a fairly large reduction in inconsistencies, and the slowdown on Kamailio is gone. So now we're just left with the Wireshark slowdown (which we understand, and are okay with). |
This PR adds IR for the static initializers of static locals. On
main, we already generate IR for runtime initializers static locals. For example, given this code:we generate IR corresponding to this snippet:
but for static initialized static locals no IR was generated. This PR adds such initialization. So given code like:
we generate IR corresponding to:
Meaning that static initialized static locals are now handled exactly like we handle initialization of global variables (which are always static initialized).
Once this has been merged, I'll add the necessary dataflow steps to make sure that we track dataflow appropriately.
Wireshark seems to have some very very large static-local initializers (such as this 44k LoC initializer). This is what's causing a large slowdown in IR generation. It's not like there's any bad performance now. We really just generate twice as much IR as before.
I did a QA run across 3000 projects, and no other project seems to suffer from the same problem. We could disable IR generation for static initializers in auto generated files (since the initializer in the file above is very clearly in an autogenerated file), but after discussing this with @rdmarsh2 we decided it wasn't worth adding this heuristic into the IR.