Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a51ac7b

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 a51ac7b

4 files changed

Lines changed: 130 additions & 90 deletions

File tree

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: 84 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,31 @@ 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() =
677+
Ssa::getIRRepresentationOfIndirectOperand(operand, indirectionIndex)
678+
}
679+
680+
Operand getOperand() { result = operand }
681+
682+
int getIndirectionIndex() { result = indirectionIndex }
683+
684+
predicate isIRRepresentationOf(Operand op, int index) {
685+
this instanceof OperandNode and
686+
(
687+
op = operand and
688+
index = indirectionIndex
689+
)
690+
}
691+
}
692+
668693
/**
669694
* The value of an uninitialized local variable, viewed as a node in a data
670695
* flow graph.
@@ -690,11 +715,11 @@ class UninitializedNode extends Node {
690715
* A node that represents the indirect value of an instruction in the IR
691716
* after `index` number of loads.
692717
*/
693-
class IndirectInstruction extends Node, TIndirectInstruction {
718+
private class RawIndirectInstruction extends Node, TRawIndirectInstruction {
694719
Instruction instr;
695720
int indirectionIndex;
696721

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

699724
/** Gets the underlying instruction. */
700725
Instruction getInstruction() { result = instr }
@@ -718,6 +743,31 @@ class IndirectInstruction extends Node, TIndirectInstruction {
718743
}
719744
}
720745

746+
class IndirectInstruction extends Node {
747+
Instruction instr;
748+
int indirectionIndex;
749+
750+
IndirectInstruction() {
751+
this.(RawIndirectInstruction).getInstruction() = instr and
752+
this.(RawIndirectInstruction).getIndirectionIndex() = indirectionIndex
753+
or
754+
this.(InstructionNode).getInstruction() =
755+
Ssa::getIRRepresentationOfIndirectInstruction(instr, indirectionIndex)
756+
}
757+
758+
Instruction getInstruction() { result = instr }
759+
760+
int getIndirectionIndex() { result = indirectionIndex }
761+
762+
predicate isIRRepresentationOf(Instruction i, int index) {
763+
this instanceof InstructionNode and
764+
(
765+
i = instr and
766+
index = indirectionIndex
767+
)
768+
}
769+
}
770+
721771
private predicate isFullyConvertedArgument(Expr e) {
722772
e = any(Call call).getAnArgument().getFullyConverted()
723773
}
@@ -732,32 +782,20 @@ private predicate convertedExprMustBeOperand(Expr e) {
732782
}
733783

734784
/** 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)
785+
predicate exprNodeShouldBeOperand(OperandNode node, Expr e) {
786+
exists(Operand operand |
787+
node.getOperand() = operand and
788+
e = operand.getDef().getConvertedResultExpression()
789+
|
790+
convertedExprMustBeOperand(e)
791+
or
792+
node.(IndirectOperand).isIRRepresentationOf(_, _)
793+
)
753794
}
754795

755796
/** 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-
|
797+
private predicate indirectExprNodeShouldBeIndirectOperand(RawIndirectOperand node, Expr e) {
798+
exists(Instruction instr | instr = node.getOperand().getDef() |
761799
e = instr.(VariableAddressInstruction).getAst().(Expr).getFullyConverted()
762800
or
763801
not instr instanceof VariableAddressInstruction and
@@ -777,7 +815,6 @@ private predicate exprNodeShouldBeIndirectOutNode(IndirectArgumentOutNode node,
777815
predicate exprNodeShouldBeInstruction(Node node, Expr e) {
778816
e = node.asInstruction().getConvertedResultExpression() and
779817
not exprNodeShouldBeOperand(_, e) and
780-
not exprNodeShouldBeIndirectOperand(_, e, _) and
781818
not exprNodeShouldBeIndirectOutNode(_, e)
782819
}
783820

@@ -821,23 +858,6 @@ private class OperandExprNode extends ExprNodeBase, OperandNode {
821858

822859
final override Expr getExpr() { result = this.getConvertedExpr().getUnconverted() }
823860

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-
841861
final override string toStringImpl() { result = this.getConvertedExpr().toString() }
842862
}
843863

@@ -852,7 +872,7 @@ abstract private class IndirectExprNodeBase extends Node {
852872
abstract Expr getExpr(int indirectionIndex);
853873
}
854874

855-
private class IndirectOperandIndirectExprNode extends IndirectExprNodeBase, IndirectOperand {
875+
private class IndirectOperandIndirectExprNode extends IndirectExprNodeBase, RawIndirectOperand {
856876
IndirectOperandIndirectExprNode() { indirectExprNodeShouldBeIndirectOperand(this, _) }
857877

858878
final override Expr getConvertedExpr(int index) {
@@ -866,7 +886,8 @@ private class IndirectOperandIndirectExprNode extends IndirectExprNodeBase, Indi
866886
}
867887
}
868888

869-
private class IndirectInstructionIndirectExprNode extends IndirectExprNodeBase, IndirectInstruction {
889+
private class IndirectInstructionIndirectExprNode extends IndirectExprNodeBase,
890+
RawIndirectInstruction {
870891
IndirectInstructionIndirectExprNode() { indirectExprNodeShouldBeIndirectInstruction(this, _) }
871892

872893
final override Expr getConvertedExpr(int index) {
@@ -886,8 +907,6 @@ private class IndirectArgumentOutExprNode extends ExprNodeBase, IndirectArgument
886907
final override Expr getConvertedExpr() { exprNodeShouldBeIndirectOutNode(this, result) }
887908

888909
final override Expr getExpr() { result = this.getConvertedExpr() }
889-
890-
final override string toStringImpl() { result = this.getConvertedExpr().toString() }
891910
}
892911

893912
/**
@@ -1154,7 +1173,7 @@ Node uninitializedNode(LocalVariable v) { none() }
11541173
*/
11551174
predicate localFlowStep = simpleLocalFlowStep/2;
11561175

1157-
private predicate indirectionOperandFlow(IndirectOperand nodeFrom, Node nodeTo) {
1176+
private predicate indirectionOperandFlow(RawIndirectOperand nodeFrom, Node nodeTo) {
11581177
// Reduce the indirection count by 1 if we're passing through a `LoadInstruction`.
11591178
exists(int ind, LoadInstruction load |
11601179
hasOperandAndIndex(nodeFrom, load.getSourceAddressOperand(), ind) and
@@ -1191,7 +1210,7 @@ predicate hasInstructionAndIndex(
11911210
indirectInstr.getIndirectionIndex() = indirectionIndex
11921211
}
11931212

1194-
private predicate indirectionInstructionFlow(IndirectInstruction nodeFrom, IndirectOperand nodeTo) {
1213+
private predicate indirectionInstructionFlow(RawIndirectInstruction nodeFrom, IndirectOperand nodeTo) {
11951214
// If there's flow from an instruction to an operand, then there's also flow from the
11961215
// indirect instruction to the indirect operand.
11971216
exists(Operand operand, Instruction instr, int indirectionIndex |
@@ -1470,9 +1489,9 @@ private IRBlock getBasicBlock(Node node) {
14701489
or
14711490
node.(SsaPhiNode).getPhiNode().getBasicBlock() = result
14721491
or
1473-
node.(IndirectOperand).getOperand().getUse().getBlock() = result
1492+
node.(RawIndirectOperand).getOperand().getUse().getBlock() = result
14741493
or
1475-
node.(IndirectInstruction).getInstruction().getBlock() = result
1494+
node.(RawIndirectInstruction).getInstruction().getBlock() = result
14761495
or
14771496
result = getBasicBlock(node.(PostUpdateNode).getPreUpdateNode())
14781497
}
@@ -1518,10 +1537,11 @@ signature predicate instructionGuardChecksSig(IRGuardCondition g, Instruction in
15181537
module InstructionBarrierGuard<instructionGuardChecksSig/3 instructionGuardChecks> {
15191538
/** Gets a node that is safely guarded by the given guard check. */
15201539
ExprNode getABarrierNode() {
1521-
exists(IRGuardCondition g, ValueNumber value, boolean edge |
1540+
exists(IRGuardCondition g, ValueNumber value, boolean edge, Operand use |
15221541
instructionGuardChecks(g, value.getAnInstruction(), edge) and
1523-
result.asInstruction() = value.getAnInstruction() and
1524-
g.controls(result.asInstruction().getBlock(), edge)
1542+
use = value.getAnInstruction().getAUse() and
1543+
result.asOperand() = use and
1544+
g.controls(use.getDef().getBlock(), edge)
15251545
)
15261546
}
15271547
}

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(getIRRepresentationOfIndirectOperand(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(getIRRepresentationOfIndirectInstruction(instr, indirectionIndex))
104114
)
105115
}
106116

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

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,38 @@ private module Cached {
166166
)
167167
}
168168

169+
/**
170+
* Holds if the underlying IR has a suitable operand to represent a value
171+
* that would otherwise need to be represented by a dedicated `RawIndirectOperand` value.
172+
*
173+
* Such operands do not create new `RawIndirectOperand` values, but are
174+
* instead associated with the operand returned by this predicate.
175+
*/
176+
cached
177+
Operand getIRRepresentationOfIndirectOperand(Operand operand, int indirectionIndex) {
178+
exists(LoadInstruction load |
179+
operand = load.getSourceAddressOperand() and
180+
result = unique( | | load.getAUse()) and
181+
isUseImpl(operand, _, indirectionIndex - 1)
182+
)
183+
}
184+
185+
/**
186+
* Holds if the underlying IR has a suitable instruction to represent a value
187+
* that would otherwise need to be represented by a dedicated `RawIndirectInstruction` value.
188+
*
189+
* Such instruction do not create new `RawIndirectOperand` values, but are
190+
* instead associated with the instruction returned by this predicate.
191+
*/
192+
cached
193+
Instruction getIRRepresentationOfIndirectInstruction(Instruction instr, int indirectionIndex) {
194+
exists(LoadInstruction load |
195+
load.getSourceAddress() = instr and
196+
isUseImpl(load.getSourceAddressOperand(), _, indirectionIndex - 1) and
197+
result = instr
198+
)
199+
}
200+
169201
/**
170202
* Holds if `operand` is a use of an SSA variable rooted at `base`, and the
171203
* path from `base` to `operand` passes through `ind` load-like instructions.

0 commit comments

Comments
 (0)