Skip to content

Commit 393512f

Browse files
committed
C++: Implement a pruning version of 'getAnUltimateDefinition'.
1 parent e9caa4e commit 393512f

2 files changed

Lines changed: 79 additions & 7 deletions

File tree

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1018,4 +1018,6 @@ module Ssa {
10181018
class IndirectExplicitDefinition = SsaImpl::IndirectExplicitDefinition;
10191019

10201020
class PhiNode = SsaImpl::PhiNode;
1021+
1022+
import SsaImpl::Public
10211023
}

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

Lines changed: 77 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1405,14 +1405,80 @@ private class PhiCycle extends PhiCycleEquivalence::EquivalenceClass {
14051405
}
14061406
}
14071407

1408-
/** An static single assignment (SSA) definition. */
1409-
class Definition extends SsaImpl::Definition {
1410-
private Definition getAPhiInputOrPriorDefinition() {
1411-
result = this.(PhiNode).getAnInput()
1412-
or
1413-
uncertainWriteDefinitionInput(this, result)
1408+
private Definition getAPhiInputOrPriorDefinition(Definition def) {
1409+
result = def.(PhiNode).getAnInput()
1410+
or
1411+
uncertainWriteDefinitionInput(def, result)
1412+
}
1413+
1414+
module Public {
1415+
/**
1416+
* A module signature to define relevant ultimate definitions for an
1417+
* optimized version of `Definition.getAnUltimateDefinition`.
1418+
*/
1419+
signature module GetAnUltimateDefinitionSig {
1420+
/**
1421+
* Holds if `def` is a relevant definition. This defines the set
1422+
* of `Definition`s which may be returned by
1423+
* `GetAnUltimateDefinition::getAnUltimateDefinition`.
1424+
*/
1425+
predicate isRelevantUltimateDefinition(Definition def);
1426+
}
1427+
1428+
/**
1429+
* A module which constructs an optimized version of
1430+
* ```
1431+
* Definition.getAnUltimateDefinition
1432+
* ```
1433+
* by restricting the set of possible ultimate definitions.
1434+
*
1435+
* Use this module by defining a module `M` which implements
1436+
* `GetAnUltimateDefinitionSig` and then call:
1437+
* ```
1438+
* GetAnUltimateDefinition<M>::getAnUltimateDefinition
1439+
* ```
1440+
*/
1441+
module GetAnUltimateDefinition<GetAnUltimateDefinitionSig Sig> {
1442+
private import Sig
1443+
1444+
private predicate relevantUltimateDefinition(Definition def) {
1445+
isRelevantUltimateDefinition(def) and
1446+
not def instanceof PhiNode
1447+
}
1448+
1449+
private predicate fwd(Definition def) {
1450+
relevantUltimateDefinition(def)
1451+
or
1452+
exists(Definition def0 |
1453+
fwd(def0) and
1454+
def0 = getAPhiInputOrPriorDefinition(def)
1455+
)
1456+
}
1457+
1458+
private predicate step(Definition def1, Definition def2) {
1459+
fwd(def1) and
1460+
fwd(def2) and
1461+
def1 = getAPhiInputOrPriorDefinition(def2)
1462+
}
1463+
1464+
/**
1465+
* Gets a definition that ultimately defines this SSA definition and is
1466+
* not itself a phi node.
1467+
*
1468+
* This predicate is restricted to ultimate definitions which
1469+
* satisfy `isRelevantUltimateDefinition`.
1470+
*/
1471+
Definition getAnUltimateDefinition(Definition def) {
1472+
step*(result, def) and
1473+
relevantUltimateDefinition(result)
1474+
}
14141475
}
1476+
}
14151477

1478+
import Public
1479+
1480+
/** An static single assignment (SSA) definition. */
1481+
class Definition extends SsaImpl::Definition {
14161482
/**
14171483
* Holds if this SSA definition is live at the end of basic block `bb`.
14181484
* That is, this definition reaches the end of basic block `bb`, at which
@@ -1424,9 +1490,13 @@ class Definition extends SsaImpl::Definition {
14241490
/**
14251491
* Gets a definition that ultimately defines this SSA definition and is
14261492
* not itself a phi node.
1493+
*
1494+
* Note: A more efficient implementation of this predicate exists. See the
1495+
* `GetAnUltimateDefinition` module for a description of how to access
1496+
* the more efficient implementation.
14271497
*/
14281498
final Definition getAnUltimateDefinition() {
1429-
result = this.getAPhiInputOrPriorDefinition*() and
1499+
result = getAPhiInputOrPriorDefinition*(this) and
14301500
not result instanceof PhiNode
14311501
}
14321502

0 commit comments

Comments
 (0)