@@ -252,23 +252,92 @@ private module SsaImplInput implements SsaImplCommon::InputSig<Py::Location, Cfg
252252 }
253253}
254254
255- /**
256- * The shared SSA instantiation for Python.
257- *
258- * Members:
259- * - `Definition` — the union of explicit, uncertain, and phi definitions
260- * - `WriteDefinition`, `UncertainWriteDefinition`, `PhiNode`
261- * - the standard SSA predicates (`getAUse`, `getAnUltimateDefinition`, ...).
262- */
263- module Ssa = SsaImplCommon:: Make< Py:: Location , CfgImpl:: Cfg , SsaImplInput > ;
255+ import SsaImplCommon:: Make< Py:: Location , CfgImpl:: Cfg , SsaImplInput > as Impl
256+
257+ // Matching the cases in `SsaImplInput.variableWrite` above
258+ newtype TVariableWrite =
259+ TName ( CfgImpl:: Ast:: Expr name , SsaSourceVariable v ) {
260+ exists ( Py:: Name n | name .asExpr ( ) = n and n .getVariable ( ) = v .getVariable ( ) |
261+ n .isDefinition ( ) or
262+ n .isDeletion ( )
263+ )
264+ } or
265+ TImportStar ( CfgImpl:: Ast:: Expr i , SsaSourceVariable v ) {
266+ exists ( Py:: ImportStar imp | i .asExpr ( ) = imp .getModuleExpr ( ) |
267+ v .getScope ( ) = imp .getScope ( )
268+ or
269+ exists ( Py:: Name other |
270+ other .uses ( v .getVariable ( ) ) and
271+ imp .getScope ( ) = other .getScope ( )
272+ )
273+ )
274+ }
264275
265- final class Definition = Ssa:: Definition ;
276+ private module SsaInput implements Impl:: SsaInputSig {
277+ // private import java as J
278+ // class Expr = Py::Expr;
279+ class Expr extends CfgImpl:: Ast:: Expr {
280+ CfgImpl:: Cfg:: ControlFlowNode getControlFlowNode ( ) { result .injects ( this ) }
281+ }
282+
283+ class Parameter = CfgImpl:: Ast:: Parameter ;
284+
285+ class VariableWrite extends TVariableWrite {
286+ Expr asExpr ( ) {
287+ this = TName ( result , _)
288+ or
289+ this = TImportStar ( result , _)
290+ }
291+
292+ Expr getValue ( ) {
293+ exists ( CfgImpl:: Ast:: Expr name , Py:: Name n , Cfg:: DefinitionNode def |
294+ this = TName ( name , _) and name .asExpr ( ) = n and def .getNode ( ) = n
295+ |
296+ result .asExpr ( ) = def .getValue ( ) .getNode ( )
297+ )
298+ }
266299
267- final class WriteDefinition = Ssa :: WriteDefinition ;
300+ predicate isParameterInit ( CfgImpl :: Ast :: Parameter p ) { this = TName ( p , _ ) }
268301
269- final class UncertainWriteDefinition = Ssa:: UncertainWriteDefinition ;
302+ string toString ( ) {
303+ exists ( CfgImpl:: Ast:: Expr n | this = TName ( n , _) | result = n .toString ( ) )
304+ or
305+ exists ( CfgImpl:: Ast:: Expr imp | this = TImportStar ( imp , _) | result = imp .toString ( ) )
306+ }
270307
271- final class PhiNode = Ssa:: PhiNode ;
308+ Py:: Location getLocation ( ) {
309+ exists ( CfgImpl:: Ast:: Expr n | this = TName ( n , _) | result = n .getLocation ( ) )
310+ or
311+ exists ( CfgImpl:: Ast:: Expr imp | this = TImportStar ( imp , _) | result = imp .getLocation ( ) )
312+ }
313+
314+ predicate writesAt ( CfgImpl:: BasicBlock bb , int i , SsaSourceVariable v ) {
315+ exists ( CfgImpl:: Ast:: Expr n |
316+ this = TName ( n , v ) and
317+ bb .getNode ( i ) .getAstNode ( ) = n
318+ )
319+ or
320+ exists ( CfgImpl:: Ast:: Expr imp |
321+ this = TImportStar ( imp , v ) and
322+ bb .getNode ( i ) .getAstNode ( ) = imp
323+ )
324+ }
325+ }
326+
327+ predicate explicitWrite ( VariableWrite def , CfgImpl:: Cfg:: BasicBlock bb , int i , SsaSourceVariable v ) {
328+ def .writesAt ( bb , i , v )
329+ }
330+ }
331+
332+ module Ssa = Impl:: MakeSsa< SsaInput > ;
333+
334+ final class Definition = Impl:: Definition ;
335+
336+ final class WriteDefinition = Impl:: WriteDefinition ;
337+
338+ final class UncertainWriteDefinition = Impl:: UncertainWriteDefinition ;
339+
340+ final class PhiNode = Impl:: PhiNode ;
272341
273342// ===========================================================================
274343// ESSA-shaped adapter layer
@@ -294,7 +363,7 @@ final class PhiNode = Ssa::PhiNode;
294363 * (synthesised at position `-1` of a scope's entry BB) this is the
295364 * scope's entry node.
296365 */
297- private Cfg:: ControlFlowNode writeDefNode ( Ssa:: WriteDefinition def ) {
366+ private Cfg:: ControlFlowNode writeDefNode ( Ssa:: SsaWriteDefinition def ) {
298367 exists ( CfgImpl:: BasicBlock bb , int i | def .definesAt ( _, bb , i ) |
299368 i >= 0 and result = bb .getNode ( i )
300369 or
@@ -307,7 +376,7 @@ private Cfg::ControlFlowNode writeDefNode(Ssa::WriteDefinition def) {
307376 * everything that's not a phi node. Mirrors legacy ESSA's
308377 * `EssaNodeDefinition`.
309378 */
310- class EssaNodeDefinition extends Ssa:: WriteDefinition {
379+ class EssaNodeDefinition extends Ssa:: SsaWriteDefinition {
311380 /** Gets the CFG node where this definition's binding takes place. */
312381 Cfg:: ControlFlowNode getDefiningNode ( ) { result = writeDefNode ( this ) }
313382
@@ -451,19 +520,19 @@ class PhiFunction extends PhiNode {
451520 * the phi from one of its predecessor blocks). Mirrors legacy
452521 * ESSA's `PhiFunction.getAnInput()`.
453522 */
454- Ssa:: Definition getAnInput ( ) { Ssa :: phiHasInputFromBlock ( this , result , _) }
523+ Ssa:: SsaDefinition getAnInput ( ) { Impl :: phiHasInputFromBlock ( this , result , _) }
455524}
456525
457526/** Base class for all ESSA definitions (legacy-shaped). */
458- class EssaDefinition = Ssa:: Definition ;
527+ class EssaDefinition = Ssa:: SsaDefinition ;
459528
460529/**
461530 * An adapter representing a single SSA-defined "variable" — wrapping
462531 * one `Ssa::Definition`. Mirrors legacy `EssaVariable` API.
463532 */
464- class EssaVariable extends Ssa:: Definition {
533+ class EssaVariable extends Ssa:: SsaDefinition {
465534 /** Gets the underlying SSA definition (legacy name). */
466- Ssa:: Definition getDefinition ( ) { result = this }
535+ Ssa:: SsaDefinition getDefinition ( ) { result = this }
467536
468537 /**
469538 * Gets a CFG node where this definition is used. Includes regular
@@ -474,7 +543,7 @@ class EssaVariable extends Ssa::Definition {
474543 */
475544 Cfg:: ControlFlowNode getAUse ( ) {
476545 exists ( CfgImpl:: BasicBlock bb , int i |
477- Ssa :: ssaDefReachesRead ( this .getSourceVariable ( ) , this , bb , i ) and
546+ Impl :: ssaDefReachesRead ( this .getSourceVariable ( ) , this . ( Ssa :: SsaWriteDefinition ) , bb , i ) and
478547 bb .getNode ( i ) = result
479548 )
480549 }
@@ -484,17 +553,6 @@ class EssaVariable extends Ssa::Definition {
484553
485554 /** Gets the scope in which this variable lives. */
486555 Py:: Scope getScope ( ) { result = this .getSourceVariable ( ) .getVariable ( ) .getScope ( ) }
487-
488- /** Gets an ultimate non-phi ancestor of this definition. */
489- EssaVariable getAnUltimateDefinition ( ) {
490- if this instanceof PhiNode
491- then
492- exists ( Ssa:: Definition input |
493- Ssa:: phiHasInputFromBlock ( this , input , _) and
494- result = input .( EssaVariable ) .getAnUltimateDefinition ( )
495- )
496- else result = this
497- }
498556}
499557
500558/**
@@ -506,16 +564,16 @@ module AdjacentUses {
506564 /** Holds if `nodeFrom` and `nodeTo` are adjacent uses of the same SSA variable. */
507565 predicate adjacentUseUse ( Cfg:: NameNode nodeFrom , Cfg:: NameNode nodeTo ) {
508566 exists ( SsaSourceVariable v , CfgImpl:: BasicBlock bb1 , int i1 , CfgImpl:: BasicBlock bb2 , int i2 |
509- Ssa :: adjacentUseUse ( bb1 , i1 , bb2 , i2 , v , _) and
567+ Impl :: adjacentUseUse ( bb1 , i1 , bb2 , i2 , v , _) and
510568 nodeFrom = bb1 .getNode ( i1 ) and
511569 nodeTo = bb2 .getNode ( i2 )
512570 )
513571 }
514572
515573 /** Holds if `use` is a first use of definition `def`. */
516- predicate firstUse ( Ssa:: Definition def , Cfg:: NameNode use ) {
574+ predicate firstUse ( Ssa:: SsaDefinition def , Cfg:: NameNode use ) {
517575 exists ( CfgImpl:: BasicBlock bb , int i |
518- Ssa :: firstUse ( def , bb , i , _) and
576+ Impl :: firstUse ( def , bb , i , _) and
519577 use = bb .getNode ( i )
520578 )
521579 }
@@ -524,7 +582,7 @@ module AdjacentUses {
524582 * Holds if `use` is any reachable use of definition `def`. Combines
525583 * `firstUse` with transitive use-use adjacency.
526584 */
527- predicate useOfDef ( Ssa:: Definition def , Cfg:: NameNode use ) {
585+ predicate useOfDef ( Ssa:: SsaDefinition def , Cfg:: NameNode use ) {
528586 firstUse ( def , use )
529587 or
530588 exists ( Cfg:: NameNode mid | useOfDef ( def , mid ) and adjacentUseUse ( mid , use ) )
0 commit comments