@@ -192,7 +192,7 @@ class OperandNode extends Node, TOperandNode {
192192FieldNode getFieldNodeForFieldInstruction ( Instruction instr ) {
193193 result .getFieldInstruction ( ) =
194194 any ( FieldAddressInstruction fai |
195- instructionOperandLocalFlowStep * ( instructionNode ( fai ) , instructionNode ( instr ) )
195+ longestRegisterInstructionOperandLocalFlowStep ( instructionNode ( fai ) , instructionNode ( instr ) )
196196 )
197197}
198198
@@ -251,13 +251,19 @@ class FieldNode extends Node, TFieldNode {
251251/**
252252 * INTERNAL: do not use. A partial definition of a `FieldNode`.
253253 */
254- class PartialFieldDefinition extends PartialDefinition {
255- override FieldNode node ;
256-
257- override FieldNode getPreUpdateNode ( ) { result = node }
254+ class PartialFieldDefinition extends FieldNode , PartialDefinition {
255+ /**
256+ * The pre-update node of a partial definition of a `FieldNode` is the `FieldNode` itself. This ensures
257+ * that the data flow library's reverse read mechanism builds up the correct access path for nested
258+ * fields.
259+ * For instance, in `a.b.c = x` there is a partial definition for `c` (let's call it `post[c]`) and a
260+ * partial definition for `b` (let's call it `post[b]`), and there is a read step from `b` to `c`
261+ * (using `instrToFieldNodeReadStep`), so there is a store step from `post[c]` to `post[b]`.
262+ */
263+ override FieldNode getPreUpdateNode ( ) { result = this }
258264
259265 override Expr getDefinedExpr ( ) {
260- result = node .getFieldInstruction ( ) .getObjectAddress ( ) .getUnconvertedResultExpression ( )
266+ result = this .getFieldInstruction ( ) .getObjectAddress ( ) .getUnconvertedResultExpression ( )
261267 }
262268}
263269
@@ -411,39 +417,13 @@ abstract class PostUpdateNode extends Node {
411417 override Location getLocation ( ) { result = getPreUpdateNode ( ) .getLocation ( ) }
412418}
413419
414- /**
415- * A partial definition of a node. A partial definition that targets arrays or pointers is attached to
416- * an `InstructionNode` (specifially, to the `ChiInstruction` that follows the `StoreInstruction`), and
417- * a partial definition that targets a `FieldNode` is attached to the `FieldNode`.
418- *
419- * The pre-update node of a partial definition of a `FieldNode` is the `FieldNode` itself. This ensures
420- * that the data flow library's reverse read mechanism builds up the correct access path for nested
421- * fields.
422- * For instance, in `a.b.c = x` there is a partial definition for `c` (let's call it `post[c]`) and a
423- * partial definition for `b` (let's call it `post[b]`), and there is a read step from `b` to `c`
424- * (using `instrToFieldNodeReadStep`), so there is a store step from `post[c]` to `post[b]`.
425- */
426- private newtype TPartialDefinition =
427- MkPartialDefinition ( Node node ) {
428- isPointerStoreNode ( node , _, _) or
429- isArrayStoreNode ( node , _, _) or
430- node instanceof FieldNode
431- }
432-
433420/** INTERNAL: do not use. A partial definition of a node. */
434- abstract class PartialDefinition extends TPartialDefinition {
435- Node node ;
436-
437- PartialDefinition ( ) { this = MkPartialDefinition ( node ) }
438-
421+ abstract class PartialDefinition extends Node {
439422 /** Gets the node before the state update. */
440423 abstract Node getPreUpdateNode ( ) ;
441424
442425 /** Gets the expression that is partially defined by this node. */
443426 abstract Expr getDefinedExpr ( ) ;
444-
445- /** Gets a string representation of this partial definition. */
446- string toString ( ) { result = node .toString ( ) + " [partial definition]" }
447427}
448428
449429/**
@@ -475,52 +455,44 @@ class PartialDefinitionNode extends PostUpdateNode, TPartialDefinitionNode {
475455 override string toString ( ) { result = getPreUpdateNode ( ) .toString ( ) + " [post update]" }
476456}
477457
478- private predicate isArrayStoreNode (
479- InstructionNode node , ChiInstruction chi , PointerAddInstruction add
480- ) {
481- chi = node .getInstruction ( ) and
482- not chi .isResultConflated ( ) and
483- exists ( StoreInstruction store |
484- chi .getPartial ( ) = store and
485- add = store .getDestinationAddress ( )
486- )
487- }
488-
489458/**
490459 * The `PostUpdateNode` that is the target of a `arrayStoreStepChi` store step. The overriden
491460 * `ChiInstruction` corresponds to the instruction represented by `node2` in `arrayStoreStepChi`.
492461 */
493- private class ArrayStoreNode extends PartialDefinition {
494- override InstructionNode node ;
462+ private class ArrayStoreNode extends InstructionNode , PartialDefinition {
495463 ChiInstruction chi ;
496464 PointerAddInstruction add ;
497465
498- ArrayStoreNode ( ) { isArrayStoreNode ( node , chi , add ) }
466+ ArrayStoreNode ( ) {
467+ chi = this .getInstruction ( ) and
468+ not chi .isResultConflated ( ) and
469+ exists ( StoreInstruction store |
470+ chi .getPartial ( ) = store and
471+ add = store .getDestinationAddress ( )
472+ )
473+ }
499474
500475 override Node getPreUpdateNode ( ) { result .asOperand ( ) = chi .getTotalOperand ( ) }
501476
502477 override Expr getDefinedExpr ( ) { result = add .getLeft ( ) .getUnconvertedResultExpression ( ) }
503478}
504479
505- private predicate isPointerStoreNode ( InstructionNode node , ChiInstruction chi , LoadInstruction load ) {
506- chi = node .getInstruction ( ) and
507- not chi .isResultConflated ( ) and
508- exists ( StoreInstruction store |
509- chi .getPartial ( ) = store and
510- load = store .getDestinationAddress ( ) .( CopyValueInstruction ) .getUnary ( )
511- )
512- }
513-
514480/**
515481 * The `PostUpdateNode` that is the target of a `arrayStoreStepChi` store step. The overriden
516482 * `ChiInstruction` corresponds to the instruction represented by `node2` in `arrayStoreStepChi`.
517483 */
518- private class PointerStoreNode extends PartialDefinition {
519- override InstructionNode node ;
484+ private class PointerStoreNode extends InstructionNode , PartialDefinition {
520485 ChiInstruction chi ;
521486 LoadInstruction load ;
522487
523- PointerStoreNode ( ) { isPointerStoreNode ( node , chi , load ) }
488+ PointerStoreNode ( ) {
489+ chi = this .getInstruction ( ) and
490+ not chi .isResultConflated ( ) and
491+ exists ( StoreInstruction store |
492+ chi .getPartial ( ) = store and
493+ load = store .getDestinationAddress ( ) .( CopyValueInstruction ) .getUnary ( )
494+ )
495+ }
524496
525497 override Node getPreUpdateNode ( ) { result .asOperand ( ) = chi .getTotalOperand ( ) }
526498
@@ -734,12 +706,40 @@ private predicate flowIntoReadNode(Node nodeFrom, FieldNode nodeTo) {
734706 )
735707}
736708
709+ /** Holds if `node` holds an `Instruction` or `Operand` that has a register result. */
710+ private predicate hasRegisterResult ( Node node ) {
711+ node .asOperand ( ) instanceof RegisterOperand
712+ or
713+ exists ( Instruction i | i = node .asInstruction ( ) and not i .hasMemoryResult ( ) )
714+ }
715+
716+ /**
717+ * Holds if there is a `Instruction` or `Operand` flow step from `nodeFrom` to `nodeTo` and both
718+ * `nodeFrom` and `nodeTo` wraps register results.
719+ */
720+ private predicate registerInstructionOperandLocalFlowStep ( Node nodeFrom , Node nodeTo ) {
721+ hasRegisterResult ( nodeFrom ) and
722+ hasRegisterResult ( nodeTo ) and
723+ instructionOperandLocalFlowStep ( nodeFrom , nodeTo )
724+ }
725+
726+ /**
727+ * INTERNAL: do not use.
728+ * Holds if `nodeFrom` has no incoming local `Operand` or `Instruction` register flow and `nodeFrom` can
729+ * reach `nodeTo` using only local `Instruction` or `Operand` register flow steps.
730+ */
731+ bindingset [ nodeTo]
732+ private predicate longestRegisterInstructionOperandLocalFlowStep ( Node nodeFrom , Node nodeTo ) {
733+ registerInstructionOperandLocalFlowStep * ( nodeFrom , nodeTo ) and
734+ not registerInstructionOperandLocalFlowStep ( _, nodeFrom )
735+ }
736+
737737/**
738738 * INTERNAL: do not use.
739739 * Holds if `nodeFrom` is an operand and `nodeTo` is an instruction node that uses this operand, or
740740 * if `nodeFrom` is an instruction and `nodeTo` is an operand that refers to this instruction.
741741 */
742- predicate instructionOperandLocalFlowStep ( Node nodeFrom , Node nodeTo ) {
742+ private predicate instructionOperandLocalFlowStep ( Node nodeFrom , Node nodeTo ) {
743743 // Operand -> Instruction flow
744744 simpleInstructionLocalFlowStep ( nodeFrom .asOperand ( ) , nodeTo .asInstruction ( ) )
745745 or
0 commit comments