Skip to content

Commit 2963dc1

Browse files
committed
C++: Include phi read nodes in SSA.
There's a small fix to the mapping from 'global def -> use'. Finally, this commit also accepts a test failure related to new missing types for phi nodes. The fix for that is in the next commit.
1 parent b3f92fc commit 2963dc1

File tree

4 files changed

+50
-28
lines changed

4 files changed

+50
-28
lines changed

cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaInternals.qll

Lines changed: 35 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -530,15 +530,15 @@ predicate adjacentDefRead(DefOrUse defOrUse1, UseOrPhi use) {
530530
exists(IRBlock bb1, int i1, SourceVariable v |
531531
defOrUse1.asDefOrUse().hasIndexInBlock(bb1, i1, v)
532532
|
533-
exists(IRBlock bb2, int i2, Definition def |
534-
adjacentDefRead(pragma[only_bind_into](def), pragma[only_bind_into](bb1),
533+
exists(IRBlock bb2, int i2, DefinitionExt def |
534+
adjacentDefReadExt(pragma[only_bind_into](def), pragma[only_bind_into](bb1),
535535
pragma[only_bind_into](i1), pragma[only_bind_into](bb2), pragma[only_bind_into](i2)) and
536536
def.getSourceVariable() = v and
537537
use.asDefOrUse().(UseImpl).hasIndexInBlock(bb2, i2, v)
538538
)
539539
or
540540
exists(PhiNode phi |
541-
lastRefRedef(_, bb1, i1, phi) and
541+
lastRefRedefExt(_, bb1, i1, phi) and
542542
use.asPhi() = phi and
543543
phi.getSourceVariable() = pragma[only_bind_into](v)
544544
)
@@ -550,11 +550,18 @@ predicate adjacentDefRead(DefOrUse defOrUse1, UseOrPhi use) {
550550
* flows to `useOrPhi`.
551551
*/
552552
private predicate globalDefToUse(GlobalDef globalDef, UseOrPhi useOrPhi) {
553-
exists(IRBlock bb1, int i1, IRBlock bb2, int i2, SourceVariable v |
554-
globalDef.hasIndexInBlock(bb1, i1, v) and
555-
adjacentDefRead(_, pragma[only_bind_into](bb1), pragma[only_bind_into](i1),
556-
pragma[only_bind_into](bb2), pragma[only_bind_into](i2)) and
557-
useOrPhi.asDefOrUse().hasIndexInBlock(bb2, i2, v)
553+
exists(IRBlock bb1, int i1, SourceVariable v | globalDef.hasIndexInBlock(bb1, i1, v) |
554+
exists(IRBlock bb2, int i2 |
555+
adjacentDefReadExt(_, pragma[only_bind_into](bb1), pragma[only_bind_into](i1),
556+
pragma[only_bind_into](bb2), pragma[only_bind_into](i2)) and
557+
useOrPhi.asDefOrUse().hasIndexInBlock(bb2, i2, v)
558+
)
559+
or
560+
exists(PhiNode phi |
561+
lastRefRedefExt(_, bb1, i1, phi) and
562+
useOrPhi.asPhi() = phi and
563+
phi.getSourceVariable() = pragma[only_bind_into](v)
564+
)
558565
)
559566
}
560567

@@ -666,17 +673,17 @@ private predicate ssaFlowImpl(SsaDefOrUse defOrUse, Node nodeFrom, Node nodeTo,
666673
* Holds if `def` is the corresponding definition of
667674
* the SSA library's `definition`.
668675
*/
669-
private Definition ssaDefinition(Def def) {
676+
private DefinitionExt ssaDefinition(Def def) {
670677
exists(IRBlock block, int i, SourceVariable sv |
671678
def.hasIndexInBlock(block, i, sv) and
672-
result.definesAt(sv, block, i)
679+
result.definesAt(sv, block, i, _)
673680
)
674681
}
675682

676683
/** Gets a node that represents the prior definition of `node`. */
677684
private Node getAPriorDefinition(SsaDefOrUse defOrUse) {
678-
exists(IRBlock bb, int i, SourceVariable sv, Definition def, DefOrUse defOrUse0 |
679-
SsaCached::lastRefRedef(pragma[only_bind_into](def), pragma[only_bind_into](bb),
685+
exists(IRBlock bb, int i, SourceVariable sv, DefinitionExt def, DefOrUse defOrUse0 |
686+
lastRefRedefExt(pragma[only_bind_into](def), pragma[only_bind_into](bb),
680687
pragma[only_bind_into](i), ssaDefinition(defOrUse)) and
681688
def.getSourceVariable() = sv and
682689
defOrUse0.hasIndexInBlock(bb, i, sv) and
@@ -702,7 +709,7 @@ pragma[nomagic]
702709
private predicate fromPhiNodeToUse(PhiNode phi, SourceVariable sv, IRBlock bb1, int i1, UseOrPhi use) {
703710
exists(IRBlock bb2, int i2 |
704711
use.asDefOrUse().hasIndexInBlock(bb2, i2, sv) and
705-
adjacentDefRead(pragma[only_bind_into](phi), pragma[only_bind_into](bb1),
712+
adjacentDefReadExt(pragma[only_bind_into](phi), pragma[only_bind_into](bb1),
706713
pragma[only_bind_into](i1), pragma[only_bind_into](bb2), pragma[only_bind_into](i2))
707714
)
708715
}
@@ -711,13 +718,13 @@ private predicate fromPhiNodeToUse(PhiNode phi, SourceVariable sv, IRBlock bb1,
711718
predicate fromPhiNode(SsaPhiNode nodeFrom, Node nodeTo) {
712719
exists(PhiNode phi, SourceVariable sv, IRBlock bb1, int i1, UseOrPhi use |
713720
phi = nodeFrom.getPhiNode() and
714-
phi.definesAt(sv, bb1, i1) and
721+
phi.definesAt(sv, bb1, i1, _) and
715722
useToNode(use, nodeTo)
716723
|
717724
fromPhiNodeToUse(phi, sv, bb1, i1, use)
718725
or
719726
exists(PhiNode phiTo |
720-
lastRefRedef(phi, _, _, phiTo) and
727+
lastRefRedefExt(phi, _, _, phiTo) and
721728
nodeTo.(SsaPhiNode).getPhiNode() = phiTo
722729
)
723730
)
@@ -796,8 +803,8 @@ module SsaCached {
796803
* path between them without any read of `def`.
797804
*/
798805
cached
799-
predicate adjacentDefRead(Definition def, IRBlock bb1, int i1, IRBlock bb2, int i2) {
800-
SsaImpl::adjacentDefRead(def, bb1, i1, bb2, i2)
806+
predicate adjacentDefReadExt(DefinitionExt def, IRBlock bb1, int i1, IRBlock bb2, int i2) {
807+
SsaImpl::adjacentDefReadExt(def, _, bb1, i1, bb2, i2)
801808
}
802809

803810
/**
@@ -806,8 +813,8 @@ module SsaCached {
806813
* without passing through another read or write.
807814
*/
808815
cached
809-
predicate lastRefRedef(Definition def, IRBlock bb, int i, Definition next) {
810-
SsaImpl::lastRefRedef(def, bb, i, next)
816+
predicate lastRefRedefExt(DefinitionExt def, IRBlock bb, int i, DefinitionExt next) {
817+
SsaImpl::lastRefRedefExt(def, _, bb, i, next)
811818
}
812819
}
813820

@@ -818,8 +825,8 @@ private newtype TSsaDefOrUse =
818825
or
819826
// Like in the pruning stage, we only include definition that's live after the
820827
// write as the final definitions computed by SSA.
821-
exists(Definition def, SourceVariable sv, IRBlock bb, int i |
822-
def.definesAt(sv, bb, i) and
828+
exists(DefinitionExt def, SourceVariable sv, IRBlock bb, int i |
829+
def.definesAt(sv, bb, i, _) and
823830
defOrUse.(DefImpl).hasIndexInBlock(bb, i, sv)
824831
)
825832
} or
@@ -967,9 +974,14 @@ class Def extends DefOrUse {
967974

968975
private module SsaImpl = SsaImplCommon::Make<SsaInput>;
969976

970-
class PhiNode = SsaImpl::PhiNode;
977+
class PhiNode extends SsaImpl::DefinitionExt {
978+
PhiNode() {
979+
this instanceof SsaImpl::PhiNode or
980+
this instanceof SsaImpl::PhiReadNode
981+
}
982+
}
971983

972-
class Definition = SsaImpl::Definition;
984+
class DefinitionExt = SsaImpl::DefinitionExt;
973985

974986
class UncertainWriteDefinition = SsaImpl::UncertainWriteDefinition;
975987

cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/ssa0/SsaInternals.qll

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -225,8 +225,8 @@ private newtype TSsaDefOrUse =
225225
or
226226
// If `defOrUse` is a definition we only include it if the
227227
// SSA library concludes that it's live after the write.
228-
exists(Definition def, SourceVariable sv, IRBlock bb, int i |
229-
def.definesAt(sv, bb, i) and
228+
exists(DefinitionExt def, SourceVariable sv, IRBlock bb, int i |
229+
def.definesAt(sv, bb, i, _) and
230230
defOrUse.(DefImpl).hasIndexInBlock(bb, i, sv)
231231
)
232232
} or
@@ -301,6 +301,11 @@ class Def extends DefOrUse {
301301

302302
private module SsaImpl = SsaImplCommon::Make<SsaInput>;
303303

304-
class PhiNode = SsaImpl::PhiNode;
304+
class PhiNode extends SsaImpl::DefinitionExt {
305+
PhiNode() {
306+
this instanceof SsaImpl::PhiNode or
307+
this instanceof SsaImpl::PhiReadNode
308+
}
309+
}
305310

306-
class Definition = SsaImpl::Definition;
311+
class DefinitionExt = SsaImpl::DefinitionExt;

cpp/ql/test/library-tests/dataflow/dataflow-tests/test.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -626,5 +626,5 @@ void test_def_via_phi_read(bool b)
626626
use(buffer);
627627
}
628628
intPointerSource(buffer);
629-
sink(buffer); // $ ast MISSING: ir
629+
sink(buffer); // $ ast,ir
630630
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
11
failures
22
astTypeBugs
33
irTypeBugs
4+
| test.cpp:15:3:15:6 | test.cpp:15:3:15:6 | test.cpp:15:3:15:6 | Phi |
5+
| test.cpp:43:10:43:20 | test.cpp:43:10:43:20 | test.cpp:43:10:43:20 | Phi |
6+
| test.cpp:43:10:43:20 | test.cpp:43:10:43:20 | test.cpp:43:10:43:20 | Phi |
7+
| test.cpp:628:3:628:18 | test.cpp:628:3:628:18 | test.cpp:628:3:628:18 | Phi |
8+
| test.cpp:628:3:628:18 | test.cpp:628:3:628:18 | test.cpp:628:3:628:18 | Phi |

0 commit comments

Comments
 (0)