@@ -291,23 +291,27 @@ predicate outNodeHasAddressAndIndex(
291291 out .getIndirectionIndex ( ) = indirectionIndex
292292}
293293
294- private predicate defToNode ( Node nodeFrom , Def def ) {
295- nodeHasOperand ( nodeFrom , def .getValue ( ) .asOperand ( ) , def .getIndirectionIndex ( ) )
296- or
297- nodeHasInstruction ( nodeFrom , def .getValue ( ) .asInstruction ( ) , def .getIndirectionIndex ( ) )
294+ private predicate defToNode ( Node nodeFrom , Def def , boolean uncertain ) {
295+ (
296+ nodeHasOperand ( nodeFrom , def .getValue ( ) .asOperand ( ) , def .getIndirectionIndex ( ) )
297+ or
298+ nodeHasInstruction ( nodeFrom , def .getValue ( ) .asInstruction ( ) , def .getIndirectionIndex ( ) )
299+ ) and
300+ if def .isCertain ( ) then uncertain = false else uncertain = true
298301}
299302
300303/**
301304 * INTERNAL: Do not use.
302305 *
303306 * Holds if `nodeFrom` is the node that correspond to the definition or use `defOrUse`.
304307 */
305- predicate nodeToDefOrUse ( Node nodeFrom , SsaDefOrUse defOrUse ) {
308+ predicate nodeToDefOrUse ( Node nodeFrom , SsaDefOrUse defOrUse , boolean uncertain ) {
306309 // Node -> Def
307- defToNode ( nodeFrom , defOrUse )
310+ defToNode ( nodeFrom , defOrUse , uncertain )
308311 or
309312 // Node -> Use
310- useToNode ( defOrUse , nodeFrom )
313+ useToNode ( defOrUse , nodeFrom ) and
314+ uncertain = false
311315}
312316
313317/**
@@ -316,7 +320,7 @@ predicate nodeToDefOrUse(Node nodeFrom, SsaDefOrUse defOrUse) {
316320 */
317321private predicate indirectConversionFlowStep ( Node nFrom , Node nTo ) {
318322 not exists ( UseOrPhi defOrUse |
319- nodeToDefOrUse ( nTo , defOrUse ) and
323+ nodeToDefOrUse ( nTo , defOrUse , _ ) and
320324 adjacentDefRead ( defOrUse , _)
321325 ) and
322326 exists ( Operand op1 , Operand op2 , int indirectionIndex , Instruction instr |
@@ -342,31 +346,60 @@ private predicate indirectConversionFlowStep(Node nFrom, Node nTo) {
342346 * So this predicate recurses back along conversions and `PointerArithmeticInstruction`s to find the
343347 * first use that has provides use-use flow, and uses that target as the target of the `nodeFrom`.
344348 */
345- private predicate adjustForPointerArith ( Node nodeFrom , UseOrPhi use ) {
349+ private predicate adjustForPointerArith ( Node nodeFrom , UseOrPhi use , boolean uncertain ) {
346350 nodeFrom = any ( PostUpdateNode pun ) .getPreUpdateNode ( ) and
347351 exists ( DefOrUse defOrUse , Node adjusted |
348352 indirectConversionFlowStep * ( adjusted , nodeFrom ) and
349- nodeToDefOrUse ( adjusted , defOrUse ) and
353+ nodeToDefOrUse ( adjusted , defOrUse , uncertain ) and
350354 adjacentDefRead ( defOrUse , use )
351355 )
352356}
353357
354- /** Holds if there is def-use or use-use flow from `nodeFrom` to `nodeTo`. */
355- predicate ssaFlow ( Node nodeFrom , Node nodeTo ) {
358+ private predicate ssaFlowImpl ( Node nodeFrom , Node nodeTo , boolean uncertain ) {
356359 // `nodeFrom = any(PostUpdateNode pun).getPreUpdateNode()` is implied by adjustedForPointerArith.
357360 exists ( UseOrPhi use |
358- adjustForPointerArith ( nodeFrom , use ) and
361+ adjustForPointerArith ( nodeFrom , use , uncertain ) and
359362 useToNode ( use , nodeTo )
360363 )
361364 or
362365 not nodeFrom = any ( PostUpdateNode pun ) .getPreUpdateNode ( ) and
363366 exists ( DefOrUse defOrUse1 , UseOrPhi use |
364- nodeToDefOrUse ( nodeFrom , defOrUse1 ) and
367+ nodeToDefOrUse ( nodeFrom , defOrUse1 , uncertain ) and
365368 adjacentDefRead ( defOrUse1 , use ) and
366369 useToNode ( use , nodeTo )
367370 )
368371}
369372
373+ /**
374+ * Holds if `def` is the corresponding definition of
375+ * the SSA library's `definition`.
376+ */
377+ private predicate ssaDefinition ( Def def , Definition definition ) {
378+ exists ( IRBlock block , int i , SourceVariable sv |
379+ def .hasIndexInBlock ( block , i , sv ) and
380+ definition .definesAt ( sv , block , i )
381+ )
382+ }
383+
384+ /** Gets a node that represents the prior definition of `node`. */
385+ private Node getAPriorDefinition ( Node node ) {
386+ exists ( Def def , Definition definition , Definition inp , Def input |
387+ defToNode ( node , def , true ) and
388+ ssaDefinition ( def , definition ) and
389+ uncertainWriteDefinitionInput ( pragma [ only_bind_into ] ( definition ) , pragma [ only_bind_into ] ( inp ) ) and
390+ ssaDefinition ( input , inp ) and
391+ defToNode ( result , input , _)
392+ )
393+ }
394+
395+ /** Holds if there is def-use or use-use flow from `nodeFrom` to `nodeTo`. */
396+ predicate ssaFlow ( Node nodeFrom , Node nodeTo ) {
397+ exists ( Node nFrom , boolean uncertain |
398+ ssaFlowImpl ( nFrom , nodeTo , uncertain ) and
399+ if uncertain = true then nodeFrom = [ nFrom , getAPriorDefinition ( nFrom ) ] else nodeFrom = nFrom
400+ )
401+ }
402+
370403/**
371404 * Holds if `use` is a use of `sv` and is a next adjacent use of `phi` in
372405 * index `i1` in basic block `bb1`.
@@ -460,6 +493,11 @@ module SsaCached {
460493 predicate lastRefRedef ( Definition def , IRBlock bb , int i , Definition next ) {
461494 SsaImpl:: lastRefRedef ( def , bb , i , next )
462495 }
496+
497+ cached
498+ predicate uncertainWriteDefinitionInput ( SsaImpl:: UncertainWriteDefinition def , Definition inp ) {
499+ SsaImpl:: uncertainWriteDefinitionInput ( def , inp )
500+ }
463501}
464502
465503cached
@@ -498,6 +536,10 @@ class DefOrUse extends TDefOrUse, SsaDefOrUse {
498536 final SourceVariable getSourceVariable ( ) { result = defOrUse .getSourceVariable ( ) }
499537
500538 override string toString ( ) { result = defOrUse .toString ( ) }
539+
540+ predicate hasIndexInBlock ( IRBlock block , int index , SourceVariable sv ) {
541+ defOrUse .hasIndexInBlock ( block , index , sv )
542+ }
501543}
502544
503545class Phi extends TPhi , SsaDefOrUse {
@@ -541,6 +583,8 @@ class Def extends DefOrUse {
541583 }
542584
543585 Node0Impl getValue ( ) { result = defOrUse .getValue ( ) }
586+
587+ predicate isCertain ( ) { defOrUse .isCertain ( ) }
544588}
545589
546590private module SsaImpl = SsaImplCommon:: Make< SsaInput > ;
@@ -549,4 +593,6 @@ class PhiNode = SsaImpl::PhiNode;
549593
550594class Definition = SsaImpl:: Definition ;
551595
596+ class UncertainWriteDefinition = SsaImpl:: UncertainWriteDefinition ;
597+
552598import SsaCached
0 commit comments