@@ -15,17 +15,79 @@ private import DataFlowPrivate
1515import SsaImplCommon
1616
1717private module SourceVariables {
18+ /**
19+ * Holds if `store` is the `StoreInstruction` generated by an postfix
20+ * increment or decrement operation `e`, and `postCrement` is the operand
21+ * that represents the use of the evaluated value of `e`.
22+ */
23+ private predicate isUseAfterPostfixCrement0 ( StoreInstruction store , Operand postCrement ) {
24+ exists (
25+ BinaryInstruction binary , IRBlock b , int iPre , int iPost , int iStore , Operand preCrement ,
26+ Instruction left
27+ |
28+ binary instanceof AddInstruction
29+ or
30+ binary instanceof PointerAddInstruction
31+ or
32+ binary instanceof SubInstruction
33+ or
34+ binary instanceof PointerSubInstruction
35+ |
36+ store .getSourceValue ( ) = binary and
37+ left = binary .getLeft ( ) and
38+ strictcount ( left .getAUse ( ) ) = 2 and
39+ left .getAUse ( ) = preCrement and
40+ left .getAUse ( ) = postCrement and
41+ b .getInstruction ( iPre ) = preCrement .getUse ( ) and
42+ b .getInstruction ( iPost ) = postCrement .getUse ( ) and
43+ b .getInstruction ( iStore ) = store and
44+ iPre < iStore and
45+ iStore < iPost
46+ )
47+ }
48+
49+ /**
50+ * Holds if `store` is the `StoreInstruction` generated by an postfix
51+ * increment or decrement operation `e`, and `postCrement` is the fully
52+ * converted operand that represents the use of the evaluated value of `e`.
53+ */
54+ private predicate isUseAfterPostfixCrement ( StoreInstruction store , Operand postCrement ) {
55+ isUseAfterPostfixCrement0 ( store , postCrement ) and
56+ conversionFlow ( postCrement , _, false , _)
57+ or
58+ exists ( Instruction instr , Operand postCrement0 |
59+ isUseAfterPostfixCrement ( store , postCrement0 ) and
60+ conversionFlow ( postCrement0 , instr , false , _) and
61+ instr = postCrement .getDef ( )
62+ )
63+ }
64+
65+ private predicate hasSavedPostfixCrementSourceVariable (
66+ BaseSourceVariable base , StoreInstruction store , int ind
67+ ) {
68+ exists ( BaseSourceVariableInstruction inst , int ind0 |
69+ isUseAfterPostfixCrement ( store , _) and
70+ inst .getBaseSourceVariable ( ) = base and
71+ isDef ( _, _, store .getDestinationAddressOperand ( ) , inst , ind0 , 0 ) and
72+ ind = [ ind0 .. countIndirectionsForCppType ( base .getLanguageType ( ) ) + 1 ]
73+ )
74+ }
75+
1876 cached
1977 private newtype TSourceVariable =
20- TMkSourceVariable ( BaseSourceVariable base , int ind ) {
78+ TNormalSourceVariable ( BaseSourceVariable base , int ind ) {
2179 ind = [ 0 .. countIndirectionsForCppType ( base .getLanguageType ( ) ) + 1 ]
80+ } or
81+ TSavedPostfixCrementSourceVariable ( StoreInstruction store , int ind ) {
82+ hasSavedPostfixCrementSourceVariable ( _, store , ind )
2283 }
2384
24- class SourceVariable extends TSourceVariable {
85+ abstract private class AbstractSourceVariable extends TSourceVariable {
2586 BaseSourceVariable base ;
2687 int ind ;
2788
28- SourceVariable ( ) { this = TMkSourceVariable ( base , ind ) }
89+ bindingset [ ind]
90+ AbstractSourceVariable ( ) { any ( ) }
2991
3092 /** Gets the IR variable associated with this `SourceVariable`, if any. */
3193 IRVariable getIRVariable ( ) { result = base .( BaseIRVariable ) .getIRVariable ( ) }
@@ -37,7 +99,7 @@ private module SourceVariables {
3799 BaseSourceVariable getBaseVariable ( ) { result = base }
38100
39101 /** Gets a textual representation of this element. */
40- string toString ( ) { result = repeatStars ( this . getIndirection ( ) ) + base . toString ( ) }
102+ abstract string toString ( ) ;
41103
42104 /**
43105 * Gets the number of loads performed on the base source variable
@@ -62,6 +124,53 @@ private module SourceVariables {
62124 /** Gets the location of this variable. */
63125 Location getLocation ( ) { result = this .getBaseVariable ( ) .getLocation ( ) }
64126 }
127+
128+ final class SourceVariable = AbstractSourceVariable ;
129+
130+ /**
131+ * A regular source variable. Most source variables are instances of this
132+ * class.
133+ */
134+ class NormalSourceVariable extends AbstractSourceVariable , TNormalSourceVariable {
135+ NormalSourceVariable ( ) { this = TNormalSourceVariable ( base , ind ) }
136+
137+ final override string toString ( ) {
138+ result = repeatStars ( this .getIndirection ( ) ) + base .toString ( )
139+ }
140+ }
141+
142+ /**
143+ * Before a value is postfix incremented (or decremented) we "save" its
144+ * current value so that the pre-incremented value can be returned to the
145+ * enclosing expression. We use the source variables represented by this
146+ * class to represent the "saved value".
147+ */
148+ class SavedPostfixCrementSourceVariable extends AbstractSourceVariable ,
149+ TSavedPostfixCrementSourceVariable
150+ {
151+ StoreInstruction store ;
152+
153+ SavedPostfixCrementSourceVariable ( ) {
154+ this = TSavedPostfixCrementSourceVariable ( store , ind ) and
155+ hasSavedPostfixCrementSourceVariable ( base , store , ind )
156+ }
157+
158+ final override string toString ( ) {
159+ result = repeatStars ( this .getIndirection ( ) ) + base .toString ( ) + " [before crement]"
160+ }
161+
162+ /**
163+ * Gets the `StoreInstruction` that writes the incremented (or decremented)
164+ * value.
165+ */
166+ StoreInstruction getStoreInstruction ( ) { result = store }
167+
168+ /**
169+ * Gets the fully converted `Operand` that represents the use of the
170+ * value before the increment.
171+ */
172+ Operand getOperand ( ) { isUseAfterPostfixCrement ( store , result ) }
173+ }
65174}
66175
67176import SourceVariables
@@ -109,17 +218,43 @@ private newtype TDefImpl =
109218 TDirectDefImpl ( Operand address , int indirectionIndex ) {
110219 isDef ( _, _, address , _, _, indirectionIndex )
111220 } or
221+ TSavedPostfixCrementDefImpl ( SavedPostfixCrementSourceVariable sv , int indirectionIndex ) {
222+ isDef ( _, _, sv .getStoreInstruction ( ) .getDestinationAddressOperand ( ) , _, sv .getIndirection ( ) ,
223+ indirectionIndex )
224+ } or
112225 TGlobalDefImpl ( GlobalLikeVariable v , IRFunction f , int indirectionIndex ) {
113226 // Represents the initial "definition" of a global variable when entering
114227 // a function body.
115228 isGlobalDefImpl ( v , f , _, indirectionIndex )
116229 }
117230
231+ pragma [ nomagic]
232+ private predicate hasOperandAndIndirection (
233+ SavedPostfixCrementSourceVariable sv , Operand operand , int indirection
234+ ) {
235+ sv .getOperand ( ) = operand and
236+ sv .getIndirection ( ) = indirection
237+ }
238+
239+ private predicate hasBeforePostCrementUseImpl (
240+ SavedPostfixCrementSourceVariable sv , Operand operand , int indirectionIndex
241+ ) {
242+ not isDef ( true , _, operand , _, _, _) and
243+ exists ( int indirection |
244+ hasOperandAndIndirection ( sv , operand , indirection ) and
245+ isUse ( _, operand , _, indirection , indirectionIndex )
246+ )
247+ }
248+
118249cached
119250private newtype TUseImpl =
120251 TDirectUseImpl ( Operand operand , int indirectionIndex ) {
121252 isUse ( _, operand , _, _, indirectionIndex ) and
122- not isDef ( true , _, operand , _, _, _)
253+ not isDef ( true , _, operand , _, _, _) and
254+ not hasBeforePostCrementUseImpl ( _, operand , indirectionIndex )
255+ } or
256+ TSavedPostfixCrementUseImpl ( SavedPostfixCrementSourceVariable sv , int indirectionIndex ) {
257+ hasBeforePostCrementUseImpl ( sv , _, indirectionIndex )
123258 } or
124259 TGlobalUse ( GlobalLikeVariable v , IRFunction f , int indirectionIndex ) {
125260 // Represents a final "use" of a global variable to ensure that
@@ -326,7 +461,7 @@ abstract private class DefAddressImpl extends DefImpl, TDefAddressImpl {
326461
327462 override Cpp:: Location getLocation ( ) { result = v .getLocation ( ) }
328463
329- final override SourceVariable getSourceVariable ( ) {
464+ final override NormalSourceVariable getSourceVariable ( ) {
330465 result .getBaseVariable ( ) = v and
331466 result .getIndirection ( ) = 0
332467 }
@@ -381,7 +516,7 @@ private class DirectDef extends DefImpl, TDirectDefImpl {
381516 indirection = this .getIndirection ( )
382517 }
383518
384- final override SourceVariable getSourceVariable ( ) {
519+ final override NormalSourceVariable getSourceVariable ( ) {
385520 exists ( BaseSourceVariable v , int indirection |
386521 sourceVariableHasBaseAndIndex ( result , v , indirection ) and
387522 this .hasBaseSourceVariableAndIndirection ( v , indirection )
@@ -395,6 +530,32 @@ private class DirectDef extends DefImpl, TDirectDefImpl {
395530 override predicate isCertain ( ) { isDef ( true , _, address , _, _, indirectionIndex ) }
396531}
397532
533+ /**
534+ * A definition that "saves" the value of a variable before it is incremented
535+ * or decremented.
536+ */
537+ private class SavedPostfixCrementDefImpl extends DefImpl , TSavedPostfixCrementDefImpl {
538+ SavedPostfixCrementSourceVariable sv ;
539+
540+ SavedPostfixCrementDefImpl ( ) { this = TSavedPostfixCrementDefImpl ( sv , indirectionIndex ) }
541+
542+ override Cpp:: Location getLocation ( ) { result = sv .getStoreInstruction ( ) .getLocation ( ) }
543+
544+ final override predicate hasIndexInBlock ( IRBlock block , int index ) {
545+ sv .getStoreInstruction ( ) = block .getInstruction ( index )
546+ }
547+
548+ override string toString ( ) { result = "Def of " + this .getSourceVariable ( ) }
549+
550+ override SourceVariable getSourceVariable ( ) { result = sv }
551+
552+ override int getIndirection ( ) { result = sv .getIndirection ( ) }
553+
554+ override predicate isCertain ( ) {
555+ isDef ( true , _, sv .getStoreInstruction ( ) .getDestinationAddressOperand ( ) , _, _, indirectionIndex )
556+ }
557+ }
558+
398559private class DirectUseImpl extends UseImpl , TDirectUseImpl {
399560 Operand operand ;
400561
@@ -414,7 +575,7 @@ private class DirectUseImpl extends UseImpl, TDirectUseImpl {
414575 this .getIndirection ( ) = indirection
415576 }
416577
417- override SourceVariable getSourceVariable ( ) {
578+ override NormalSourceVariable getSourceVariable ( ) {
418579 exists ( BaseSourceVariable v , int indirection |
419580 sourceVariableHasBaseAndIndex ( result , v , indirection ) and
420581 this .hasBaseSourceVariableAndIndirection ( v , indirection )
@@ -432,6 +593,34 @@ private class DirectUseImpl extends UseImpl, TDirectUseImpl {
432593 override Node getNode ( ) { nodeHasOperand ( result , operand , indirectionIndex ) }
433594}
434595
596+ /**
597+ * The use of the original "saved" variable after the variable has been incremented
598+ * or decremented.
599+ */
600+ private class SavedPostfixCrementUseImpl extends UseImpl , TSavedPostfixCrementUseImpl {
601+ SavedPostfixCrementSourceVariable sv ;
602+
603+ SavedPostfixCrementUseImpl ( ) { this = TSavedPostfixCrementUseImpl ( sv , indirectionIndex ) }
604+
605+ override string toString ( ) { result = "Use of " + this .getSourceVariable ( ) }
606+
607+ final override predicate hasIndexInBlock ( IRBlock block , int index ) {
608+ this .getOperand ( ) .getUse ( ) = block .getInstruction ( index )
609+ }
610+
611+ override SourceVariable getSourceVariable ( ) { result = sv }
612+
613+ final Operand getOperand ( ) { result = sv .getOperand ( ) }
614+
615+ final override Cpp:: Location getLocation ( ) { result = this .getOperand ( ) .getLocation ( ) }
616+
617+ override int getIndirection ( ) { result = sv .getIndirection ( ) }
618+
619+ override predicate isCertain ( ) { isUse ( true , this .getOperand ( ) , _, _, indirectionIndex ) }
620+
621+ override Node getNode ( ) { nodeHasOperand ( result , this .getOperand ( ) , indirectionIndex ) }
622+ }
623+
435624pragma [ nomagic]
436625private predicate finalParameterNodeHasParameterAndIndex (
437626 FinalParameterNode n , Parameter p , int indirectionIndex
@@ -502,7 +691,7 @@ class FinalParameterUse extends UseImpl, TFinalParameterUse {
502691 indirection = this .getIndirection ( )
503692 }
504693
505- override SourceVariable getSourceVariable ( ) {
694+ override NormalSourceVariable getSourceVariable ( ) {
506695 exists ( BaseIRVariable v , int indirection |
507696 sourceVariableHasBaseAndIndex ( result , v , indirection ) and
508697 this .hasBaseSourceVariableAndIndirectrion ( v , indirection )
@@ -593,7 +782,7 @@ class GlobalUse extends UseImpl, TGlobalUse {
593782 indirection = this .getIndirection ( )
594783 }
595784
596- override SourceVariable getSourceVariable ( ) {
785+ override NormalSourceVariable getSourceVariable ( ) {
597786 exists ( BaseIRVariable v , int indirection |
598787 sourceVariableHasBaseAndIndex ( result , v , indirection ) and
599788 this .hasBaseSourceVariableAndIndirection ( v , indirection )
@@ -642,7 +831,7 @@ class GlobalDefImpl extends DefImpl, TGlobalDefImpl {
642831 )
643832 }
644833
645- final override SourceVariable getSourceVariable ( ) {
834+ final override NormalSourceVariable getSourceVariable ( ) {
646835 exists ( BaseSourceVariable v |
647836 sourceVariableHasBaseAndIndex ( result , v , indirectionIndex ) and
648837 baseSourceVariableIsGlobal ( v , global , f )
@@ -688,9 +877,15 @@ predicate defToNode(Node node, Definition def, SourceVariable sv) {
688877}
689878
690879private predicate defToNode ( Node node , Definition def ) {
691- nodeHasOperand ( node , def .getValue ( ) .asOperand ( ) , def .getIndirectionIndex ( ) )
692- or
693- nodeHasInstruction ( node , def .getValue ( ) .asInstruction ( ) , def .getIndirectionIndex ( ) )
880+ // Only definitions of `NormalSourceVariable` need to be converted into
881+ // dataflow nodes. The other case, `SavedPostfixCrementSourceVariable`,
882+ // are internal definitions that don't have a dataflow node representation.
883+ def .getSourceVariable ( ) instanceof NormalSourceVariable and
884+ (
885+ nodeHasOperand ( node , def .getValue ( ) .asOperand ( ) , def .getIndirectionIndex ( ) )
886+ or
887+ nodeHasInstruction ( node , def .getValue ( ) .asInstruction ( ) , def .getIndirectionIndex ( ) )
888+ )
694889 or
695890 node .( InitialGlobalValue ) .getGlobalDef ( ) = def
696891}
0 commit comments