Skip to content

Commit 6837233

Browse files
author
Dave Bartolomeo
committed
Treat CallSideEffect and InitializeDynamicAllocation the same as other side effects during IR generation
This commit moves the IR generation for the `CallSideEffect` and `InitializeDynamicAllocation` side effect instruction into their own subclasses of `TranslatedSideEffect`. Previously, they were embeddded in `TranslatedCall` and `TranslatedAllocationSideEffects`. There are no diffs in the generated IR. This just makes the implementation of all side effect generation be consistent.
1 parent d1e6813 commit 6837233

File tree

3 files changed

+162
-147
lines changed

3 files changed

+162
-147
lines changed

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

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -112,28 +112,41 @@ private predicate hasDefaultSideEffect(Call call, ParameterIndex i, boolean buff
112112
}
113113

114114
/**
115-
* Gets the `SideEffectFunction` called by the specified expression.class, if known.
115+
* A `Call` or `NewOrNewArrayExpr`.
116116
*
117-
* Thie will return a result only for `Call`, in which case it returns the target of the call, or
118-
* for `NewExpr` and `NewArrayExpr`, in which case it returns the allocator function called by the
119-
* expression.
117+
* Both kinds of expression invoke a function as part of their evaluation. This class provides a
118+
* way to treat both kinds of function similarly, and to get the invoked `Function`.
120119
*/
121-
private SideEffectFunction getCallOrAllocationSideEffectFunction(Expr expr) {
122-
result = expr.(Call).getTarget()
123-
or
124-
result = expr.(NewOrNewArrayExpr).getAllocator()
120+
class CallOrAllocationExpr extends Expr {
121+
CallOrAllocationExpr() {
122+
this instanceof Call
123+
or
124+
this instanceof NewOrNewArrayExpr
125+
}
126+
127+
/** Gets the `Function` invoked by this expression, if known. */
128+
final Function getTarget() {
129+
result = this.(Call).getTarget()
130+
or
131+
result = this.(NewOrNewArrayExpr).getAllocator()
132+
}
125133
}
126134

127135
/**
128136
* Returns the side effect opcode, if any, that represents any side effects not specifically modeled
129137
* by an argument side effect.
130138
*/
131-
Opcode getCallSideEffectOpcode(Expr expr) {
132-
if not getCallOrAllocationSideEffectFunction(expr).hasOnlySpecificWriteSideEffects()
133-
then result instanceof Opcode::CallSideEffect
134-
else (
135-
not getCallOrAllocationSideEffectFunction(expr).hasOnlySpecificReadSideEffects() and
136-
result instanceof Opcode::CallReadSideEffect
139+
Opcode getCallSideEffectOpcode(CallOrAllocationExpr expr) {
140+
not exists(expr.getTarget().(SideEffectFunction)) and result instanceof Opcode::CallSideEffect
141+
or
142+
exists(SideEffectFunction sideEffectFunction |
143+
sideEffectFunction = expr.getTarget() and
144+
if not sideEffectFunction.hasOnlySpecificWriteSideEffects()
145+
then result instanceof Opcode::CallSideEffect
146+
else (
147+
not sideEffectFunction.hasOnlySpecificReadSideEffects() and
148+
result instanceof Opcode::CallReadSideEffect
149+
)
137150
)
138151
}
139152

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

Lines changed: 111 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -49,16 +49,6 @@ abstract class TranslatedCall extends TranslatedExpr {
4949
tag = CallTag() and
5050
opcode instanceof Opcode::Call and
5151
resultType = getTypeForPRValue(getCallResultType())
52-
or
53-
tag = CallSideEffectTag() and
54-
opcode = getCallSideEffectOpcode(expr) and
55-
(
56-
opcode instanceof Opcode::CallSideEffect and
57-
resultType = getUnknownType()
58-
or
59-
opcode instanceof Opcode::CallReadSideEffect and
60-
resultType = getVoidType()
61-
)
6252
}
6353

6454
override Instruction getChildSuccessor(TranslatedElement child) {
@@ -81,25 +71,8 @@ abstract class TranslatedCall extends TranslatedExpr {
8171

8272
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
8373
kind instanceof GotoEdge and
84-
(
85-
(
86-
tag = CallTag() and
87-
if hasSideEffect()
88-
then result = getInstruction(CallSideEffectTag())
89-
else
90-
if hasPreciseSideEffect()
91-
then result = getSideEffects().getFirstInstruction()
92-
else result = getParent().getChildSuccessor(this)
93-
)
94-
or
95-
(
96-
hasSideEffect() and
97-
tag = CallSideEffectTag() and
98-
if hasPreciseSideEffect()
99-
then result = getSideEffects().getFirstInstruction()
100-
else result = getParent().getChildSuccessor(this)
101-
)
102-
)
74+
tag = CallTag() and
75+
result = getSideEffects().getFirstInstruction()
10376
}
10477

10578
override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
@@ -118,15 +91,6 @@ abstract class TranslatedCall extends TranslatedExpr {
11891
)
11992
}
12093

121-
final override CppType getInstructionMemoryOperandType(
122-
InstructionTag tag, TypedOperandTag operandTag
123-
) {
124-
tag = CallSideEffectTag() and
125-
hasSideEffect() and
126-
operandTag instanceof SideEffectOperandTag and
127-
result = getUnknownType()
128-
}
129-
13094
final override Instruction getResult() { result = getInstruction(CallTag()) }
13195

13296
/**
@@ -197,27 +161,25 @@ abstract class TranslatedCall extends TranslatedExpr {
197161
*/
198162
abstract predicate hasArguments();
199163

200-
final private predicate hasSideEffect() { exists(getCallSideEffectOpcode(expr)) }
201-
202-
override Instruction getPrimaryInstructionForSideEffect(InstructionTag tag) {
203-
hasSideEffect() and
204-
tag = CallSideEffectTag() and
205-
result = getResult()
206-
}
207-
208-
predicate hasPreciseSideEffect() { exists(getSideEffects()) }
209-
210164
final TranslatedSideEffects getSideEffects() { result.getExpr() = expr }
211165
}
212166

167+
/**
168+
* The IR translation of the side effects of the parent `TranslatedElement`.
169+
*
170+
* This object does not itself generate the side effect instructions. Instead, its children provide
171+
* the actual side effects, with this object acting as a placeholder so the parent only needs to
172+
* insert this one element at the point where all the side effects are supposed to occur.
173+
*/
213174
abstract class TranslatedSideEffects extends TranslatedElement {
175+
/** Gets the expression whose side effects are being modeled. */
214176
abstract Expr getExpr();
215177

216178
final override Locatable getAST() { result = getExpr() }
217179

218180
final override Function getFunction() { result = getExpr().getEnclosingFunction() }
219181

220-
override TranslatedElement getChild(int i) {
182+
final override TranslatedElement getChild(int i) {
221183
result =
222184
rank[i + 1](TranslatedSideEffect tse, int group, int indexInGroup |
223185
tse.getPrimaryExpr() = getExpr() and
@@ -236,12 +198,21 @@ abstract class TranslatedSideEffects extends TranslatedElement {
236198
)
237199
}
238200

239-
/**
240-
* Gets the `TranslatedFunction` containing this expression.
241-
*/
242-
final TranslatedFunction getEnclosingFunction() {
243-
result = getTranslatedFunction(getExpr().getEnclosingFunction())
201+
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType type) {
202+
none()
203+
}
204+
205+
final override Instruction getFirstInstruction() {
206+
result = getChild(0).getFirstInstruction()
207+
or
208+
// Some functions, like `std::move()`, have no side effects whatsoever.
209+
not exists(getChild(0)) and result = getParent().getChildSuccessor(this)
244210
}
211+
212+
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
213+
214+
/** Gets the primary instruction to be associated with each side effect instruction. */
215+
abstract Instruction getPrimaryInstruction();
245216
}
246217

247218
/**
@@ -345,64 +316,24 @@ class TranslatedStructorCall extends TranslatedFunctionCall {
345316
override predicate hasQualifier() { any() }
346317
}
347318

348-
class TranslatedAllocationSideEffects extends TranslatedSideEffects,
349-
TTranslatedAllocationSideEffects {
350-
AllocationExpr expr;
351-
352-
TranslatedAllocationSideEffects() { this = TTranslatedAllocationSideEffects(expr) }
353-
354-
final override AllocationExpr getExpr() { result = expr }
355-
356-
override string toString() { result = "(allocation side effects for " + expr.toString() + ")" }
357-
358-
override Instruction getFirstInstruction() { result = getInstruction(OnlyInstructionTag()) }
359-
360-
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType type) {
361-
opcode instanceof Opcode::InitializeDynamicAllocation and
362-
tag = OnlyInstructionTag() and
363-
type = getUnknownType()
364-
}
365-
366-
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
367-
tag = OnlyInstructionTag() and
368-
kind = EdgeKind::gotoEdge() and
369-
if exists(getChild(0))
370-
then result = getChild(0).getFirstInstruction()
371-
else result = getParent().getChildSuccessor(this)
372-
}
373-
374-
override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
375-
tag = OnlyInstructionTag() and
376-
operandTag = addressOperand() and
377-
result = getPrimaryInstructionForSideEffect(OnlyInstructionTag())
378-
}
379-
380-
override Instruction getPrimaryInstructionForSideEffect(InstructionTag tag) {
381-
tag = OnlyInstructionTag() and
382-
if expr instanceof NewOrNewArrayExpr
383-
then result = getTranslatedAllocatorCall(expr).getInstruction(CallTag())
384-
else result = getTranslatedCallInstruction(expr)
385-
}
386-
}
387-
319+
/**
320+
* The IR translation of the side effects of a function call, including the implicit allocator
321+
* call in a `new` or `new[]` expression.
322+
*/
388323
class TranslatedCallSideEffects extends TranslatedSideEffects, TTranslatedCallSideEffects {
389-
Call expr;
324+
Expr expr;
390325

391326
TranslatedCallSideEffects() { this = TTranslatedCallSideEffects(expr) }
392327

393-
override string toString() { result = "(side effects for " + expr.toString() + ")" }
394-
395-
override Call getExpr() { result = expr }
396-
397-
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType type) { none() }
328+
final override string toString() { result = "(side effects for " + expr.toString() + ")" }
398329

399-
override Instruction getFirstInstruction() { result = getChild(0).getFirstInstruction() }
330+
final override Expr getExpr() { result = expr }
400331

401-
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
402-
403-
override Instruction getPrimaryInstructionForSideEffect(InstructionTag tag) {
404-
tag = OnlyInstructionTag() and
405-
result = getTranslatedCallInstruction(expr)
332+
final override Instruction getPrimaryInstruction() {
333+
expr instanceof Call and result = getTranslatedCallInstruction(expr)
334+
or
335+
expr instanceof NewOrNewArrayExpr and
336+
result = getTranslatedAllocatorCall(expr).getInstruction(CallTag())
406337
}
407338
}
408339

@@ -441,6 +372,13 @@ abstract class TranslatedSideEffect extends TranslatedElement {
441372
kind instanceof GotoEdge
442373
}
443374

375+
final override Function getFunction() { result = getParent().getFunction() }
376+
377+
final override Instruction getPrimaryInstructionForSideEffect(InstructionTag tag) {
378+
tag = OnlyInstructionTag() and
379+
result = getParent().(TranslatedSideEffects).getPrimaryInstruction()
380+
}
381+
444382
/**
445383
* Gets the expression that caused this side effect.
446384
*
@@ -490,11 +428,6 @@ abstract class TranslatedArgumentSideEffect extends TranslatedSideEffect {
490428
if isWrite() then group = argumentWriteGroup() else group = argumentReadGroup()
491429
}
492430

493-
override Instruction getPrimaryInstructionForSideEffect(InstructionTag tag) {
494-
tag = OnlyInstructionTag() and
495-
result = getTranslatedCallInstruction(call)
496-
}
497-
498431
final override int getInstructionIndex(InstructionTag tag) {
499432
tag = OnlyInstructionTag() and
500433
result = index
@@ -507,11 +440,6 @@ abstract class TranslatedArgumentSideEffect extends TranslatedSideEffect {
507440
result = getTranslatedFunction(call.getEnclosingFunction())
508441
}
509442

510-
/**
511-
* Gets the `Function` containing this expression.
512-
*/
513-
final override Function getFunction() { result = call.getEnclosingFunction() }
514-
515443
final override predicate sideEffectInstruction(Opcode opcode, CppType type) {
516444
opcode = sideEffectOpcode and
517445
(
@@ -638,3 +566,70 @@ class TranslatedStructorQualifierSideEffect extends TranslatedArgumentSideEffect
638566
)
639567
}
640568
}
569+
570+
/** The IR translation of the non-argument-specific side effect of a call. */
571+
class TranslatedCallSideEffect extends TranslatedSideEffect, TTranslatedCallSideEffect {
572+
Expr expr;
573+
SideEffectOpcode sideEffectOpcode;
574+
575+
TranslatedCallSideEffect() { this = TTranslatedCallSideEffect(expr, sideEffectOpcode) }
576+
577+
override Locatable getAST() { result = expr }
578+
579+
override Expr getPrimaryExpr() { result = expr }
580+
581+
override predicate sortOrder(int group, int indexInGroup) {
582+
group = callSideEffectGroup() and indexInGroup = 0
583+
}
584+
585+
override string toString() { result = "(call side effect for '" + expr.toString() + "')" }
586+
587+
override predicate sideEffectInstruction(Opcode opcode, CppType type) {
588+
opcode = sideEffectOpcode and
589+
(
590+
opcode instanceof Opcode::CallSideEffect and
591+
type = getUnknownType()
592+
or
593+
opcode instanceof Opcode::CallReadSideEffect and
594+
type = getVoidType()
595+
)
596+
}
597+
598+
override CppType getInstructionMemoryOperandType(InstructionTag tag, TypedOperandTag operandTag) {
599+
tag instanceof OnlyInstructionTag and
600+
operandTag instanceof SideEffectOperandTag and
601+
result = getUnknownType()
602+
}
603+
}
604+
605+
/**
606+
* The IR translation of the allocation side effect of a call to a memory allocation function.
607+
*
608+
* This side effect provides a definition for the newly-allocated memory.
609+
*/
610+
class TranslatedAllocationSideEffect extends TranslatedSideEffect, TTranslatedAllocationSideEffect {
611+
AllocationExpr expr;
612+
613+
TranslatedAllocationSideEffect() { this = TTranslatedAllocationSideEffect(expr) }
614+
615+
override Locatable getAST() { result = expr }
616+
617+
override Expr getPrimaryExpr() { result = expr }
618+
619+
override predicate sortOrder(int group, int indexInGroup) {
620+
group = initializeAllocationGroup() and indexInGroup = 0
621+
}
622+
623+
override string toString() { result = "(allocation side effect for '" + expr.toString() + "')" }
624+
625+
override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
626+
tag = OnlyInstructionTag() and
627+
operandTag = addressOperand() and
628+
result = getPrimaryInstructionForSideEffect(OnlyInstructionTag())
629+
}
630+
631+
override predicate sideEffectInstruction(Opcode opcode, CppType type) {
632+
opcode instanceof Opcode::InitializeDynamicAllocation and
633+
type = getUnknownType()
634+
}
635+
}

0 commit comments

Comments
 (0)