Skip to content

Commit 613323e

Browse files
committed
SSA: Copy parts of SsaDefReaches verbatim to new module.
1 parent 81b3035 commit 613323e

File tree

1 file changed

+120
-0
lines changed

1 file changed

+120
-0
lines changed

shared/ssa/codeql/ssa/Ssa.qll

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,126 @@ module Make<LocationSig Location, InputSig<Location> Input> {
328328

329329
private class TDefinition = TWriteDef or TPhiNode;
330330

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+
331451
private module SsaDefReaches {
332452
newtype TSsaRefKind =
333453
SsaActualRead() or

0 commit comments

Comments
 (0)