Skip to content

Commit cfaa2d8

Browse files
authored
Merge pull request #15152 from MathiasVP/fix-unnecessary-evaluation-of-debug-strings
C++: Fix unnecessary evaluation of debug strings
2 parents 2305d55 + 95cd31f commit cfaa2d8

File tree

7 files changed

+127
-123
lines changed

7 files changed

+127
-123
lines changed

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

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,41 @@ private module Cached {
5959
import Cached
6060
private import Nodes0
6161

62+
/**
63+
* A module for calculating the number of stars (i.e., `*`s) needed for various
64+
* dataflow node `toString` predicates.
65+
*/
66+
module NodeStars {
67+
private int getNumberOfIndirections(Node n) {
68+
result = n.(RawIndirectOperand).getIndirectionIndex()
69+
or
70+
result = n.(RawIndirectInstruction).getIndirectionIndex()
71+
or
72+
result = n.(VariableNode).getIndirectionIndex()
73+
or
74+
result = n.(PostUpdateNodeImpl).getIndirectionIndex()
75+
or
76+
result = n.(FinalParameterNode).getIndirectionIndex()
77+
}
78+
79+
private int maxNumberOfIndirections() { result = max(getNumberOfIndirections(_)) }
80+
81+
private string repeatStars(int n) {
82+
n = 0 and result = ""
83+
or
84+
n = [1 .. maxNumberOfIndirections()] and
85+
result = "*" + repeatStars(n - 1)
86+
}
87+
88+
/**
89+
* Gets the number of stars (i.e., `*`s) needed to produce the `toString`
90+
* output for `n`.
91+
*/
92+
string stars(Node n) { result = repeatStars(getNumberOfIndirections(n)) }
93+
}
94+
95+
import NodeStars
96+
6297
class Node0Impl extends TIRDataFlowNode0 {
6398
/**
6499
* INTERNAL: Do not use.

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

Lines changed: 4 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -486,47 +486,6 @@ class Node extends TIRDataFlowNode {
486486
}
487487
}
488488

489-
private string toExprString(Node n) {
490-
not isDebugMode() and
491-
(
492-
result = n.asExpr(0).toString()
493-
or
494-
not exists(n.asExpr()) and
495-
result = stars(n) + n.asIndirectExpr(0, 1).toString()
496-
)
497-
}
498-
499-
private module NodeStars {
500-
private int getNumberOfIndirections(Node n) {
501-
result = n.(RawIndirectOperand).getIndirectionIndex()
502-
or
503-
result = n.(RawIndirectInstruction).getIndirectionIndex()
504-
or
505-
result = n.(VariableNode).getIndirectionIndex()
506-
or
507-
result = n.(PostUpdateNodeImpl).getIndirectionIndex()
508-
or
509-
result = n.(FinalParameterNode).getIndirectionIndex()
510-
}
511-
512-
private int maxNumberOfIndirections() { result = max(getNumberOfIndirections(_)) }
513-
514-
private string repeatStars(int n) {
515-
n = 0 and result = ""
516-
or
517-
n = [1 .. maxNumberOfIndirections()] and
518-
result = "*" + repeatStars(n - 1)
519-
}
520-
521-
/**
522-
* Gets the number of stars (i.e., `*`s) needed to produce the `toString`
523-
* output for `n`.
524-
*/
525-
string stars(Node n) { result = repeatStars(getNumberOfIndirections(n)) }
526-
}
527-
528-
private import NodeStars
529-
530489
/**
531490
* A class that lifts pre-SSA dataflow nodes to regular dataflow nodes.
532491
*/
@@ -589,7 +548,10 @@ Type stripPointer(Type t) {
589548
result = t.(FunctionPointerIshType).getBaseType()
590549
}
591550

592-
private class PostUpdateNodeImpl extends PartialDefinitionNode, TPostUpdateNodeImpl {
551+
/**
552+
* INTERNAL: Do not use.
553+
*/
554+
class PostUpdateNodeImpl extends PartialDefinitionNode, TPostUpdateNodeImpl {
593555
int indirectionIndex;
594556
Operand operand;
595557

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,24 @@
11
/**
2-
* This file activates debugging mode for dataflow node printing.
2+
* This file contains the class that implements the _debug_ version of
3+
* `toString` for `Instruction` and `Operand` dataflow nodes.
34
*/
45

6+
private import semmle.code.cpp.ir.IR
7+
private import codeql.util.Unit
58
private import Node0ToString
9+
private import DataFlowUtil
610

711
private class DebugNode0ToString extends Node0ToString {
8-
final override predicate isDebugMode() { any() }
12+
DebugNode0ToString() {
13+
// Silence warning about `this` not being bound.
14+
exists(this)
15+
}
16+
17+
override string instructionToString(Instruction i) { result = i.getDumpString() }
18+
19+
override string operandToString(Operand op) {
20+
result = op.getDumpString() + " @ " + op.getUse().getResultId()
21+
}
22+
23+
override string toExprString(Node n) { none() }
924
}
Lines changed: 30 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,75 +1,53 @@
11
/**
2-
* This file contains the abstract class that serves as the base class for
3-
* dataflow node printing.
2+
* This file imports the class that is used to construct the strings used by
3+
* `Node.ToString`.
44
*
5-
* By default, a non-debug string is produced. However, a debug-friendly
6-
* string can be produced by importing `DebugPrinting.qll`.
5+
* Normally, this file should just import `NormalNode0ToString` to compute the
6+
* efficient `toString`, but for debugging purposes one can import
7+
* `DebugPrinting.qll` to better correlate the dataflow nodes with their
8+
* underlying instructions and operands.
79
*/
810

911
private import semmle.code.cpp.ir.IR
1012
private import codeql.util.Unit
13+
private import DataFlowUtil
14+
import NormalNode0ToString // Change this import to control which version should be used.
1115

12-
/**
13-
* A class to control whether a debugging version of instructions and operands
14-
* should be printed as part of the `toString` output of dataflow nodes.
15-
*
16-
* To enable debug printing import the `DebugPrinting.ql` file. By default,
17-
* non-debug output will be used.
18-
*/
19-
class Node0ToString extends Unit {
20-
abstract predicate isDebugMode();
21-
22-
private string normalInstructionToString(Instruction i) {
23-
not this.isDebugMode() and
24-
if i.(InitializeParameterInstruction).getIRVariable() instanceof IRThisVariable
25-
then result = "this"
26-
else result = i.getAst().toString()
27-
}
28-
29-
private string normalOperandToString(Operand op) {
30-
not this.isDebugMode() and
31-
if op.getDef().(InitializeParameterInstruction).getIRVariable() instanceof IRThisVariable
32-
then result = "this"
33-
else result = op.getDef().getAst().toString()
34-
}
35-
16+
/** An abstract class to control the behavior of `Node.toString`. */
17+
abstract class Node0ToString extends Unit {
3618
/**
37-
* Gets the string that should be used by `InstructionNode.toString`
19+
* Gets the string that should be used by `OperandNode.toString` to print the
20+
* dataflow node whose underlying operand is `op.`
3821
*/
39-
string instructionToString(Instruction i) {
40-
if this.isDebugMode()
41-
then result = i.getDumpString()
42-
else result = this.normalInstructionToString(i)
43-
}
22+
abstract string operandToString(Operand op);
4423

4524
/**
46-
* Gets the string that should be used by `OperandNode.toString`.
25+
* Gets the string that should be used by `InstructionNode.toString` to print
26+
* the dataflow node whose underlying instruction is `instr`.
4727
*/
48-
string operandToString(Operand op) {
49-
if this.isDebugMode()
50-
then result = op.getDumpString() + " @ " + op.getUse().getResultId()
51-
else result = this.normalOperandToString(op)
52-
}
53-
}
28+
abstract string instructionToString(Instruction i);
5429

55-
private class NoDebugNode0ToString extends Node0ToString {
56-
final override predicate isDebugMode() { none() }
30+
/**
31+
* Gets the string representation of the `Expr` associated with `n`, if any.
32+
*/
33+
abstract string toExprString(Node n);
5734
}
5835

5936
/**
60-
* Gets the string that should be used by `OperandNode.toString`.
37+
* Gets the string that should be used by `OperandNode.toString` to print the
38+
* dataflow node whose underlying operand is `op.`
6139
*/
62-
string operandToString(Operand op) { result = any(Node0ToString nts).operandToString(op) }
40+
string operandToString(Operand op) { result = any(Node0ToString s).operandToString(op) }
6341

6442
/**
65-
* Gets the string that should be used by `InstructionNode.toString`
43+
* Gets the string that should be used by `InstructionNode.toString` to print
44+
* the dataflow node whose underlying instruction is `instr`.
6645
*/
67-
string instructionToString(Instruction i) { result = any(Node0ToString nts).instructionToString(i) }
46+
string instructionToString(Instruction instr) {
47+
result = any(Node0ToString s).instructionToString(instr)
48+
}
6849

6950
/**
70-
* Holds if debugging mode is enabled.
71-
*
72-
* In debug mode the `toString` on dataflow nodes is more expensive to compute,
73-
* but gives more precise information about the different dataflow nodes.
51+
* Gets the string representation of the `Expr` associated with `n`, if any.
7452
*/
75-
predicate isDebugMode() { any(Node0ToString nts).isDebugMode() }
53+
string toExprString(Node n) { result = any(Node0ToString s).toExprString(n) }
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/**
2+
* This file contains the class that implements the non-debug version of
3+
* `toString` for `Instruction` and `Operand` dataflow nodes.
4+
*/
5+
6+
private import semmle.code.cpp.ir.IR
7+
private import codeql.util.Unit
8+
private import Node0ToString
9+
private import DataFlowUtil
10+
private import DataFlowPrivate
11+
12+
private class NormalNode0ToString extends Node0ToString {
13+
NormalNode0ToString() {
14+
// Silence warning about `this` not being bound.
15+
exists(this)
16+
}
17+
18+
override string instructionToString(Instruction i) {
19+
if i.(InitializeParameterInstruction).getIRVariable() instanceof IRThisVariable
20+
then result = "this"
21+
else result = i.getAst().toString()
22+
}
23+
24+
override string operandToString(Operand op) {
25+
if op.getDef().(InitializeParameterInstruction).getIRVariable() instanceof IRThisVariable
26+
then result = "this"
27+
else result = op.getDef().getAst().toString()
28+
}
29+
30+
override string toExprString(Node n) {
31+
result = n.asExpr(0).toString()
32+
or
33+
not exists(n.asExpr()) and
34+
result = stars(n) + n.asIndirectExpr(0, 1).toString()
35+
}
36+
}

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
private import cpp
22
private import semmle.code.cpp.ir.IR
33
private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil
4+
private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate
45
private import SsaInternals as Ssa
56
private import PrintIRUtilities
67

@@ -33,9 +34,9 @@ private string getNodeProperty(Node node, string key) {
3334
key = "flow" and
3435
result =
3536
strictconcat(string flow, boolean to, int order1, int order2 |
36-
flow = getFromFlow(node, order1, order2) + "->" + starsForNode(node) + "@" and to = false
37+
flow = getFromFlow(node, order1, order2) + "->" + stars(node) + "@" and to = false
3738
or
38-
flow = starsForNode(node) + "@->" + getToFlow(node, order1, order2) and to = true
39+
flow = stars(node) + "@->" + getToFlow(node, order1, order2) and to = true
3940
|
4041
flow, ", " order by to, order1, order2, flow
4142
)

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

Lines changed: 2 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -7,37 +7,14 @@ private import semmle.code.cpp.ir.IR
77
private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil
88
private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate
99

10-
private string stars(int k) {
11-
k =
12-
[0 .. max([
13-
any(RawIndirectInstruction n).getIndirectionIndex(),
14-
any(RawIndirectOperand n).getIndirectionIndex()
15-
]
16-
)] and
17-
(if k = 0 then result = "" else result = "*" + stars(k - 1))
18-
}
19-
20-
string starsForNode(Node node) {
21-
exists(int indirectionIndex |
22-
node.(IndirectInstruction).hasInstructionAndIndirectionIndex(_, indirectionIndex) or
23-
node.(IndirectOperand).hasOperandAndIndirectionIndex(_, indirectionIndex)
24-
|
25-
result = stars(indirectionIndex)
26-
)
27-
or
28-
not node instanceof IndirectInstruction and
29-
not node instanceof IndirectOperand and
30-
result = ""
31-
}
32-
3310
private Instruction getInstruction(Node n, string stars) {
3411
result = [n.asInstruction(), n.(RawIndirectInstruction).getInstruction()] and
35-
stars = starsForNode(n)
12+
stars = stars(n)
3613
}
3714

3815
private Operand getOperand(Node n, string stars) {
3916
result = [n.asOperand(), n.(RawIndirectOperand).getOperand()] and
40-
stars = starsForNode(n)
17+
stars = stars(n)
4118
}
4219

4320
/**

0 commit comments

Comments
 (0)