C++: Use local flow instead of GVN to find parameters that are used in switch statements.

This commit is contained in:
Mathias Vorreiter Pedersen
2023-03-15 10:00:47 +00:00
parent d96dbea7be
commit deb43c21e6

View File

@@ -897,6 +897,55 @@ IRBlock getBasicBlock(Node node) {
result = getBasicBlock(node.(PostUpdateNode).getPreUpdateNode())
}
/**
* A local flow relation that includes both local steps, read steps and
* argument-to-return flow through summarized functions.
*/
private predicate localFlowStepWithSummaries(Node node1, Node node2) {
localFlowStep(node1, node2)
or
readStep(node1, _, node2)
or
argumentValueFlowsThrough(node1, _, node2)
}
/** Holds if `node` flows to a node that is used in a `SwitchInstruction`. */
private predicate localStepsToSwitch(Node node) {
node.asOperand() = any(SwitchInstruction switch).getExpressionOperand()
or
exists(Node succ |
localStepsToSwitch(succ) and
localFlowStepWithSummaries(node, succ)
)
}
/**
* Holds if `node` is part of a path from a `ParameterNode` to an operand
* of a `SwitchInstruction`.
*/
private predicate localStepsFromParameter(Node node) {
localStepsToSwitch(node) and
(
node instanceof ParameterNode
or
exists(Node prev |
localStepsFromParameter(prev) and
localFlowStepWithSummaries(prev, node)
)
)
}
/**
* The local flow relation `localFlowStepWithSummaries` pruned to only
* include steps that are part of a path from a `ParameterNode` to an
* operand of a `SwitchInstruction`.
*/
private predicate getAdditionalFlowIntoCallNodeTermStep(Node node1, Node node2) {
localStepsFromParameter(node1) and
localStepsFromParameter(node2) and
localFlowStepWithSummaries(node1, node2)
}
/**
* Gets an additional term that is added to the `join` and `branch` computations to reflect
* an additional forward or backwards branching factor that is not taken into account
@@ -910,7 +959,7 @@ int getAdditionalFlowIntoCallNodeTerm(ArgumentNode arg, ParameterNode p) {
viableParamArg(call, p, arg) and
viableParamArg(call, switchee, _) and
switch.getExpressionOperand() = op and
valueNumber(switchee.asInstruction()).getAUse() = op and
getAdditionalFlowIntoCallNodeTermStep+(switchee, operandNode(op)) and
result = countNumberOfBranchesUsingParameter(switch, p)
)
}