@@ -459,6 +459,92 @@ class ByteSliceType extends SliceType {
459459 ByteSliceType ( ) { this .getElementType ( ) instanceof Uint8Type }
460460}
461461
462+ // Improve efficiency of matching a struct to its unaliased equivalent
463+ // by unpacking the first 5 fields and tags, allowing a single join
464+ // to strongly constrain the available candidates.
465+ private predicate hasComponentTypeAndTag ( StructType s , int i , string name , Type tp , string tag ) {
466+ component_types ( s , i , name , tp ) and component_tags ( s , i , tag )
467+ }
468+
469+ private newtype TOptStructComponent =
470+ MkNoComponent ( ) or
471+ MkSomeComponent ( string name , Type tp , string tag ) { hasComponentTypeAndTag ( _, _, name , tp , tag ) }
472+
473+ private class OptStructComponent extends TOptStructComponent {
474+ OptStructComponent getWithDeepUnaliasedType ( ) {
475+ this = MkNoComponent ( ) and result = MkNoComponent ( )
476+ or
477+ exists ( string name , Type tp , string tag |
478+ this = MkSomeComponent ( name , tp , tag ) and
479+ result = MkSomeComponent ( name , tp .getDeepUnaliasedType ( ) , tag )
480+ )
481+ }
482+
483+ string toString ( ) { result = "struct component" }
484+ }
485+
486+ private class StructComponent extends MkSomeComponent {
487+ string toString ( ) { result = "struct component" }
488+
489+ predicate isComponentOf ( StructType s , int i ) {
490+ exists ( string name , Type tp , string tag |
491+ hasComponentTypeAndTag ( s , i , name , tp , tag ) and
492+ this = MkSomeComponent ( name , tp , tag )
493+ )
494+ }
495+ }
496+
497+ pragma [ nomagic]
498+ predicate unpackStructType (
499+ StructType s , TOptStructComponent c0 , TOptStructComponent c1 , TOptStructComponent c2 ,
500+ TOptStructComponent c3 , TOptStructComponent c4 , int nComponents
501+ ) {
502+ nComponents = count ( int i | component_types ( s , i , _, _) ) and
503+ (
504+ if nComponents >= 1
505+ then c0 = any ( StructComponent sc | sc .isComponentOf ( s , 0 ) )
506+ else c0 = MkNoComponent ( )
507+ ) and
508+ (
509+ if nComponents >= 2
510+ then c1 = any ( StructComponent sc | sc .isComponentOf ( s , 1 ) )
511+ else c1 = MkNoComponent ( )
512+ ) and
513+ (
514+ if nComponents >= 3
515+ then c2 = any ( StructComponent sc | sc .isComponentOf ( s , 2 ) )
516+ else c2 = MkNoComponent ( )
517+ ) and
518+ (
519+ if nComponents >= 4
520+ then c3 = any ( StructComponent sc | sc .isComponentOf ( s , 3 ) )
521+ else c3 = MkNoComponent ( )
522+ ) and
523+ (
524+ if nComponents >= 5
525+ then c4 = any ( StructComponent sc | sc .isComponentOf ( s , 4 ) )
526+ else c4 = MkNoComponent ( )
527+ )
528+ }
529+
530+ pragma [ nomagic]
531+ predicate unpackAndUnaliasStructType (
532+ StructType s , TOptStructComponent c0 , TOptStructComponent c1 , TOptStructComponent c2 ,
533+ TOptStructComponent c3 , TOptStructComponent c4 , int nComponents
534+ ) {
535+ exists (
536+ OptStructComponent c0a , OptStructComponent c1a , OptStructComponent c2a , OptStructComponent c3a ,
537+ OptStructComponent c4a
538+ |
539+ unpackStructType ( s , c0a , c1a , c2a , c3a , c4a , nComponents ) and
540+ c0 = c0a .getWithDeepUnaliasedType ( ) and
541+ c1 = c1a .getWithDeepUnaliasedType ( ) and
542+ c2 = c2a .getWithDeepUnaliasedType ( ) and
543+ c3 = c3a .getWithDeepUnaliasedType ( ) and
544+ c4 = c4a .getWithDeepUnaliasedType ( )
545+ )
546+ }
547+
462548/** A struct type. */
463549class StructType extends @structtype, CompositeType {
464550 /**
@@ -598,29 +684,36 @@ class StructType extends @structtype, CompositeType {
598684 )
599685 }
600686
601- private predicate hasComponentTypeAndTag ( int i , string name , Type tp , string tag ) {
602- component_types ( this , i , name , tp ) and component_tags ( this , i , tag )
687+ private StructType getDeepUnaliasedTypeCandidate ( ) {
688+ exists (
689+ OptStructComponent c0 , OptStructComponent c1 , OptStructComponent c2 , OptStructComponent c3 ,
690+ OptStructComponent c4 , int nComponents
691+ |
692+ unpackAndUnaliasStructType ( this , c0 , c1 , c2 , c3 , c4 , nComponents ) and
693+ unpackStructType ( result , c0 , c1 , c2 , c3 , c4 , nComponents )
694+ )
603695 }
604696
605697 private predicate isDeepUnaliasedTypeUpTo ( StructType unaliased , int i ) {
606698 // Note we must use component_types not hasOwnField here because component_types may specify
607699 // interface-in-struct embedding, but hasOwnField does not return such members.
700+ unaliased = this .getDeepUnaliasedTypeCandidate ( ) and
701+ i >= 5 and
608702 (
609- i = 0 or
703+ i = 5 or
610704 this .isDeepUnaliasedTypeUpTo ( unaliased , i - 1 )
611705 ) and
612- exists ( string name , Type tp , string tag | this . hasComponentTypeAndTag ( i , name , tp , tag ) |
613- unaliased . hasComponentTypeAndTag ( i , name , tp .getDeepUnaliasedType ( ) , tag )
706+ exists ( string name , Type tp , string tag | hasComponentTypeAndTag ( this , i , name , tp , tag ) |
707+ hasComponentTypeAndTag ( unaliased , i , name , tp .getDeepUnaliasedType ( ) , tag )
614708 )
615709 }
616710
617711 override StructType getDeepUnaliasedType ( ) {
712+ result = this .getDeepUnaliasedTypeCandidate ( ) and
618713 exists ( int nComponents | nComponents = count ( int i | component_types ( this , i , _, _) ) |
619- (
620- this .isDeepUnaliasedTypeUpTo ( result , nComponents - 1 )
621- or
622- nComponents = 0 and result = this
623- )
714+ this .isDeepUnaliasedTypeUpTo ( result , nComponents - 1 )
715+ or
716+ nComponents <= 5
624717 )
625718 }
626719
@@ -961,11 +1054,14 @@ class TupleType extends @tupletype, CompositeType {
9611054 }
9621055
9631056 override TupleType getDeepUnaliasedType ( ) {
964- exists ( int nComponents | nComponents = count ( int i | exists ( this .getComponentType ( i ) ) ) |
1057+ exists ( int nComponents |
1058+ nComponents = count ( int i | exists ( this .getComponentType ( i ) ) ) and
1059+ nComponents = count ( int i | exists ( result .getComponentType ( i ) ) )
1060+ |
9651061 this .isDeepUnaliasedTypeUpTo ( result , nComponents - 1 )
9661062 or
9671063 // I don't think Go allows empty tuples in any context, but this is at least harmless.
968- nComponents = 0 and result = this
1064+ nComponents = 0
9691065 )
9701066 }
9711067
@@ -978,6 +1074,68 @@ class TupleType extends @tupletype, CompositeType {
9781074 override string toString ( ) { result = "tuple type" }
9791075}
9801076
1077+ // Reasonably efficiently map from a signature type to its
1078+ // deep-unaliased equivalent, by using a single join for the leading 5 parameters
1079+ // and/or 3 results.
1080+ private newtype TOptType =
1081+ MkNoType ( ) or
1082+ MkSomeType ( Type tp )
1083+
1084+ private class OptType extends TOptType {
1085+ OptType getDeepUnaliasedType ( ) {
1086+ exists ( Type t | this = MkSomeType ( t ) | result = MkSomeType ( t .getDeepUnaliasedType ( ) ) )
1087+ or
1088+ this = MkNoType ( ) and result = MkNoType ( )
1089+ }
1090+
1091+ string toString ( ) {
1092+ exists ( Type t | this = MkSomeType ( t ) | result = t .toString ( ) )
1093+ or
1094+ this = MkNoType ( ) and result = "no type"
1095+ }
1096+ }
1097+
1098+ pragma [ nomagic]
1099+ private predicate unpackSignatureType (
1100+ SignatureType sig , OptType param0 , OptType param1 , OptType param2 , OptType param3 , OptType param4 ,
1101+ int nParams , OptType result0 , OptType result1 , OptType result2 , int nResults , boolean isVariadic
1102+ ) {
1103+ nParams = sig .getNumParameter ( ) and
1104+ nResults = sig .getNumResult ( ) and
1105+ ( if nParams >= 1 then param0 = MkSomeType ( sig .getParameterType ( 0 ) ) else param0 = MkNoType ( ) ) and
1106+ ( if nParams >= 2 then param1 = MkSomeType ( sig .getParameterType ( 1 ) ) else param1 = MkNoType ( ) ) and
1107+ ( if nParams >= 3 then param2 = MkSomeType ( sig .getParameterType ( 2 ) ) else param2 = MkNoType ( ) ) and
1108+ ( if nParams >= 4 then param3 = MkSomeType ( sig .getParameterType ( 3 ) ) else param3 = MkNoType ( ) ) and
1109+ ( if nParams >= 5 then param4 = MkSomeType ( sig .getParameterType ( 4 ) ) else param4 = MkNoType ( ) ) and
1110+ ( if nResults >= 1 then result0 = MkSomeType ( sig .getResultType ( 0 ) ) else result0 = MkNoType ( ) ) and
1111+ ( if nResults >= 2 then result1 = MkSomeType ( sig .getResultType ( 1 ) ) else result1 = MkNoType ( ) ) and
1112+ ( if nResults >= 3 then result2 = MkSomeType ( sig .getResultType ( 2 ) ) else result2 = MkNoType ( ) ) and
1113+ ( if sig .isVariadic ( ) then isVariadic = true else isVariadic = false )
1114+ }
1115+
1116+ pragma [ nomagic]
1117+ private predicate unpackAndUnaliasSignatureType (
1118+ SignatureType sig , OptType param0 , OptType param1 , OptType param2 , OptType param3 , OptType param4 ,
1119+ int nParams , OptType result0 , OptType result1 , OptType result2 , int nResults , boolean isVariadic
1120+ ) {
1121+ exists (
1122+ OptType param0a , OptType param1a , OptType param2a , OptType param3a , OptType param4a ,
1123+ OptType result0a , OptType result1a , OptType result2a
1124+ |
1125+ unpackSignatureType ( sig , param0a , param1a , param2a , param3a , param4a , nParams , result0a ,
1126+ result1a , result2a , nResults , isVariadic )
1127+ |
1128+ param0 = param0a .getDeepUnaliasedType ( ) and
1129+ param1 = param1a .getDeepUnaliasedType ( ) and
1130+ param2 = param2a .getDeepUnaliasedType ( ) and
1131+ param3 = param3a .getDeepUnaliasedType ( ) and
1132+ param4 = param4a .getDeepUnaliasedType ( ) and
1133+ result0 = result0a .getDeepUnaliasedType ( ) and
1134+ result1 = result1a .getDeepUnaliasedType ( ) and
1135+ result2 = result2a .getDeepUnaliasedType ( )
1136+ )
1137+ }
1138+
9811139/** A signature type. */
9821140class SignatureType extends @signaturetype, CompositeType {
9831141 /** Gets the `i`th parameter type of this signature type. */
@@ -995,31 +1153,48 @@ class SignatureType extends @signaturetype, CompositeType {
9951153 /** Holds if this signature type is variadic. */
9961154 predicate isVariadic ( ) { variadic ( this ) }
9971155
1156+ private SignatureType getDeepUnaliasedTypeCandidate ( ) {
1157+ exists (
1158+ OptType param0 , OptType param1 , OptType param2 , OptType param3 , OptType param4 , int nParams ,
1159+ OptType result0 , OptType result1 , OptType result2 , int nResults , boolean isVariadic
1160+ |
1161+ unpackAndUnaliasSignatureType ( this , param0 , param1 , param2 , param3 , param4 , nParams , result0 ,
1162+ result1 , result2 , nResults , isVariadic ) and
1163+ unpackSignatureType ( result , param0 , param1 , param2 , param3 , param4 , nParams , result0 , result1 ,
1164+ result2 , nResults , isVariadic )
1165+ )
1166+ }
1167+
1168+ // These incremental recursive implementations only apply from parameter 5 or result 3
1169+ // upwards to avoid constructing large squares of candidates -- the initial parameters
1170+ // and results are taken care of by the candidate predicate.
9981171 private predicate hasDeepUnaliasedParameterTypesUpTo ( SignatureType unaliased , int i ) {
999- ( i = 0 or this .hasDeepUnaliasedParameterTypesUpTo ( unaliased , i - 1 ) ) and
1172+ unaliased = this .getDeepUnaliasedTypeCandidate ( ) and
1173+ i >= 5 and
1174+ ( i = 5 or this .hasDeepUnaliasedParameterTypesUpTo ( unaliased , i - 1 ) ) and
10001175 unaliased .getParameterType ( i ) = this .getParameterType ( i ) .getDeepUnaliasedType ( )
10011176 }
10021177
10031178 private predicate hasDeepUnaliasedResultTypesUpTo ( SignatureType unaliased , int i ) {
1004- ( i = 0 or this .hasDeepUnaliasedResultTypesUpTo ( unaliased , i - 1 ) ) and
1179+ unaliased = this .getDeepUnaliasedTypeCandidate ( ) and
1180+ i >= 3 and
1181+ ( i = 3 or this .hasDeepUnaliasedResultTypesUpTo ( unaliased , i - 1 ) ) and
10051182 unaliased .getResultType ( i ) = this .getResultType ( i ) .getDeepUnaliasedType ( )
10061183 }
10071184
10081185 override SignatureType getDeepUnaliasedType ( ) {
1009- exists ( int nParams | nParams = this .getNumParameter ( ) |
1010- nParams = 0 and result .getNumParameter ( ) = 0
1011- or
1012- this .hasDeepUnaliasedParameterTypesUpTo ( result , nParams - 1 )
1013- ) and
1014- exists ( int nResults | nResults = this .getNumResult ( ) |
1015- nResults = 0 and result .getNumResult ( ) = 0
1016- or
1017- this .hasDeepUnaliasedResultTypesUpTo ( result , nResults - 1 )
1018- ) and
1019- (
1020- this .isVariadic ( ) and result .isVariadic ( )
1021- or
1022- not this .isVariadic ( ) and not result .isVariadic ( )
1186+ result = this .getDeepUnaliasedTypeCandidate ( ) and
1187+ exists ( int nParams , int nResults |
1188+ this .getNumParameter ( ) = nParams and this .getNumResult ( ) = nResults
1189+ |
1190+ (
1191+ nParams <= 5
1192+ or
1193+ this .hasDeepUnaliasedParameterTypesUpTo ( result , nParams - 1 ) and
1194+ nResults <= 3
1195+ or
1196+ this .hasDeepUnaliasedResultTypesUpTo ( result , nResults - 1 )
1197+ )
10231198 )
10241199 }
10251200
0 commit comments