Skip to content

Commit b15dd82

Browse files
author
Dave Bartolomeo
committed
C++/C#: Share alias analysis between C++ and C#
1 parent 1b1fded commit b15dd82

11 files changed

Lines changed: 177 additions & 130 deletions

File tree

cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll

Lines changed: 12 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,9 @@
11
private import AliasAnalysisInternal
2-
private import cpp
32
private import InputIR
4-
private import semmle.code.cpp.ir.internal.IntegerConstant as Ints
5-
private import semmle.code.cpp.ir.implementation.IRConfiguration
6-
private import semmle.code.cpp.models.interfaces.Alias
3+
private import AliasAnalysisImports
74

85
private class IntValue = Ints::IntValue;
96

10-
/**
11-
* Gets the offset of field `field` in bits.
12-
*/
13-
private IntValue getFieldBitOffset(Field field) {
14-
if field instanceof BitField
15-
then result = Ints::add(Ints::mul(field.getByteOffset(), 8), field.(BitField).getBitOffset())
16-
else result = Ints::mul(field.getByteOffset(), 8)
17-
}
18-
197
/**
208
* Holds if the operand `tag` of instruction `instr` is used in a way that does
219
* not result in any address held in that operand from escaping beyond the
@@ -36,7 +24,7 @@ private predicate operandIsConsumedWithoutEscaping(Operand operand) {
3624
instr instanceof PointerDiffInstruction
3725
or
3826
// Converting an address to a `bool` does not escape the address.
39-
instr.(ConvertInstruction).getResultType() instanceof BoolType
27+
instr.(ConvertInstruction).getResultIRType() instanceof IRBooleanType
4028
)
4129
)
4230
or
@@ -107,13 +95,10 @@ private predicate operandIsPropagated(Operand operand, IntValue bitOffset) {
10795
bitOffset = Ints::unknown()
10896
or
10997
// Conversion to another pointer type propagates the source address.
110-
exists(ConvertInstruction convert, Type resultType |
98+
exists(ConvertInstruction convert, IRType resultType |
11199
convert = instr and
112-
resultType = convert.getResultType() and
113-
(
114-
resultType instanceof PointerType or
115-
resultType instanceof Class //REVIEW: Remove when all glvalues are pointers
116-
) and
100+
resultType = convert.getResultIRType() and
101+
resultType instanceof IRAddressType and
117102
bitOffset = 0
118103
)
119104
or
@@ -127,7 +112,7 @@ private predicate operandIsPropagated(Operand operand, IntValue bitOffset) {
127112
or
128113
// Computing a field address from a pointer propagates the address plus the
129114
// offset of the field.
130-
bitOffset = getFieldBitOffset(instr.(FieldAddressInstruction).getField())
115+
bitOffset = Language::getFieldBitOffset(instr.(FieldAddressInstruction).getField())
131116
or
132117
// A copy propagates the source value.
133118
operand = instr.(CopyInstruction).getSourceValueOperand() and bitOffset = 0
@@ -208,7 +193,7 @@ private predicate operandReturned(Operand operand, IntValue bitOffset) {
208193
}
209194

210195
private predicate isArgumentForParameter(CallInstruction ci, Operand operand, Instruction init) {
211-
exists(Function f |
196+
exists(Language::Function f |
212197
ci = operand.getUse() and
213198
f = ci.getStaticCallTarget() and
214199
(
@@ -219,27 +204,27 @@ private predicate isArgumentForParameter(CallInstruction ci, Operand operand, In
219204
init.getEnclosingFunction() = f and
220205
operand instanceof ThisArgumentOperand
221206
) and
222-
not f.isVirtual() and
223-
not f instanceof AliasFunction
207+
not Language::isFunctionVirtual(f) and
208+
not f instanceof AliasModels::AliasFunction
224209
)
225210
}
226211

227212
private predicate isAlwaysReturnedArgument(Operand operand) {
228-
exists(AliasFunction f |
213+
exists(AliasModels::AliasFunction f |
229214
f = operand.getUse().(CallInstruction).getStaticCallTarget() and
230215
f.parameterIsAlwaysReturned(operand.(PositionalArgumentOperand).getIndex())
231216
)
232217
}
233218

234219
private predicate isOnlyEscapesViaReturnArgument(Operand operand) {
235-
exists(AliasFunction f |
220+
exists(AliasModels::AliasFunction f |
236221
f = operand.getUse().(CallInstruction).getStaticCallTarget() and
237222
f.parameterEscapesOnlyViaReturn(operand.(PositionalArgumentOperand).getIndex())
238223
)
239224
}
240225

241226
private predicate isNeverEscapesArgument(Operand operand) {
242-
exists(AliasFunction f |
227+
exists(AliasModels::AliasFunction f |
243228
f = operand.getUse().(CallInstruction).getStaticCallTarget() and
244229
f.parameterNeverEscapes(operand.(PositionalArgumentOperand).getIndex())
245230
)
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import semmle.code.cpp.ir.implementation.IRConfiguration
2+
import semmle.code.cpp.ir.internal.IntegerConstant as Ints
3+
import semmle.code.cpp.models.interfaces.Alias as AliasModels
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1+
import semmle.code.cpp.ir.internal.IRCppLanguage as Language
12
import semmle.code.cpp.ir.implementation.unaliased_ssa.IR as InputIR

cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll

Lines changed: 12 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,9 @@
11
private import AliasAnalysisInternal
2-
private import cpp
32
private import InputIR
4-
private import semmle.code.cpp.ir.internal.IntegerConstant as Ints
5-
private import semmle.code.cpp.ir.implementation.IRConfiguration
6-
private import semmle.code.cpp.models.interfaces.Alias
3+
private import AliasAnalysisImports
74

85
private class IntValue = Ints::IntValue;
96

10-
/**
11-
* Gets the offset of field `field` in bits.
12-
*/
13-
private IntValue getFieldBitOffset(Field field) {
14-
if field instanceof BitField
15-
then result = Ints::add(Ints::mul(field.getByteOffset(), 8), field.(BitField).getBitOffset())
16-
else result = Ints::mul(field.getByteOffset(), 8)
17-
}
18-
197
/**
208
* Holds if the operand `tag` of instruction `instr` is used in a way that does
219
* not result in any address held in that operand from escaping beyond the
@@ -36,7 +24,7 @@ private predicate operandIsConsumedWithoutEscaping(Operand operand) {
3624
instr instanceof PointerDiffInstruction
3725
or
3826
// Converting an address to a `bool` does not escape the address.
39-
instr.(ConvertInstruction).getResultType() instanceof BoolType
27+
instr.(ConvertInstruction).getResultIRType() instanceof IRBooleanType
4028
)
4129
)
4230
or
@@ -107,13 +95,10 @@ private predicate operandIsPropagated(Operand operand, IntValue bitOffset) {
10795
bitOffset = Ints::unknown()
10896
or
10997
// Conversion to another pointer type propagates the source address.
110-
exists(ConvertInstruction convert, Type resultType |
98+
exists(ConvertInstruction convert, IRType resultType |
11199
convert = instr and
112-
resultType = convert.getResultType() and
113-
(
114-
resultType instanceof PointerType or
115-
resultType instanceof Class //REVIEW: Remove when all glvalues are pointers
116-
) and
100+
resultType = convert.getResultIRType() and
101+
resultType instanceof IRAddressType and
117102
bitOffset = 0
118103
)
119104
or
@@ -127,7 +112,7 @@ private predicate operandIsPropagated(Operand operand, IntValue bitOffset) {
127112
or
128113
// Computing a field address from a pointer propagates the address plus the
129114
// offset of the field.
130-
bitOffset = getFieldBitOffset(instr.(FieldAddressInstruction).getField())
115+
bitOffset = Language::getFieldBitOffset(instr.(FieldAddressInstruction).getField())
131116
or
132117
// A copy propagates the source value.
133118
operand = instr.(CopyInstruction).getSourceValueOperand() and bitOffset = 0
@@ -208,7 +193,7 @@ private predicate operandReturned(Operand operand, IntValue bitOffset) {
208193
}
209194

210195
private predicate isArgumentForParameter(CallInstruction ci, Operand operand, Instruction init) {
211-
exists(Function f |
196+
exists(Language::Function f |
212197
ci = operand.getUse() and
213198
f = ci.getStaticCallTarget() and
214199
(
@@ -219,27 +204,27 @@ private predicate isArgumentForParameter(CallInstruction ci, Operand operand, In
219204
init.getEnclosingFunction() = f and
220205
operand instanceof ThisArgumentOperand
221206
) and
222-
not f.isVirtual() and
223-
not f instanceof AliasFunction
207+
not Language::isFunctionVirtual(f) and
208+
not f instanceof AliasModels::AliasFunction
224209
)
225210
}
226211

227212
private predicate isAlwaysReturnedArgument(Operand operand) {
228-
exists(AliasFunction f |
213+
exists(AliasModels::AliasFunction f |
229214
f = operand.getUse().(CallInstruction).getStaticCallTarget() and
230215
f.parameterIsAlwaysReturned(operand.(PositionalArgumentOperand).getIndex())
231216
)
232217
}
233218

234219
private predicate isOnlyEscapesViaReturnArgument(Operand operand) {
235-
exists(AliasFunction f |
220+
exists(AliasModels::AliasFunction f |
236221
f = operand.getUse().(CallInstruction).getStaticCallTarget() and
237222
f.parameterEscapesOnlyViaReturn(operand.(PositionalArgumentOperand).getIndex())
238223
)
239224
}
240225

241226
private predicate isNeverEscapesArgument(Operand operand) {
242-
exists(AliasFunction f |
227+
exists(AliasModels::AliasFunction f |
243228
f = operand.getUse().(CallInstruction).getStaticCallTarget() and
244229
f.parameterNeverEscapes(operand.(PositionalArgumentOperand).getIndex())
245230
)
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import semmle.code.cpp.ir.implementation.IRConfiguration
2+
import semmle.code.cpp.ir.internal.IntegerConstant as Ints
3+
import semmle.code.cpp.models.interfaces.Alias as AliasModels
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1+
import semmle.code.cpp.ir.internal.IRCppLanguage as Language
12
import semmle.code.cpp.ir.implementation.raw.IR as InputIR

cpp/ql/src/semmle/code/cpp/ir/internal/IRCppLanguage.qll

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,17 @@ predicate hasPotentialLoop(Function f) {
8080
}
8181

8282
predicate hasGoto(Function f) { exists(Cpp::GotoStmt s | s.getEnclosingFunction() = f) }
83+
84+
/**
85+
* Gets the offset of field `field` in bits.
86+
*/
87+
int getFieldBitOffset(Field field) {
88+
if field instanceof Cpp::BitField
89+
then result = (field.getByteOffset() * 8) + field.(Cpp::BitField).getBitOffset()
90+
else result = field.getByteOffset() * 8
91+
}
92+
93+
/**
94+
* Holds if the specified `Function` can be overridden in a derived class.
95+
*/
96+
predicate isFunctionVirtual(Function f) { f.isVirtual() }

0 commit comments

Comments
 (0)