@@ -328,6 +328,126 @@ module Make<LocationSig Location, InputSig<Location> Input> {
328
328
329
329
private class TDefinition = TWriteDef or TPhiNode ;
330
330
331
+ private module SsaDefReachesNew {
332
+ newtype TSsaRefKind =
333
+ SsaActualRead ( ) or
334
+ SsaPhiRead ( ) or
335
+ SsaDef ( )
336
+
337
+ class SsaRead = SsaActualRead or SsaPhiRead ;
338
+
339
+ class SsaDefExt = SsaDef or SsaPhiRead ;
340
+
341
+ SsaDefExt ssaDefExt ( ) { any ( ) }
342
+
343
+ /**
344
+ * A classification of SSA variable references into reads and definitions.
345
+ */
346
+ class SsaRefKind extends TSsaRefKind {
347
+ string toString ( ) {
348
+ this = SsaActualRead ( ) and
349
+ result = "SsaActualRead"
350
+ or
351
+ this = SsaPhiRead ( ) and
352
+ result = "SsaPhiRead"
353
+ or
354
+ this = SsaDef ( ) and
355
+ result = "SsaDef"
356
+ }
357
+
358
+ int getOrder ( ) {
359
+ this instanceof SsaRead and
360
+ result = 0
361
+ or
362
+ this = SsaDef ( ) and
363
+ result = 1
364
+ }
365
+ }
366
+
367
+ /**
368
+ * Holds if the `i`th node of basic block `bb` is a reference to `v`,
369
+ * either a read (when `k` is `SsaActualRead()`), an SSA definition (when `k`
370
+ * is `SsaDef()`), or a phi-read (when `k` is `SsaPhiRead()`).
371
+ *
372
+ * Unlike `Liveness::ref`, this includes `phi` (read) nodes.
373
+ */
374
+ pragma [ nomagic]
375
+ predicate ssaRef ( BasicBlock bb , int i , SourceVariable v , SsaRefKind k ) {
376
+ variableRead ( bb , i , v , _) and
377
+ k = SsaActualRead ( )
378
+ or
379
+ any ( Definition def ) .definesAt ( v , bb , i ) and
380
+ k = SsaDef ( )
381
+ or
382
+ synthPhiRead ( bb , v ) and i = - 1 and k = SsaPhiRead ( )
383
+ }
384
+
385
+ private newtype OrderedSsaRefIndex =
386
+ MkOrderedSsaRefIndex ( int i , SsaRefKind k ) { ssaRef ( _, i , _, k ) }
387
+
388
+ private OrderedSsaRefIndex ssaRefOrd (
389
+ BasicBlock bb , int i , SourceVariable v , SsaRefKind k , int ord
390
+ ) {
391
+ ssaRef ( bb , i , v , k ) and
392
+ result = MkOrderedSsaRefIndex ( i , k ) and
393
+ ord = k .getOrder ( )
394
+ }
395
+
396
+ /**
397
+ * Gets the (1-based) rank of the reference to `v` at the `i`th node of basic
398
+ * block `bb`, which has the given reference kind `k`.
399
+ *
400
+ * For example, if `bb` is a basic block with a phi node for `v` (considered
401
+ * to be at index -1), reads `v` at node 2, and defines it at node 5, we have:
402
+ *
403
+ * ```ql
404
+ * ssaRefRank(bb, -1, v, SsaDef()) = 1 // phi node
405
+ * ssaRefRank(bb, 2, v, Read()) = 2 // read at node 2
406
+ * ssaRefRank(bb, 5, v, SsaDef()) = 3 // definition at node 5
407
+ * ```
408
+ *
409
+ * Reads are considered before writes when they happen at the same index.
410
+ */
411
+ int ssaRefRank ( BasicBlock bb , int i , SourceVariable v , SsaRefKind k ) {
412
+ ssaRefOrd ( bb , i , v , k , _) =
413
+ rank [ result ] ( int j , int ord , OrderedSsaRefIndex res |
414
+ res = ssaRefOrd ( bb , j , v , _, ord )
415
+ |
416
+ res order by j , ord
417
+ )
418
+ }
419
+
420
+ int maxSsaRefRank ( BasicBlock bb , SourceVariable v ) {
421
+ result = ssaRefRank ( bb , _, v , _) and
422
+ not result + 1 = ssaRefRank ( bb , _, v , _)
423
+ }
424
+
425
+ /**
426
+ * Holds if the SSA definition `def` reaches rank index `rnk` in its own
427
+ * basic block `bb`.
428
+ */
429
+ predicate ssaDefReachesRank ( BasicBlock bb , DefinitionExt def , int rnk , SourceVariable v ) {
430
+ exists ( int i |
431
+ rnk = ssaRefRank ( bb , i , v , ssaDefExt ( ) ) and
432
+ def .definesAt ( v , bb , i , _)
433
+ )
434
+ or
435
+ ssaDefReachesRank ( bb , def , rnk - 1 , v ) and
436
+ rnk = ssaRefRank ( bb , _, v , SsaActualRead ( ) )
437
+ }
438
+
439
+ /**
440
+ * Holds if the SSA definition of `v` at `def` reaches index `i` in the same
441
+ * basic block `bb`, without crossing another SSA definition of `v`.
442
+ */
443
+ predicate ssaDefReachesReadWithinBlock ( SourceVariable v , DefinitionExt def , BasicBlock bb , int i ) {
444
+ exists ( int rnk |
445
+ ssaDefReachesRank ( bb , def , rnk , v ) and
446
+ rnk = ssaRefRank ( bb , i , v , SsaActualRead ( ) )
447
+ )
448
+ }
449
+ }
450
+
331
451
private module SsaDefReaches {
332
452
newtype TSsaRefKind =
333
453
SsaActualRead ( ) or
0 commit comments