Skip to content

Commit 411aff6

Browse files
committed
SSA: Refactor ranking into parameterised module.
1 parent 11166fc commit 411aff6

File tree

1 file changed

+65
-113
lines changed

1 file changed

+65
-113
lines changed

shared/ssa/codeql/ssa/Ssa.qll

Lines changed: 65 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -114,43 +114,41 @@ module Make<LocationSig Location, InputSig<Location> Input> {
114114
}
115115

116116
/**
117-
* Liveness analysis (based on source variables) to restrict the size of the
118-
* SSA representation.
117+
* A classification of variable references into reads and
118+
* (certain or uncertain) writes / definitions.
119119
*/
120-
private module Liveness {
121-
/**
122-
* A classification of variable references into reads (of a given kind) and
123-
* (certain or uncertain) writes.
124-
*/
125-
private newtype TRefKind =
126-
Read() or
127-
Write(boolean certain) { certain in [false, true] }
128-
129-
private class RefKind extends TRefKind {
130-
string toString() {
131-
this = Read() and result = "read"
132-
or
133-
exists(boolean certain | this = Write(certain) and result = "write (" + certain + ")")
134-
}
135-
136-
int getOrder() {
137-
this = Read() and
138-
result = 0
139-
or
140-
this = Write(_) and
141-
result = 1
142-
}
120+
private newtype TRefKind =
121+
Read() or
122+
Write(boolean certain) { certain in [false, true] } or
123+
Def()
124+
125+
private class RefKind extends TRefKind {
126+
string toString() {
127+
this = Read() and result = "read"
128+
or
129+
exists(boolean certain | this = Write(certain) and result = "write (" + certain + ")")
130+
or
131+
this = Def() and result = "def"
143132
}
144133

145-
/**
146-
* Holds if the `i`th node of basic block `bb` is a reference to `v` of kind `k`.
147-
*/
148-
predicate ref(BasicBlock bb, int i, SourceVariable v, RefKind k) {
149-
variableRead(bb, i, v, _) and k = Read()
134+
int getOrder() {
135+
this = Read() and
136+
result = 0
150137
or
151-
exists(boolean certain | variableWrite(bb, i, v, certain) | k = Write(certain))
138+
this = Write(_) and
139+
result = 1
140+
or
141+
this = Def() and
142+
result = 1
152143
}
144+
}
153145

146+
/**
147+
* Holds if the `i`th node of basic block `bb` is a reference to `v` of kind `k`.
148+
*/
149+
private signature predicate refSig(BasicBlock bb, int i, SourceVariable v, RefKind k);
150+
151+
private module RankRefs<refSig/4 ref> {
154152
private newtype OrderedRefIndex =
155153
MkOrderedRefIndex(int i, int tag) {
156154
exists(RefKind rk | ref(_, i, _, rk) | tag = rk.getOrder())
@@ -168,7 +166,7 @@ module Make<LocationSig Location, InputSig<Location> Input> {
168166
*
169167
* Reads are considered before writes when they happen at the same index.
170168
*/
171-
private int refRank(BasicBlock bb, int i, SourceVariable v, RefKind k) {
169+
int refRank(BasicBlock bb, int i, SourceVariable v, RefKind k) {
172170
refOrd(bb, i, v, k, _) =
173171
rank[result](int j, int ord, OrderedRefIndex res |
174172
res = refOrd(bb, j, v, _, ord)
@@ -177,10 +175,27 @@ module Make<LocationSig Location, InputSig<Location> Input> {
177175
)
178176
}
179177

180-
private int maxRefRank(BasicBlock bb, SourceVariable v) {
178+
int maxRefRank(BasicBlock bb, SourceVariable v) {
181179
result = refRank(bb, _, v, _) and
182180
not result + 1 = refRank(bb, _, v, _)
183181
}
182+
}
183+
184+
/**
185+
* Liveness analysis (based on source variables) to restrict the size of the
186+
* SSA representation.
187+
*/
188+
private module Liveness {
189+
/**
190+
* Holds if the `i`th node of basic block `bb` is a reference to `v` of kind `k`.
191+
*/
192+
predicate varRef(BasicBlock bb, int i, SourceVariable v, RefKind k) {
193+
variableRead(bb, i, v, _) and k = Read()
194+
or
195+
exists(boolean certain | variableWrite(bb, i, v, certain) | k = Write(certain))
196+
}
197+
198+
private import RankRefs<varRef/4>
184199

185200
/**
186201
* Gets the (1-based) rank of the first reference to `v` inside basic block `bb`
@@ -295,7 +310,7 @@ module Make<LocationSig Location, InputSig<Location> Input> {
295310
not variableWrite(readbb, _, v, _)
296311
or
297312
synthPhiRead(readbb, v) and
298-
not ref(readbb, _, v, _)
313+
not varRef(readbb, _, v, _)
299314
)
300315
}
301316

@@ -329,103 +344,40 @@ module Make<LocationSig Location, InputSig<Location> Input> {
329344
private class TDefinition = TWriteDef or TPhiNode;
330345

331346
private module SsaDefReachesNew {
332-
newtype TSsaRefKind =
333-
SsaActualRead() or
334-
SsaDef()
335-
336-
/**
337-
* A classification of SSA variable references into reads and definitions.
338-
*/
339-
class SsaRefKind extends TSsaRefKind {
340-
string toString() {
341-
this = SsaActualRead() and
342-
result = "SsaActualRead"
343-
or
344-
this = SsaDef() and
345-
result = "SsaDef"
346-
}
347-
348-
int getOrder() {
349-
this = SsaActualRead() and
350-
result = 0
351-
or
352-
this = SsaDef() and
353-
result = 1
354-
}
355-
}
356-
357347
/**
358348
* Holds if the `i`th node of basic block `bb` is a reference to `v`,
359-
* either a read (when `k` is `SsaActualRead()`) or an SSA definition (when
360-
* `k` is `SsaDef()`).
349+
* either a read (when `k` is `Read()`) or an SSA definition (when
350+
* `k` is `Def()`).
361351
*
362-
* Unlike `Liveness::ref`, this includes `phi` nodes and pseudo-reads
352+
* Unlike `Liveness::varRef`, this includes `phi` nodes and pseudo-reads
363353
* associated with uncertain writes.
364354
*/
365355
pragma[nomagic]
366-
predicate ssaRef(BasicBlock bb, int i, SourceVariable v, SsaRefKind k) {
356+
predicate ssaRef(BasicBlock bb, int i, SourceVariable v, RefKind k) {
367357
variableRead(bb, i, v, _) and
368-
k = SsaActualRead()
358+
k = Read()
369359
or
370360
variableWrite(bb, i, v, false) and
371-
k = SsaActualRead()
361+
k = Read()
372362
or
373363
any(Definition def).definesAt(v, bb, i) and
374-
k = SsaDef()
375-
}
376-
377-
private newtype OrderedSsaRefIndex =
378-
MkOrderedSsaRefIndex(int i, SsaRefKind k) { ssaRef(_, i, _, k) }
379-
380-
private OrderedSsaRefIndex ssaRefOrd(
381-
BasicBlock bb, int i, SourceVariable v, SsaRefKind k, int ord
382-
) {
383-
ssaRef(bb, i, v, k) and
384-
result = MkOrderedSsaRefIndex(i, k) and
385-
ord = k.getOrder()
386-
}
387-
388-
/**
389-
* Gets the (1-based) rank of the reference to `v` at the `i`th node of basic
390-
* block `bb`, which has the given reference kind `k`.
391-
*
392-
* For example, if `bb` is a basic block with a phi node for `v` (considered
393-
* to be at index -1), reads `v` at node 2, and defines it at node 5, we have:
394-
*
395-
* ```ql
396-
* ssaRefRank(bb, -1, v, SsaDef()) = 1 // phi node
397-
* ssaRefRank(bb, 2, v, Read()) = 2 // read at node 2
398-
* ssaRefRank(bb, 5, v, SsaDef()) = 3 // definition at node 5
399-
* ```
400-
*
401-
* Reads are considered before writes when they happen at the same index.
402-
*/
403-
int ssaRefRank(BasicBlock bb, int i, SourceVariable v, SsaRefKind k) {
404-
ssaRefOrd(bb, i, v, k, _) =
405-
rank[result](int j, int ord, OrderedSsaRefIndex res |
406-
res = ssaRefOrd(bb, j, v, _, ord)
407-
|
408-
res order by j, ord
409-
)
364+
k = Def()
410365
}
411366

412-
int maxSsaRefRank(BasicBlock bb, SourceVariable v) {
413-
result = ssaRefRank(bb, _, v, _) and
414-
not result + 1 = ssaRefRank(bb, _, v, _)
415-
}
367+
private import RankRefs<ssaRef/4>
416368

417369
/**
418370
* Holds if the SSA definition `def` reaches rank index `rnk` in its own
419371
* basic block `bb`.
420372
*/
421373
predicate ssaDefReachesRank(BasicBlock bb, Definition def, int rnk, SourceVariable v) {
422374
exists(int i |
423-
rnk = ssaRefRank(bb, i, v, SsaDef()) and
375+
rnk = refRank(bb, i, v, Def()) and
424376
def.definesAt(v, bb, i)
425377
)
426378
or
427379
ssaDefReachesRank(bb, def, rnk - 1, v) and
428-
rnk = ssaRefRank(bb, _, v, SsaActualRead())
380+
rnk = refRank(bb, _, v, Read())
429381
}
430382

431383
/**
@@ -436,7 +388,7 @@ module Make<LocationSig Location, InputSig<Location> Input> {
436388
private predicate liveThrough(BasicBlock idom, BasicBlock bb, SourceVariable v) {
437389
idom = getImmediateBasicBlockDominator(bb) and
438390
liveAtExit(bb, v) and
439-
not ssaRef(bb, _, v, SsaDef())
391+
not ssaRef(bb, _, v, Def())
440392
}
441393

442394
/**
@@ -447,7 +399,7 @@ module Make<LocationSig Location, InputSig<Location> Input> {
447399
pragma[nomagic]
448400
predicate ssaDefReachesEndOfBlock(BasicBlock bb, Definition def, SourceVariable v) {
449401
exists(int last |
450-
last = maxSsaRefRank(pragma[only_bind_into](bb), pragma[only_bind_into](v)) and
402+
last = maxRefRank(pragma[only_bind_into](bb), pragma[only_bind_into](v)) and
451403
ssaDefReachesRank(bb, def, last, v) and
452404
liveAtExit(bb, v)
453405
)
@@ -471,7 +423,7 @@ module Make<LocationSig Location, InputSig<Location> Input> {
471423
predicate ssaDefReachesReadWithinBlock(SourceVariable v, Definition def, BasicBlock bb, int i) {
472424
exists(int rnk |
473425
ssaDefReachesRank(bb, def, rnk, v) and
474-
rnk = ssaRefRank(bb, i, v, SsaActualRead())
426+
rnk = refRank(bb, i, v, Read())
475427
)
476428
}
477429

@@ -483,7 +435,7 @@ module Make<LocationSig Location, InputSig<Location> Input> {
483435
predicate ssaDefReachesRead(SourceVariable v, Definition def, BasicBlock bb, int i) {
484436
ssaDefReachesReadWithinBlock(v, def, bb, i)
485437
or
486-
ssaRef(bb, i, v, SsaActualRead()) and
438+
ssaRef(bb, i, v, Read()) and
487439
ssaDefReachesEndOfBlock(getImmediateBasicBlockDominator(bb), def, v) and
488440
not ssaDefReachesReadWithinBlock(v, _, bb, i)
489441
}
@@ -537,7 +489,7 @@ module Make<LocationSig Location, InputSig<Location> Input> {
537489
* either a read (when `k` is `SsaActualRead()`), an SSA definition (when `k`
538490
* is `SsaDef()`), or a phi-read (when `k` is `SsaPhiRead()`).
539491
*
540-
* Unlike `Liveness::ref`, this includes `phi` (read) nodes.
492+
* Unlike `Liveness::varRef`, this includes `phi` (read) nodes.
541493
*/
542494
pragma[nomagic]
543495
predicate ssaRef(BasicBlock bb, int i, SourceVariable v, SsaRefKind k) {
@@ -697,7 +649,7 @@ module Make<LocationSig Location, InputSig<Location> Input> {
697649
exists(SourceVariable v |
698650
varBlockReachesExt(pragma[only_bind_into](def), v, bb1, pragma[only_bind_into](bb2)) and
699651
phi.definesAt(v, bb2, _, _) and
700-
not ref(bb2, _, v, _)
652+
not varRef(bb2, _, v, _)
701653
)
702654
}
703655

0 commit comments

Comments
 (0)