Skip to content

Commit 32db922

Browse files
committed
C++: Remove some unnecessary IPA values from 'IndirectInstruction' and 'IndirectOperand' when the semantically identical value already exists in the IR.
1 parent 0d27d63 commit 32db922

File tree

12 files changed

+291
-263
lines changed

12 files changed

+291
-263
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ private module VirtualDispatch {
143143
private class DataSensitiveExprCall extends DataSensitiveCall {
144144
DataSensitiveExprCall() { not exists(this.getStaticCallTarget()) }
145145

146-
override DataFlow::Node getDispatchValue() { result.asInstruction() = this.getCallTarget() }
146+
override DataFlow::Node getDispatchValue() { result.asOperand() = this.getCallTargetOperand() }
147147

148148
override Function resolve() {
149149
exists(FunctionInstruction fi |

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

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -47,24 +47,6 @@ private class PrimaryArgumentNode extends ArgumentNode, OperandNode {
4747
override predicate argumentOf(DataFlowCall call, ArgumentPosition pos) {
4848
op = call.getArgumentOperand(pos.(DirectPosition).getIndex())
4949
}
50-
51-
override string toStringImpl() { result = argumentOperandToString(op) }
52-
}
53-
54-
private string argumentOperandToString(ArgumentOperand op) {
55-
exists(Expr unconverted |
56-
unconverted = op.getDef().getUnconvertedResultExpression() and
57-
result = unconverted.toString()
58-
)
59-
or
60-
// Certain instructions don't map to an unconverted result expression. For these cases
61-
// we fall back to a simpler naming scheme. This can happen in IR-generated constructors.
62-
not exists(op.getDef().getUnconvertedResultExpression()) and
63-
(
64-
result = "Argument " + op.(PositionalArgumentOperand).getIndex()
65-
or
66-
op instanceof ThisArgumentOperand and result = "Argument this"
67-
)
6850
}
6951

7052
private class SideEffectArgumentNode extends ArgumentNode, SideEffectOperandNode {
@@ -73,10 +55,6 @@ private class SideEffectArgumentNode extends ArgumentNode, SideEffectOperandNode
7355
pos.(IndirectionPosition).getArgumentIndex() = this.getArgumentIndex() and
7456
pos.(IndirectionPosition).getIndirectionIndex() = super.getIndirectionIndex()
7557
}
76-
77-
override string toStringImpl() {
78-
result = argumentOperandToString(this.getAddressOperand()) + " indirection"
79-
}
8058
}
8159

8260
/** A parameter position represented by an integer. */

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

Lines changed: 83 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ private module Cached {
2626
* - `SsaPhiNode`, which represents phi nodes as computed by the shared SSA library.
2727
* - `IndirectArgumentOutNode`, which represents the value of an argument (and its indirections) after
2828
* it leaves a function call.
29-
* - `IndirectOperand`, which represents the value of `operand` after loading the address a number
29+
* - `RawIndirectOperand`, which represents the value of `operand` after loading the address a number
3030
* of times.
31-
* - `IndirectInstruction`, which represents the value of `instr` after loading the address a number
31+
* - `RawIndirectInstruction`, which represents the value of `instr` after loading the address a number
3232
* of times.
3333
*/
3434
cached
@@ -52,11 +52,11 @@ private module Cached {
5252
Ssa::isModifiableByCall(operand) and
5353
indirectionIndex = [1 .. Ssa::countIndirectionsForCppType(operand.getLanguageType())]
5454
} or
55-
TIndirectOperand(Operand op, int indirectionIndex) {
56-
Ssa::hasIndirectOperand(op, indirectionIndex)
55+
TRawIndirectOperand(Operand op, int indirectionIndex) {
56+
Ssa::hasRawIndirectOperand(op, indirectionIndex)
5757
} or
58-
TIndirectInstruction(Instruction instr, int indirectionIndex) {
59-
Ssa::hasIndirectInstruction(instr, indirectionIndex)
58+
TRawIndirectInstruction(Instruction instr, int indirectionIndex) {
59+
Ssa::hasRawIndirectInstruction(instr, indirectionIndex)
6060
}
6161
}
6262

@@ -583,15 +583,15 @@ class IndirectArgumentOutNode extends Node, TIndirectArgumentOutNode, PartialDef
583583

584584
pragma[nomagic]
585585
predicate indirectReturnOutNodeOperand0(CallInstruction call, Operand operand, int indirectionIndex) {
586-
Ssa::hasIndirectInstruction(call, indirectionIndex) and
586+
Ssa::hasRawIndirectInstruction(call, indirectionIndex) and
587587
operandForfullyConvertedCall(operand, call)
588588
}
589589

590590
pragma[nomagic]
591591
predicate indirectReturnOutNodeInstruction0(
592592
CallInstruction call, Instruction instr, int indirectionIndex
593593
) {
594-
Ssa::hasIndirectInstruction(call, indirectionIndex) and
594+
Ssa::hasRawIndirectInstruction(call, indirectionIndex) and
595595
instructionForfullyConvertedCall(instr, call)
596596
}
597597

@@ -637,11 +637,11 @@ private Type getTypeImpl(Type t, int indirectionIndex) {
637637
* A node that represents the indirect value of an operand in the IR
638638
* after `index` number of loads.
639639
*/
640-
class IndirectOperand extends Node, TIndirectOperand {
640+
private class RawIndirectOperand extends Node, TRawIndirectOperand {
641641
Operand operand;
642642
int indirectionIndex;
643643

644-
IndirectOperand() { this = TIndirectOperand(operand, indirectionIndex) }
644+
RawIndirectOperand() { this = TRawIndirectOperand(operand, indirectionIndex) }
645645

646646
/** Gets the underlying instruction. */
647647
Operand getOperand() { result = operand }
@@ -665,6 +665,30 @@ class IndirectOperand extends Node, TIndirectOperand {
665665
}
666666
}
667667

668+
class IndirectOperand extends Node {
669+
Operand operand;
670+
int indirectionIndex;
671+
672+
IndirectOperand() {
673+
this.(RawIndirectOperand).getOperand() = operand and
674+
this.(RawIndirectOperand).getIndirectionIndex() = indirectionIndex
675+
or
676+
this.(OperandNode).getOperand() = Ssa::getIRBackedIndirectOperand(operand, indirectionIndex)
677+
}
678+
679+
Operand getOperand() { result = operand }
680+
681+
int getIndirectionIndex() { result = indirectionIndex }
682+
683+
predicate isIRBackedBy(Operand op, int index) {
684+
this instanceof OperandNode and
685+
(
686+
op = operand and
687+
index = indirectionIndex
688+
)
689+
}
690+
}
691+
668692
/**
669693
* The value of an uninitialized local variable, viewed as a node in a data
670694
* flow graph.
@@ -690,11 +714,11 @@ class UninitializedNode extends Node {
690714
* A node that represents the indirect value of an instruction in the IR
691715
* after `index` number of loads.
692716
*/
693-
class IndirectInstruction extends Node, TIndirectInstruction {
717+
private class RawIndirectInstruction extends Node, TRawIndirectInstruction {
694718
Instruction instr;
695719
int indirectionIndex;
696720

697-
IndirectInstruction() { this = TIndirectInstruction(instr, indirectionIndex) }
721+
RawIndirectInstruction() { this = TRawIndirectInstruction(instr, indirectionIndex) }
698722

699723
/** Gets the underlying instruction. */
700724
Instruction getInstruction() { result = instr }
@@ -718,6 +742,31 @@ class IndirectInstruction extends Node, TIndirectInstruction {
718742
}
719743
}
720744

745+
class IndirectInstruction extends Node {
746+
Instruction instr;
747+
int indirectionIndex;
748+
749+
IndirectInstruction() {
750+
this.(RawIndirectInstruction).getInstruction() = instr and
751+
this.(RawIndirectInstruction).getIndirectionIndex() = indirectionIndex
752+
or
753+
this.(InstructionNode).getInstruction() =
754+
Ssa::getIRBackedIndirectInstruction(instr, indirectionIndex)
755+
}
756+
757+
Instruction getInstruction() { result = instr }
758+
759+
int getIndirectionIndex() { result = indirectionIndex }
760+
761+
predicate isIRBackedBy(Instruction i, int index) {
762+
this instanceof InstructionNode and
763+
(
764+
i = instr and
765+
index = indirectionIndex
766+
)
767+
}
768+
}
769+
721770
private predicate isFullyConvertedArgument(Expr e) {
722771
e = any(Call call).getAnArgument().getFullyConverted()
723772
}
@@ -732,32 +781,20 @@ private predicate convertedExprMustBeOperand(Expr e) {
732781
}
733782

734783
/** Holds if `node` is an `OperandNode` that should map `node.asExpr()` to `e`. */
735-
predicate exprNodeShouldBeOperand(Node node, Expr e) {
736-
e = node.asOperand().getDef().getConvertedResultExpression() and
737-
convertedExprMustBeOperand(e)
738-
}
739-
740-
/**
741-
* Holds if `load` is a `LoadInstruction` that is the result of evaluating `e`
742-
* and `node` is an `IndirectOperandNode` that should map `node.asExpr()` to `e`.
743-
*
744-
* We map `e` to `node.asExpr()` when `node` semantically represents the
745-
* same value as `load`. A subsequent flow step will flow `node` to
746-
* the `LoadInstruction`.
747-
*/
748-
private predicate exprNodeShouldBeIndirectOperand(IndirectOperand node, Expr e, LoadInstruction load) {
749-
node.getIndirectionIndex() = 1 and
750-
e = load.getConvertedResultExpression() and
751-
load.getSourceAddressOperand() = node.getOperand() and
752-
not convertedExprMustBeOperand(e)
784+
predicate exprNodeShouldBeOperand(OperandNode node, Expr e) {
785+
exists(Operand operand |
786+
node.getOperand() = operand and
787+
e = operand.getDef().getConvertedResultExpression()
788+
|
789+
convertedExprMustBeOperand(e)
790+
or
791+
node.(IndirectOperand).isIRBackedBy(_, _)
792+
)
753793
}
754794

755795
/** Holds if `node` should be an `IndirectOperand` that maps `node.asIndirectExpr()` to `e`. */
756-
private predicate indirectExprNodeShouldBeIndirectOperand(IndirectOperand node, Expr e) {
757-
exists(Instruction instr |
758-
instr = node.getOperand().getDef() and
759-
not node instanceof ExprNode
760-
|
796+
private predicate indirectExprNodeShouldBeIndirectOperand(RawIndirectOperand node, Expr e) {
797+
exists(Instruction instr | instr = node.getOperand().getDef() |
761798
e = instr.(VariableAddressInstruction).getAst().(Expr).getFullyConverted()
762799
or
763800
not instr instanceof VariableAddressInstruction and
@@ -777,7 +814,6 @@ private predicate exprNodeShouldBeIndirectOutNode(IndirectArgumentOutNode node,
777814
predicate exprNodeShouldBeInstruction(Node node, Expr e) {
778815
e = node.asInstruction().getConvertedResultExpression() and
779816
not exprNodeShouldBeOperand(_, e) and
780-
not exprNodeShouldBeIndirectOperand(_, e, _) and
781817
not exprNodeShouldBeIndirectOutNode(_, e)
782818
}
783819

@@ -821,23 +857,6 @@ private class OperandExprNode extends ExprNodeBase, OperandNode {
821857

822858
final override Expr getExpr() { result = this.getConvertedExpr().getUnconverted() }
823859

824-
final override string toStringImpl() {
825-
// Avoid generating multiple `toString` results for `ArgumentNode`s
826-
// since they have a better `toString`.
827-
result = this.(ArgumentNode).toStringImpl()
828-
or
829-
not this instanceof ArgumentNode and
830-
result = this.getConvertedExpr().toString()
831-
}
832-
}
833-
834-
private class IndirectOperandExprNode extends ExprNodeBase, IndirectOperand {
835-
IndirectOperandExprNode() { exprNodeShouldBeIndirectOperand(this, _, _) }
836-
837-
final override Expr getConvertedExpr() { exprNodeShouldBeIndirectOperand(this, result, _) }
838-
839-
final override Expr getExpr() { result = this.getConvertedExpr().getUnconverted() }
840-
841860
final override string toStringImpl() { result = this.getConvertedExpr().toString() }
842861
}
843862

@@ -852,7 +871,7 @@ abstract private class IndirectExprNodeBase extends Node {
852871
abstract Expr getExpr(int indirectionIndex);
853872
}
854873

855-
private class IndirectOperandIndirectExprNode extends IndirectExprNodeBase, IndirectOperand {
874+
private class IndirectOperandIndirectExprNode extends IndirectExprNodeBase, RawIndirectOperand {
856875
IndirectOperandIndirectExprNode() { indirectExprNodeShouldBeIndirectOperand(this, _) }
857876

858877
final override Expr getConvertedExpr(int index) {
@@ -866,7 +885,8 @@ private class IndirectOperandIndirectExprNode extends IndirectExprNodeBase, Indi
866885
}
867886
}
868887

869-
private class IndirectInstructionIndirectExprNode extends IndirectExprNodeBase, IndirectInstruction {
888+
private class IndirectInstructionIndirectExprNode extends IndirectExprNodeBase,
889+
RawIndirectInstruction {
870890
IndirectInstructionIndirectExprNode() { indirectExprNodeShouldBeIndirectInstruction(this, _) }
871891

872892
final override Expr getConvertedExpr(int index) {
@@ -886,8 +906,6 @@ private class IndirectArgumentOutExprNode extends ExprNodeBase, IndirectArgument
886906
final override Expr getConvertedExpr() { exprNodeShouldBeIndirectOutNode(this, result) }
887907

888908
final override Expr getExpr() { result = this.getConvertedExpr() }
889-
890-
final override string toStringImpl() { result = this.getConvertedExpr().toString() }
891909
}
892910

893911
/**
@@ -1154,7 +1172,7 @@ Node uninitializedNode(LocalVariable v) { none() }
11541172
*/
11551173
predicate localFlowStep = simpleLocalFlowStep/2;
11561174

1157-
private predicate indirectionOperandFlow(IndirectOperand nodeFrom, Node nodeTo) {
1175+
private predicate indirectionOperandFlow(RawIndirectOperand nodeFrom, Node nodeTo) {
11581176
// Reduce the indirection count by 1 if we're passing through a `LoadInstruction`.
11591177
exists(int ind, LoadInstruction load |
11601178
hasOperandAndIndex(nodeFrom, load.getSourceAddressOperand(), ind) and
@@ -1191,7 +1209,7 @@ predicate hasInstructionAndIndex(
11911209
indirectInstr.getIndirectionIndex() = indirectionIndex
11921210
}
11931211

1194-
private predicate indirectionInstructionFlow(IndirectInstruction nodeFrom, IndirectOperand nodeTo) {
1212+
private predicate indirectionInstructionFlow(RawIndirectInstruction nodeFrom, IndirectOperand nodeTo) {
11951213
// If there's flow from an instruction to an operand, then there's also flow from the
11961214
// indirect instruction to the indirect operand.
11971215
exists(Operand operand, Instruction instr, int indirectionIndex |
@@ -1470,9 +1488,9 @@ private IRBlock getBasicBlock(Node node) {
14701488
or
14711489
node.(SsaPhiNode).getPhiNode().getBasicBlock() = result
14721490
or
1473-
node.(IndirectOperand).getOperand().getUse().getBlock() = result
1491+
node.(RawIndirectOperand).getOperand().getUse().getBlock() = result
14741492
or
1475-
node.(IndirectInstruction).getInstruction().getBlock() = result
1493+
node.(RawIndirectInstruction).getInstruction().getBlock() = result
14761494
or
14771495
result = getBasicBlock(node.(PostUpdateNode).getPreUpdateNode())
14781496
}
@@ -1518,10 +1536,11 @@ signature predicate instructionGuardChecksSig(IRGuardCondition g, Instruction in
15181536
module InstructionBarrierGuard<instructionGuardChecksSig/3 instructionGuardChecks> {
15191537
/** Gets a node that is safely guarded by the given guard check. */
15201538
ExprNode getABarrierNode() {
1521-
exists(IRGuardCondition g, ValueNumber value, boolean edge |
1539+
exists(IRGuardCondition g, ValueNumber value, boolean edge, Operand use |
15221540
instructionGuardChecks(g, value.getAnInstruction(), edge) and
1523-
result.asInstruction() = value.getAnInstruction() and
1524-
g.controls(result.asInstruction().getBlock(), edge)
1541+
use = value.getAnInstruction().getAUse() and
1542+
result.asOperand() = use and
1543+
g.controls(use.getDef().getBlock(), edge)
15251544
)
15261545
}
15271546
}

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

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,21 +86,31 @@ private module SourceVariables {
8686

8787
import SourceVariables
8888

89-
predicate hasIndirectOperand(Operand op, int indirectionIndex) {
89+
/**
90+
* Holds if the `(operand, indirectionIndex)` columns should be
91+
* assigned an `RawIndirectOperand` value.
92+
*/
93+
predicate hasRawIndirectOperand(Operand op, int indirectionIndex) {
9094
exists(CppType type, int m |
9195
not ignoreOperand(op) and
9296
type = getLanguageType(op) and
9397
m = countIndirectionsForCppType(type) and
94-
indirectionIndex = [1 .. m]
98+
indirectionIndex = [1 .. m] and
99+
not exists(getIRBackedIndirectOperand(op, indirectionIndex))
95100
)
96101
}
97102

98-
predicate hasIndirectInstruction(Instruction instr, int indirectionIndex) {
103+
/**
104+
* Holds if the `(instr, indirectionIndex)` columns should be
105+
* assigned an `RawIndirectInstruction` value.
106+
*/
107+
predicate hasRawIndirectInstruction(Instruction instr, int indirectionIndex) {
99108
exists(CppType type, int m |
100109
not ignoreInstruction(instr) and
101110
type = getResultLanguageType(instr) and
102111
m = countIndirectionsForCppType(type) and
103-
indirectionIndex = [1 .. m]
112+
indirectionIndex = [1 .. m] and
113+
not exists(getIRBackedIndirectInstruction(instr, indirectionIndex))
104114
)
105115
}
106116

0 commit comments

Comments
 (0)