@@ -48,6 +48,16 @@ private module SourceVariables {
4848 * indirections) of this source variable.
4949 */
5050 abstract BaseSourceVariable getBaseVariable ( ) ;
51+
52+ /** Holds if this variable is a glvalue. */
53+ predicate isGLValue ( ) { none ( ) }
54+
55+ /**
56+ * Gets the type of this source variable. If `isGLValue()` holds, then
57+ * the type of this source variable should be thought of as "pointer
58+ * to `getType()`".
59+ */
60+ abstract DataFlowType getType ( ) ;
5161 }
5262
5363 class SourceIRVariable extends SourceVariable , TSourceIRVariable {
@@ -66,6 +76,12 @@ private module SourceVariables {
6676 ind > 0 and
6777 result = this .getIRVariable ( ) .toString ( ) + " indirection"
6878 }
79+
80+ override predicate isGLValue ( ) { ind = 0 }
81+
82+ override DataFlowType getType ( ) {
83+ if ind = 0 then result = var .getType ( ) else result = getTypeImpl ( var .getType ( ) , ind - 1 )
84+ }
6985 }
7086
7187 class CallVariable extends SourceVariable , TCallVariable {
@@ -84,6 +100,8 @@ private module SourceVariables {
84100 ind > 0 and
85101 result = "Call indirection"
86102 }
103+
104+ override DataFlowType getType ( ) { result = getTypeImpl ( call .getResultType ( ) , ind ) }
87105 }
88106}
89107
@@ -530,15 +548,15 @@ predicate adjacentDefRead(DefOrUse defOrUse1, UseOrPhi use) {
530548 exists ( IRBlock bb1 , int i1 , SourceVariable v |
531549 defOrUse1 .asDefOrUse ( ) .hasIndexInBlock ( bb1 , i1 , v )
532550 |
533- exists ( IRBlock bb2 , int i2 , Definition def |
534- adjacentDefRead ( pragma [ only_bind_into ] ( def ) , pragma [ only_bind_into ] ( bb1 ) ,
551+ exists ( IRBlock bb2 , int i2 , DefinitionExt def |
552+ adjacentDefReadExt ( pragma [ only_bind_into ] ( def ) , pragma [ only_bind_into ] ( bb1 ) ,
535553 pragma [ only_bind_into ] ( i1 ) , pragma [ only_bind_into ] ( bb2 ) , pragma [ only_bind_into ] ( i2 ) ) and
536554 def .getSourceVariable ( ) = v and
537555 use .asDefOrUse ( ) .( UseImpl ) .hasIndexInBlock ( bb2 , i2 , v )
538556 )
539557 or
540558 exists ( PhiNode phi |
541- lastRefRedef ( _, bb1 , i1 , phi ) and
559+ lastRefRedefExt ( _, bb1 , i1 , phi ) and
542560 use .asPhi ( ) = phi and
543561 phi .getSourceVariable ( ) = pragma [ only_bind_into ] ( v )
544562 )
@@ -550,11 +568,18 @@ predicate adjacentDefRead(DefOrUse defOrUse1, UseOrPhi use) {
550568 * flows to `useOrPhi`.
551569 */
552570private predicate globalDefToUse ( GlobalDef globalDef , UseOrPhi useOrPhi ) {
553- exists ( IRBlock bb1 , int i1 , IRBlock bb2 , int i2 , SourceVariable v |
554- globalDef .hasIndexInBlock ( bb1 , i1 , v ) and
555- adjacentDefRead ( _, pragma [ only_bind_into ] ( bb1 ) , pragma [ only_bind_into ] ( i1 ) ,
556- pragma [ only_bind_into ] ( bb2 ) , pragma [ only_bind_into ] ( i2 ) ) and
557- useOrPhi .asDefOrUse ( ) .hasIndexInBlock ( bb2 , i2 , v )
571+ exists ( IRBlock bb1 , int i1 , SourceVariable v | globalDef .hasIndexInBlock ( bb1 , i1 , v ) |
572+ exists ( IRBlock bb2 , int i2 |
573+ adjacentDefReadExt ( _, pragma [ only_bind_into ] ( bb1 ) , pragma [ only_bind_into ] ( i1 ) ,
574+ pragma [ only_bind_into ] ( bb2 ) , pragma [ only_bind_into ] ( i2 ) ) and
575+ useOrPhi .asDefOrUse ( ) .hasIndexInBlock ( bb2 , i2 , v )
576+ )
577+ or
578+ exists ( PhiNode phi |
579+ lastRefRedefExt ( _, bb1 , i1 , phi ) and
580+ useOrPhi .asPhi ( ) = phi and
581+ phi .getSourceVariable ( ) = pragma [ only_bind_into ] ( v )
582+ )
558583 )
559584}
560585
@@ -666,17 +691,17 @@ private predicate ssaFlowImpl(SsaDefOrUse defOrUse, Node nodeFrom, Node nodeTo,
666691 * Holds if `def` is the corresponding definition of
667692 * the SSA library's `definition`.
668693 */
669- private Definition ssaDefinition ( Def def ) {
694+ private DefinitionExt ssaDefinition ( Def def ) {
670695 exists ( IRBlock block , int i , SourceVariable sv |
671696 def .hasIndexInBlock ( block , i , sv ) and
672- result .definesAt ( sv , block , i )
697+ result .definesAt ( sv , block , i , _ )
673698 )
674699}
675700
676701/** Gets a node that represents the prior definition of `node`. */
677702private Node getAPriorDefinition ( SsaDefOrUse defOrUse ) {
678- exists ( IRBlock bb , int i , SourceVariable sv , Definition def , DefOrUse defOrUse0 |
679- SsaCached :: lastRefRedef ( pragma [ only_bind_into ] ( def ) , pragma [ only_bind_into ] ( bb ) ,
703+ exists ( IRBlock bb , int i , SourceVariable sv , DefinitionExt def , DefOrUse defOrUse0 |
704+ lastRefRedefExt ( pragma [ only_bind_into ] ( def ) , pragma [ only_bind_into ] ( bb ) ,
680705 pragma [ only_bind_into ] ( i ) , ssaDefinition ( defOrUse ) ) and
681706 def .getSourceVariable ( ) = sv and
682707 defOrUse0 .hasIndexInBlock ( bb , i , sv ) and
@@ -702,7 +727,7 @@ pragma[nomagic]
702727private predicate fromPhiNodeToUse ( PhiNode phi , SourceVariable sv , IRBlock bb1 , int i1 , UseOrPhi use ) {
703728 exists ( IRBlock bb2 , int i2 |
704729 use .asDefOrUse ( ) .hasIndexInBlock ( bb2 , i2 , sv ) and
705- adjacentDefRead ( pragma [ only_bind_into ] ( phi ) , pragma [ only_bind_into ] ( bb1 ) ,
730+ adjacentDefReadExt ( pragma [ only_bind_into ] ( phi ) , pragma [ only_bind_into ] ( bb1 ) ,
706731 pragma [ only_bind_into ] ( i1 ) , pragma [ only_bind_into ] ( bb2 ) , pragma [ only_bind_into ] ( i2 ) )
707732 )
708733}
@@ -711,13 +736,13 @@ private predicate fromPhiNodeToUse(PhiNode phi, SourceVariable sv, IRBlock bb1,
711736predicate fromPhiNode ( SsaPhiNode nodeFrom , Node nodeTo ) {
712737 exists ( PhiNode phi , SourceVariable sv , IRBlock bb1 , int i1 , UseOrPhi use |
713738 phi = nodeFrom .getPhiNode ( ) and
714- phi .definesAt ( sv , bb1 , i1 ) and
739+ phi .definesAt ( sv , bb1 , i1 , _ ) and
715740 useToNode ( use , nodeTo )
716741 |
717742 fromPhiNodeToUse ( phi , sv , bb1 , i1 , use )
718743 or
719744 exists ( PhiNode phiTo |
720- lastRefRedef ( phi , _, _, phiTo ) and
745+ lastRefRedefExt ( phi , _, _, phiTo ) and
721746 nodeTo .( SsaPhiNode ) .getPhiNode ( ) = phiTo
722747 )
723748 )
@@ -796,8 +821,8 @@ module SsaCached {
796821 * path between them without any read of `def`.
797822 */
798823 cached
799- predicate adjacentDefRead ( Definition def , IRBlock bb1 , int i1 , IRBlock bb2 , int i2 ) {
800- SsaImpl:: adjacentDefRead ( def , bb1 , i1 , bb2 , i2 )
824+ predicate adjacentDefReadExt ( DefinitionExt def , IRBlock bb1 , int i1 , IRBlock bb2 , int i2 ) {
825+ SsaImpl:: adjacentDefReadExt ( def , _ , bb1 , i1 , bb2 , i2 )
801826 }
802827
803828 /**
@@ -806,8 +831,8 @@ module SsaCached {
806831 * without passing through another read or write.
807832 */
808833 cached
809- predicate lastRefRedef ( Definition def , IRBlock bb , int i , Definition next ) {
810- SsaImpl:: lastRefRedef ( def , bb , i , next )
834+ predicate lastRefRedefExt ( DefinitionExt def , IRBlock bb , int i , DefinitionExt next ) {
835+ SsaImpl:: lastRefRedefExt ( def , _ , bb , i , next )
811836 }
812837}
813838
@@ -818,8 +843,8 @@ private newtype TSsaDefOrUse =
818843 or
819844 // Like in the pruning stage, we only include definition that's live after the
820845 // write as the final definitions computed by SSA.
821- exists ( Definition def , SourceVariable sv , IRBlock bb , int i |
822- def .definesAt ( sv , bb , i ) and
846+ exists ( DefinitionExt def , SourceVariable sv , IRBlock bb , int i |
847+ def .definesAt ( sv , bb , i , _ ) and
823848 defOrUse .( DefImpl ) .hasIndexInBlock ( bb , i , sv )
824849 )
825850 } or
@@ -967,9 +992,14 @@ class Def extends DefOrUse {
967992
968993private module SsaImpl = SsaImplCommon:: Make< SsaInput > ;
969994
970- class PhiNode = SsaImpl:: PhiNode ;
995+ class PhiNode extends SsaImpl:: DefinitionExt {
996+ PhiNode ( ) {
997+ this instanceof SsaImpl:: PhiNode or
998+ this instanceof SsaImpl:: PhiReadNode
999+ }
1000+ }
9711001
972- class Definition = SsaImpl:: Definition ;
1002+ class DefinitionExt = SsaImpl:: DefinitionExt ;
9731003
9741004class UncertainWriteDefinition = SsaImpl:: UncertainWriteDefinition ;
9751005
0 commit comments