Skip to content

Commit 5d75b25

Browse files
committed
C++: Remove IR re-evaluation.
1 parent 26e8701 commit 5d75b25

File tree

4 files changed

+139
-77
lines changed

4 files changed

+139
-77
lines changed

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

Lines changed: 10 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@ private import semmle.code.cpp.ir.IR
77
private import DataFlowUtil
88
private import DataFlowPrivate
99
private import DataFlowNodes
10-
private import semmle.code.cpp.ir.implementation.raw.internal.TranslatedExpr
11-
private import semmle.code.cpp.ir.implementation.raw.internal.InstructionTag
10+
private import semmle.code.cpp.ir.implementation.raw.internal.IRConstruction as IRConstruction
1211

1312
cached
1413
private module Cached {
@@ -74,17 +73,9 @@ private module Cached {
7473
// a result for `getConvertedResultExpression`. We remap this here so that
7574
// this `ConvertInstruction` maps to the result of the expression that
7675
// represents the extent.
77-
exists(TranslatedNonConstantAllocationSize tas |
78-
result = tas.getExtent().getExpr() and
79-
instr = tas.getInstruction(AllocationExtentConvertTag())
80-
)
76+
result = IRConstruction::Raw::getAllocationExtentConvertExpr(instr)
8177
or
82-
// There's no instruction that returns `ParenthesisExpr`, but some queries
83-
// expect this
84-
exists(TranslatedTransparentConversion ttc |
85-
result = ttc.getExpr().(ParenthesisExpr) and
86-
instr = ttc.getResult()
87-
)
78+
result = IRConstruction::Raw::getTransparentConversionParenthesisExpr(instr)
8879
or
8980
// Certain expressions generate `CopyValueInstruction`s only when they
9081
// are needed. Examples of this include crement operations and compound
@@ -113,10 +104,10 @@ private module Cached {
113104
// needed, and in that case the only value that will propagate forward in
114105
// the program is the value that's been updated. So in those cases we just
115106
// use the result of `node.asDefinition()` as the result of `node.asExpr()`.
116-
exists(TranslatedCoreExpr tco |
117-
tco.getInstruction(_) = instr and
118-
tco.producesExprResult() and
119-
result = asDefinitionImpl0(instr)
107+
exists(StoreInstruction store |
108+
store = instr and
109+
IRConstruction::Raw::instructionProducesExprResult(store) and
110+
result = asDefinitionImpl0(store)
120111
)
121112
or
122113
// IR construction breaks an array aggregate literal `{1, 2, 3}` into a
@@ -146,18 +137,9 @@ private module Cached {
146137
// For an expression such as `i += 2` we pretend that the generated
147138
// `StoreInstruction` contains the result of the expression even though
148139
// this isn't totally aligned with the C/C++ standard.
149-
exists(TranslatedAssignOperation tao |
150-
store = tao.getInstruction(AssignmentStoreTag()) and
151-
result = tao.getExpr()
152-
)
140+
result = IRConstruction::Raw::getAssignOperationStoreExpr(store)
153141
or
154-
// Similarly for `i++` and `++i` we pretend that the generated
155-
// `StoreInstruction` contains the result of the expression even though
156-
// this isn't totally aligned with the C/C++ standard.
157-
exists(TranslatedCrementOperation tco |
158-
store = tco.getInstruction(CrementStoreTag()) and
159-
result = tco.getExpr()
160-
)
142+
result = IRConstruction::Raw::getCrementOperationStoreExpr(store)
161143
}
162144

163145
/**
@@ -167,11 +149,7 @@ private module Cached {
167149
*/
168150
private predicate excludeAsDefinitionResult(StoreInstruction store) {
169151
// Exclude the store to the temporary generated by a ternary expression.
170-
exists(TranslatedConditionalExpr tce |
171-
store = tce.getInstruction(ConditionValueFalseStoreTag())
172-
or
173-
store = tce.getInstruction(ConditionValueTrueStoreTag())
174-
)
152+
IRConstruction::Raw::isConditionalExprTempStore(store)
175153
}
176154

177155
/**

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

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ private import semmle.code.cpp.models.interfaces.PartialFlow as PartialFlow
1010
private import semmle.code.cpp.models.interfaces.FunctionInputsAndOutputs as FIO
1111
private import semmle.code.cpp.ir.internal.IRCppLanguage
1212
private import semmle.code.cpp.ir.dataflow.internal.ModelUtil
13-
private import semmle.code.cpp.ir.implementation.raw.internal.TranslatedInitialization
13+
private import semmle.code.cpp.ir.implementation.raw.internal.IRConstruction as IRConstruction
1414
private import DataFlowPrivate
1515
private import DataFlowNodes
1616
import SsaImplCommon
@@ -439,10 +439,7 @@ private predicate sourceVariableHasBaseAndIndex(SourceVariable v, BaseSourceVari
439439
* initialize `v`.
440440
*/
441441
private Instruction getInitializationTargetAddress(IRVariable v) {
442-
exists(TranslatedVariableInitialization init |
443-
init.getIRVariable() = v and
444-
result = init.getTargetAddress()
445-
)
442+
result = IRConstruction::Raw::getInitializationTargetAddress(v)
446443
}
447444

448445
/** An initial definition of an SSA variable address. */

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

Lines changed: 43 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -10,42 +10,6 @@ private import DataFlowPrivate
1010
private import TypeFlow
1111
private import semmle.code.cpp.ir.ValueNumbering
1212

13-
/**
14-
* Holds if `operand` is an operand that is not used by the dataflow library.
15-
* Ignored operands are not recognized as uses by SSA, and they don't have a
16-
* corresponding `(Indirect)OperandNode`.
17-
*/
18-
predicate ignoreOperand(Operand operand) {
19-
operand = any(Instruction instr | ignoreInstruction(instr)).getAnOperand() or
20-
operand = any(Instruction instr | ignoreInstruction(instr)).getAUse() or
21-
operand instanceof MemoryOperand
22-
}
23-
24-
/**
25-
* Holds if `instr` is an instruction that is not used by the dataflow library.
26-
* Ignored instructions are not recognized as reads/writes by SSA, and they
27-
* don't have a corresponding `(Indirect)InstructionNode`.
28-
*/
29-
predicate ignoreInstruction(Instruction instr) {
30-
DataFlowImplCommon::forceCachingInSameStage() and
31-
(
32-
instr instanceof CallSideEffectInstruction or
33-
instr instanceof CallReadSideEffectInstruction or
34-
instr instanceof ExitFunctionInstruction or
35-
instr instanceof EnterFunctionInstruction or
36-
instr instanceof WriteSideEffectInstruction or
37-
instr instanceof PhiInstruction or
38-
instr instanceof ReadSideEffectInstruction or
39-
instr instanceof ChiInstruction or
40-
instr instanceof InitializeIndirectionInstruction or
41-
instr instanceof AliasedDefinitionInstruction or
42-
instr instanceof AliasedUseInstruction or
43-
instr instanceof InitializeNonLocalInstruction or
44-
instr instanceof ReturnIndirectionInstruction or
45-
instr instanceof UninitializedGroupInstruction
46-
)
47-
}
48-
4913
/**
5014
* Gets the C++ type of `this` in the member function `f`.
5115
* The result is a glvalue if `isGLValue` is true, and
@@ -328,10 +292,6 @@ predicate isWrite(Node0Impl value, Operand address, boolean certain) {
328292
)
329293
}
330294

331-
predicate isAdditionalConversionFlow(Operand opFrom, Instruction instrTo) {
332-
any(Indirection ind).isAdditionalConversionFlow(opFrom, instrTo)
333-
}
334-
335295
newtype TBaseSourceVariable =
336296
// Each IR variable gets its own source variable
337297
TBaseIRVariable(IRVariable var) or
@@ -553,6 +513,49 @@ private class BaseCallInstruction extends BaseSourceVariableInstruction, CallIns
553513

554514
cached
555515
private module Cached {
516+
/**
517+
* Holds if `operand` is an operand that is not used by the dataflow library.
518+
* Ignored operands are not recognized as uses by SSA, and they don't have a
519+
* corresponding `(Indirect)OperandNode`.
520+
*/
521+
cached
522+
predicate ignoreOperand(Operand operand) {
523+
operand = any(Instruction instr | ignoreInstruction(instr)).getAnOperand() or
524+
operand = any(Instruction instr | ignoreInstruction(instr)).getAUse() or
525+
operand instanceof MemoryOperand
526+
}
527+
528+
/**
529+
* Holds if `instr` is an instruction that is not used by the dataflow library.
530+
* Ignored instructions are not recognized as reads/writes by SSA, and they
531+
* don't have a corresponding `(Indirect)InstructionNode`.
532+
*/
533+
cached
534+
predicate ignoreInstruction(Instruction instr) {
535+
DataFlowImplCommon::forceCachingInSameStage() and
536+
(
537+
instr instanceof CallSideEffectInstruction or
538+
instr instanceof CallReadSideEffectInstruction or
539+
instr instanceof ExitFunctionInstruction or
540+
instr instanceof EnterFunctionInstruction or
541+
instr instanceof WriteSideEffectInstruction or
542+
instr instanceof PhiInstruction or
543+
instr instanceof ReadSideEffectInstruction or
544+
instr instanceof ChiInstruction or
545+
instr instanceof InitializeIndirectionInstruction or
546+
instr instanceof AliasedDefinitionInstruction or
547+
instr instanceof AliasedUseInstruction or
548+
instr instanceof InitializeNonLocalInstruction or
549+
instr instanceof ReturnIndirectionInstruction or
550+
instr instanceof UninitializedGroupInstruction
551+
)
552+
}
553+
554+
cached
555+
predicate isAdditionalConversionFlow(Operand opFrom, Instruction instrTo) {
556+
any(Indirection ind).isAdditionalConversionFlow(opFrom, instrTo)
557+
}
558+
556559
/**
557560
* Gets the C++ type of the instruction `i`.
558561
*

cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ private import TranslatedCall
1515
private import TranslatedStmt
1616
private import TranslatedFunction
1717
private import TranslatedGlobalVar
18+
private import TranslatedInitialization
1819

1920
TranslatedElement getInstructionTranslatedElement(Instruction instruction) {
2021
instruction = TRawInstruction(result, _)
@@ -194,6 +195,89 @@ module Raw {
194195
Expr getInstructionUnconvertedResultExpression(Instruction instruction) {
195196
result = getInstructionConvertedResultExpression(instruction).getUnconverted()
196197
}
198+
199+
/**
200+
* Gets the expression associated with the instruction `instr` that computes
201+
* the `Convert` instruction on the extent expression of an allocation.
202+
*/
203+
cached
204+
Expr getAllocationExtentConvertExpr(Instruction instr) {
205+
exists(TranslatedNonConstantAllocationSize tas |
206+
instr = tas.getInstruction(AllocationExtentConvertTag()) and
207+
result = tas.getExtent().getExpr()
208+
)
209+
}
210+
211+
/**
212+
* Gets the `ParenthesisExpr` associated with a transparent conversion
213+
* instruction, if any.
214+
*/
215+
cached
216+
ParenthesisExpr getTransparentConversionParenthesisExpr(Instruction instr) {
217+
exists(TranslatedTransparentConversion ttc |
218+
result = ttc.getExpr() and
219+
instr = ttc.getResult()
220+
)
221+
}
222+
223+
/**
224+
* Holds if `instr` belongs to a `TranslatedCoreExpr` that produces an
225+
* expression result. This indicates that the instruction represents a
226+
* definition whose result should be mapped back to the expression.
227+
*/
228+
cached
229+
predicate instructionProducesExprResult(Instruction instr) {
230+
exists(TranslatedCoreExpr tco |
231+
tco.getInstruction(_) = instr and
232+
tco.producesExprResult()
233+
)
234+
}
235+
236+
/**
237+
* Gets the expression associated with a `StoreInstruction` generated
238+
* by an `TranslatedAssignOperation`.
239+
*/
240+
cached
241+
Expr getAssignOperationStoreExpr(StoreInstruction store) {
242+
exists(TranslatedAssignOperation tao |
243+
store = tao.getInstruction(AssignmentStoreTag()) and
244+
result = tao.getExpr()
245+
)
246+
}
247+
248+
/**
249+
* Gets the expression associated with a `StoreInstruction` generated
250+
* by an `TranslatedCrementOperation`.
251+
*/
252+
cached
253+
Expr getCrementOperationStoreExpr(StoreInstruction store) {
254+
exists(TranslatedCrementOperation tco |
255+
store = tco.getInstruction(CrementStoreTag()) and
256+
result = tco.getExpr()
257+
)
258+
}
259+
260+
/**
261+
* Holds if `store` is a `StoreInstruction` that defines the temporary
262+
* `IRVariable` generated as part of the translation of a ternary expression.
263+
*/
264+
cached
265+
predicate isConditionalExprTempStore(StoreInstruction store) {
266+
exists(TranslatedConditionalExpr tce |
267+
store = tce.getInstruction(ConditionValueFalseStoreTag())
268+
or
269+
store = tce.getInstruction(ConditionValueTrueStoreTag())
270+
)
271+
}
272+
273+
/** Gets the instruction that computes the address used to initialize `v`. */
274+
cached
275+
Instruction getInitializationTargetAddress(IRVariable v) {
276+
exists(TranslatedVariableInitialization init |
277+
init.getIRVariable() = v and
278+
result = init.getTargetAddress()
279+
)
280+
}
197281
}
198282

199283
class TStageInstruction = TRawInstruction or TRawUnreachedInstruction;

0 commit comments

Comments
 (0)