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

Skip to content

Commit 145dea0

Browse files
committed
C++: Introduce a node class that exists before computing SSA.
1 parent 2ef13d1 commit 145dea0

5 files changed

Lines changed: 186 additions & 70 deletions

File tree

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

Lines changed: 106 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,111 @@ private import DataFlowImplConsistency
66
private import semmle.code.cpp.ir.internal.IRCppLanguage
77
private import SsaInternals as Ssa
88

9+
cached
10+
private module Cached {
11+
cached
12+
newtype TIRDataFlowNode0 =
13+
TInstructionNode0(Instruction i) {
14+
not Ssa::ignoreInstruction(i) and
15+
// We exclude `void`-typed instructions because they cannot contain data.
16+
// However, if the instruction is a glvalue, and their type is `void`, then the result
17+
// type of the instruction is really `void*`, and thus we still want to have a dataflow
18+
// node for it.
19+
(not i.getResultType() instanceof VoidType or i.isGLValue())
20+
} or
21+
TOperandNode0(Operand op) { not Ssa::ignoreOperand(op) }
22+
}
23+
24+
private import Cached
25+
26+
class Node0Impl extends TIRDataFlowNode0 {
27+
/**
28+
* INTERNAL: Do not use.
29+
*/
30+
Declaration getEnclosingCallable() { none() } // overridden in subclasses
31+
32+
/** Gets the function to which this node belongs, if any. */
33+
Declaration getFunction() { none() } // overridden in subclasses
34+
35+
/**
36+
* Gets the type of this node.
37+
*
38+
* If `asInstruction().isGLValue()` holds, then the type of this node
39+
* should be thought of as "pointer to `getType()`".
40+
*/
41+
DataFlowType getType() { none() } // overridden in subclasses
42+
43+
/** Gets the instruction corresponding to this node, if any. */
44+
Instruction asInstruction() { result = this.(InstructionNode0).getInstruction() }
45+
46+
/** Gets the operands corresponding to this node, if any. */
47+
Operand asOperand() { result = this.(OperandNode0).getOperand() }
48+
49+
/** INTERNAL: Do not use. */
50+
Location getLocationImpl() {
51+
none() // overridden by subclasses
52+
}
53+
54+
/** INTERNAL: Do not use. */
55+
string toStringImpl() {
56+
none() // overridden by subclasses
57+
}
58+
59+
/** Gets the location of this node. */
60+
final Location getLocation() { result = this.getLocationImpl() }
61+
62+
/** Gets a textual representation of this node. */
63+
final string toString() { result = this.toStringImpl() }
64+
}
65+
66+
/**
67+
* An instruction, viewed as a node in a data flow graph.
68+
*/
69+
class InstructionNode0 extends Node0Impl, TInstructionNode0 {
70+
Instruction instr;
71+
72+
InstructionNode0() { this = TInstructionNode0(instr) }
73+
74+
/** Gets the instruction corresponding to this node. */
75+
Instruction getInstruction() { result = instr }
76+
77+
override Declaration getEnclosingCallable() { result = this.getFunction() }
78+
79+
override Declaration getFunction() { result = instr.getEnclosingFunction() }
80+
81+
override DataFlowType getType() { result = instr.getResultType() }
82+
83+
final override Location getLocationImpl() { result = instr.getLocation() }
84+
85+
override string toStringImpl() {
86+
// This predicate is overridden in subclasses. This default implementation
87+
// does not use `Instruction.toString` because that's expensive to compute.
88+
result = this.getInstruction().getOpcode().toString()
89+
}
90+
}
91+
92+
/**
93+
* An operand, viewed as a node in a data flow graph.
94+
*/
95+
class OperandNode0 extends Node0Impl, TOperandNode0 {
96+
Operand op;
97+
98+
OperandNode0() { this = TOperandNode0(op) }
99+
100+
/** Gets the operand corresponding to this node. */
101+
Operand getOperand() { result = op }
102+
103+
override Declaration getEnclosingCallable() { result = this.getFunction() }
104+
105+
override Declaration getFunction() { result = op.getUse().getEnclosingFunction() }
106+
107+
override DataFlowType getType() { result = op.getType() }
108+
109+
final override Location getLocationImpl() { result = op.getLocation() }
110+
111+
override string toStringImpl() { result = this.getOperand().toString() }
112+
}
113+
9114
/**
10115
* INTERNAL: Do not use.
11116
*
@@ -251,7 +356,7 @@ class ReturnNode extends Node instanceof IndirectReturnNode {
251356
*/
252357
private predicate hasNonInitializeParameterDef(IRVariable v) {
253358
exists(Ssa::Def def |
254-
not def.getDefiningInstruction() instanceof InitializeParameterInstruction and
359+
not def.getValue().asInstruction() instanceof InitializeParameterInstruction and
255360
v = def.getSourceVariable().getBaseVariable().(Ssa::BaseIRVariable).getIRVariable()
256361
)
257362
}

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

Lines changed: 27 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,7 @@ private module Cached {
3333
*/
3434
cached
3535
newtype TIRDataFlowNode =
36-
TInstructionNode(Instruction i) {
37-
not Ssa::ignoreInstruction(i) and
38-
// We exclude `void`-typed instructions because they cannot contain data.
39-
// However, if the instruction is a glvalue, and their type is `void`, then the result
40-
// type of the instruction is really `void*`, and thus we still want to have a dataflow
41-
// node for it.
42-
(not i.getResultType() instanceof VoidType or i.isGLValue())
43-
} or
44-
TOperandNode(Operand op) { not Ssa::ignoreOperand(op) } or
36+
TNode0(Node0Impl node) or
4537
TVariableNode(Variable var) or
4638
TPostFieldUpdateNode(FieldAddress operand, int indirectionIndex) {
4739
indirectionIndex =
@@ -335,52 +327,50 @@ private string toExprString(Node n) {
335327
result = n.asIndirectExpr().toString() + " indirection"
336328
}
337329

338-
/**
339-
* An instruction, viewed as a node in a data flow graph.
340-
*/
341-
class InstructionNode extends Node, TInstructionNode {
342-
Instruction instr;
330+
class Node0 extends Node, TNode0 {
331+
Node0Impl node;
343332

344-
InstructionNode() { this = TInstructionNode(instr) }
333+
Node0() { this = TNode0(node) }
345334

346-
/** Gets the instruction corresponding to this node. */
347-
Instruction getInstruction() { result = instr }
335+
override Declaration getEnclosingCallable() { result = node.getEnclosingCallable() }
348336

349-
override Declaration getEnclosingCallable() { result = this.getFunction() }
350-
351-
override Declaration getFunction() { result = instr.getEnclosingFunction() }
337+
override Declaration getFunction() { result = node.getFunction() }
352338

353-
override DataFlowType getType() { result = instr.getResultType() }
339+
override DataFlowType getType() { result = node.getType() }
354340

355-
final override Location getLocationImpl() { result = instr.getLocation() }
341+
final override Location getLocationImpl() { result = node.getLocationImpl() }
356342

357343
override string toStringImpl() {
358344
// This predicate is overridden in subclasses. This default implementation
359345
// does not use `Instruction.toString` because that's expensive to compute.
360-
result = this.getInstruction().getOpcode().toString()
346+
result = node.toStringImpl()
361347
}
362348
}
363349

364350
/**
365-
* An operand, viewed as a node in a data flow graph.
351+
* An instruction, viewed as a node in a data flow graph.
366352
*/
367-
class OperandNode extends Node, TOperandNode {
368-
Operand op;
369-
370-
OperandNode() { this = TOperandNode(op) }
371-
372-
/** Gets the operand corresponding to this node. */
373-
Operand getOperand() { result = op }
353+
class InstructionNode extends Node0 {
354+
override InstructionNode0 node;
355+
Instruction instr;
374356

375-
override Declaration getEnclosingCallable() { result = this.getFunction() }
357+
InstructionNode() { instr = node.getInstruction() }
376358

377-
override Declaration getFunction() { result = op.getUse().getEnclosingFunction() }
359+
/** Gets the instruction corresponding to this node. */
360+
Instruction getInstruction() { result = instr }
361+
}
378362

379-
override DataFlowType getType() { result = op.getType() }
363+
/**
364+
* An operand, viewed as a node in a data flow graph.
365+
*/
366+
class OperandNode extends Node, Node0 {
367+
override OperandNode0 node;
368+
Operand op;
380369

381-
final override Location getLocationImpl() { result = op.getLocation() }
370+
OperandNode() { op = node.getOperand() }
382371

383-
override string toStringImpl() { result = this.getOperand().toString() }
372+
/** Gets the operand corresponding to this node. */
373+
Operand getOperand() { result = node.getOperand() }
384374
}
385375

386376
/**
@@ -681,7 +671,7 @@ class UninitializedNode extends Node {
681671

682672
UninitializedNode() {
683673
exists(Ssa::Def def |
684-
def.getDefiningInstruction() instanceof UninitializedInstruction and
674+
def.getValue().asInstruction() instanceof UninitializedInstruction and
685675
Ssa::nodeToDefOrUse(this, def) and
686676
v = def.getSourceVariable().getBaseVariable().(Ssa::BaseIRVariable).getIRVariable().getAst()
687677
)

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

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -222,16 +222,16 @@ class DefImpl extends DefOrUseImpl, TDefImpl {
222222

223223
override int getIndirectionIndex() { result = ind }
224224

225-
Instruction getDefiningInstruction() { isDef(_, result, address, _, _, _) }
225+
Node0Impl getValue() { isDef(_, result, address, _, _, _) }
226226

227227
override string toString() { result = "DefImpl" }
228228

229-
override IRBlock getBlock() { result = this.getDefiningInstruction().getBlock() }
229+
override IRBlock getBlock() { result = this.getAddressOperand().getUse().getBlock() }
230230

231-
override Cpp::Location getLocation() { result = this.getDefiningInstruction().getLocation() }
231+
override Cpp::Location getLocation() { result = this.getAddressOperand().getUse().getLocation() }
232232

233233
final override predicate hasIndexInBlock(IRBlock block, int index) {
234-
this.getDefiningInstruction() = block.getInstruction(index)
234+
this.getAddressOperand().getUse() = block.getInstruction(index)
235235
}
236236

237237
predicate isCertain() { isDef(true, _, address, _, _, ind) }
@@ -308,7 +308,10 @@ predicate outNodeHasAddressAndIndex(
308308
}
309309

310310
private predicate defToNode(Node nodeFrom, Def def) {
311-
nodeHasInstruction(nodeFrom, def.getDefiningInstruction(), def.getIndirectionIndex())
311+
// TODO: This is not yet needed (and in fact, the compiler rejects it because `exists(def.getValue().asOperand())` never holds).
312+
// nodeHasOperand(nodeFrom, def.getValue().asOperand(), def.getIndirectionIndex())
313+
// or
314+
nodeHasInstruction(nodeFrom, def.getValue().asInstruction(), def.getIndirectionIndex())
312315
}
313316

314317
/**
@@ -562,7 +565,7 @@ class Def extends DefOrUse {
562565
pragma[only_bind_into](result) = pragma[only_bind_out](defOrUse).getIndirectionIndex()
563566
}
564567

565-
Instruction getDefiningInstruction() { result = defOrUse.getDefiningInstruction() }
568+
Node0Impl getValue() { result = defOrUse.getValue() }
566569
}
567570

568571
private module SsaImpl = SsaImplCommon::Make<SsaInput>;

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

Lines changed: 38 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import semmle.code.cpp.ir.internal.IRCppLanguage
44
private import semmle.code.cpp.ir.implementation.raw.internal.SideEffects as SideEffects
55
private import DataFlowImplCommon as DataFlowImplCommon
66
private import DataFlowUtil
7+
private import DataFlowPrivate
78

89
/**
910
* Holds if `operand` is an operand that is not used by the dataflow library.
@@ -126,15 +127,29 @@ class AllocationInstruction extends CallInstruction {
126127
AllocationInstruction() { this.getStaticCallTarget() instanceof Cpp::AllocationFunction }
127128
}
128129

129-
/**
130-
* Holds if `i` is a base instruction that starts a sequence of uses
131-
* of some variable that SSA can handle.
132-
*
133-
* This is either when `i` is a `VariableAddressInstruction` or when
134-
* `i` is a fresh allocation produced by an `AllocationInstruction`.
135-
*/
136-
private predicate isSourceVariableBase(Instruction i) {
137-
i instanceof VariableAddressInstruction or i instanceof AllocationInstruction
130+
predicate isWrite(Node0Impl value, Operand address, boolean certain) {
131+
certain = true and
132+
(
133+
exists(StoreInstruction store |
134+
value.asInstruction() = store and
135+
address = store.getDestinationAddressOperand()
136+
)
137+
or
138+
exists(InitializeParameterInstruction init |
139+
value.asInstruction() = init and
140+
address = init.getAnOperand()
141+
)
142+
or
143+
exists(InitializeDynamicAllocationInstruction init |
144+
value.asInstruction() = init and
145+
address = init.getAllocationAddressOperand()
146+
)
147+
or
148+
exists(UninitializedInstruction uninitialized |
149+
value.asInstruction() = uninitialized and
150+
address = uninitialized.getAnOperand()
151+
)
152+
)
138153
}
139154

140155
/**
@@ -263,6 +278,17 @@ private module Cached {
263278
)
264279
}
265280

281+
/**
282+
* Holds if `i` is a base instruction that starts a sequence of uses
283+
* of some variable that SSA can handle.
284+
*
285+
* This is either when `i` is a `VariableAddressInstruction` or when
286+
* `i` is a fresh allocation produced by an `AllocationInstruction`.
287+
*/
288+
private predicate isSourceVariableBase(Instruction i) {
289+
i instanceof VariableAddressInstruction or i instanceof AllocationInstruction
290+
}
291+
266292
/**
267293
* Holds if `address` is an address of an SSA variable rooted at `base`,
268294
* and `instr` is a definition of the SSA variable with `ind` number of indirections.
@@ -273,25 +299,17 @@ private module Cached {
273299
*/
274300
cached
275301
predicate isDef(
276-
boolean certain, Instruction instr, Operand address, Instruction base, int ind,
302+
boolean certain, Node0Impl value, Operand address, Instruction base, int ind,
277303
int indirectionIndex
278304
) {
279-
certain = true and
280305
exists(int ind0, CppType type, int lower, int upper |
281-
address =
282-
[
283-
instr.(StoreInstruction).getDestinationAddressOperand(),
284-
instr.(InitializeParameterInstruction).getAnOperand(),
285-
instr.(InitializeDynamicAllocationInstruction).getAllocationAddressOperand(),
286-
instr.(UninitializedInstruction).getAnOperand()
287-
]
288-
|
306+
isWrite(value, address, certain) and
289307
isDefImpl(address, base, ind0) and
290308
type = getLanguageType(address) and
291309
upper = countIndirectionsForCppType(type) and
292310
ind = ind0 + [lower .. upper] and
293311
indirectionIndex = ind - (ind0 + lower) and
294-
if type.hasType(any(Cpp::ArrayType arrayType), true) then lower = 0 else lower = 1
312+
(if type.hasType(any(Cpp::ArrayType arrayType), true) then lower = 0 else lower = 1)
295313
)
296314
}
297315

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -168,16 +168,16 @@ class DefImpl extends DefOrUseImpl, TDefImpl {
168168

169169
Operand getAddressOperand() { result = address }
170170

171-
Instruction getDefiningInstruction() { isDef(_, result, address, _, _, _) }
171+
Node0Impl getValue() { isDef(_, result, address, _, _, _) }
172172

173173
override string toString() { result = address.toString() }
174174

175-
override IRBlock getBlock() { result = this.getDefiningInstruction().getBlock() }
175+
override IRBlock getBlock() { result = this.getAddressOperand().getDef().getBlock() }
176176

177-
override Cpp::Location getLocation() { result = this.getDefiningInstruction().getLocation() }
177+
override Cpp::Location getLocation() { result = this.getAddressOperand().getLocation() }
178178

179179
final override predicate hasIndexInBlock(IRBlock block, int index) {
180-
this.getDefiningInstruction() = block.getInstruction(index)
180+
this.getAddressOperand().getUse() = block.getInstruction(index)
181181
}
182182

183183
predicate isCertain() { isDef(true, _, address, _, _, _) }
@@ -302,9 +302,9 @@ class Def extends DefOrUse {
302302

303303
Instruction getAddress() { result = this.getAddressOperand().getDef() }
304304

305-
Instruction getDefiningInstruction() { result = defOrUse.getDefiningInstruction() }
305+
Node0Impl getValue() { result = defOrUse.getValue() }
306306

307-
override string toString() { result = this.asDefOrUse().toString() + " (def)" }
307+
override string toString() { result = this.asDefOrUse().toString() }
308308
}
309309

310310
private module SsaImpl = SsaImplCommon::Make<SsaInput>;

0 commit comments

Comments
 (0)