Skip to content

Commit 6c12b59

Browse files
author
Dave Bartolomeo
committed
C++/C#: Allow non-Phi memory operands to have no definition
1 parent 9de597d commit 6c12b59

File tree

7 files changed

+111
-92
lines changed

7 files changed

+111
-92
lines changed

cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Operand.qll

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,8 @@ private newtype TOperand =
1414
not Construction::isInCycle(useInstr) and
1515
strictcount(Construction::getRegisterOperandDefinition(useInstr, tag)) = 1
1616
} or
17-
TNonPhiMemoryOperand(
18-
Instruction useInstr, MemoryOperandTag tag, Instruction defInstr, Overlap overlap
19-
) {
20-
defInstr = Construction::getMemoryOperandDefinition(useInstr, tag, overlap) and
21-
not Construction::isInCycle(useInstr) and
22-
strictcount(Construction::getMemoryOperandDefinition(useInstr, tag, _)) = 1
17+
TNonPhiMemoryOperand(Instruction useInstr, MemoryOperandTag tag) {
18+
useInstr.getOpcode().hasOperand(tag)
2319
} or
2420
TPhiOperand(
2521
PhiInstruction useInstr, Instruction defInstr, IRBlock predecessorBlock, Overlap overlap
@@ -45,10 +41,8 @@ private class NonPhiMemoryOperandBase extends OperandBase, TNonPhiMemoryOperand
4541
abstract override string toString();
4642
}
4743

48-
private NonPhiMemoryOperandBase nonPhiMemoryOperand(
49-
Instruction useInstr, MemoryOperandTag tag, Instruction defInstr, Overlap overlap
50-
) {
51-
result = TNonPhiMemoryOperand(useInstr, tag, defInstr, overlap)
44+
private NonPhiMemoryOperandBase nonPhiMemoryOperand(Instruction useInstr, MemoryOperandTag tag) {
45+
result = TNonPhiMemoryOperand(useInstr, tag)
5246
}
5347

5448
private class PhiOperandBase extends OperandBase, TPhiOperand {
@@ -234,18 +228,15 @@ class MemoryOperand extends Operand {
234228
*/
235229
class NonPhiOperand extends Operand {
236230
Instruction useInstr;
237-
Instruction defInstr;
238231
OperandTag tag;
239232

240233
NonPhiOperand() {
241-
this = registerOperand(useInstr, tag, defInstr) or
242-
this = nonPhiMemoryOperand(useInstr, tag, defInstr, _)
234+
this = registerOperand(useInstr, tag, _) or
235+
this = nonPhiMemoryOperand(useInstr, tag)
243236
}
244237

245238
final override Instruction getUse() { result = useInstr }
246239

247-
final override Instruction getAnyDef() { result = defInstr }
248-
249240
final override string getDumpLabel() { result = tag.getLabel() }
250241

251242
final override int getDumpSortOrder() { result = tag.getSortOrder() }
@@ -258,9 +249,14 @@ class NonPhiOperand extends Operand {
258249
*/
259250
class RegisterOperand extends NonPhiOperand, RegisterOperandBase {
260251
override RegisterOperandTag tag;
252+
Instruction defInstr;
253+
254+
RegisterOperand() { this = registerOperand(useInstr, tag, defInstr) }
261255

262256
final override string toString() { result = tag.toString() }
263257

258+
final override Instruction getAnyDef() { result = defInstr }
259+
264260
final override Overlap getDefinitionOverlap() {
265261
// All register results overlap exactly with their uses.
266262
result instanceof MustExactlyOverlap
@@ -269,13 +265,21 @@ class RegisterOperand extends NonPhiOperand, RegisterOperandBase {
269265

270266
class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, NonPhiMemoryOperandBase {
271267
override MemoryOperandTag tag;
272-
Overlap overlap;
273268

274-
NonPhiMemoryOperand() { this = TNonPhiMemoryOperand(useInstr, tag, defInstr, overlap) }
269+
NonPhiMemoryOperand() { this = nonPhiMemoryOperand(useInstr, tag) }
275270

276271
final override string toString() { result = tag.toString() }
277272

278-
final override Overlap getDefinitionOverlap() { result = overlap }
273+
final override Instruction getAnyDef() { hasDefinition(result, _) }
274+
275+
final override Overlap getDefinitionOverlap() { hasDefinition(_, result) }
276+
277+
pragma[noinline]
278+
private predicate hasDefinition(Instruction defInstr, Overlap overlap) {
279+
defInstr = Construction::getMemoryOperandDefinition(useInstr, tag, overlap) and
280+
not Construction::isInCycle(useInstr) and
281+
strictcount(Construction::getMemoryOperandDefinition(useInstr, tag, _)) = 1
282+
}
279283
}
280284

281285
class TypedOperand extends NonPhiMemoryOperand {

cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Operand.qll

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,8 @@ private newtype TOperand =
1414
not Construction::isInCycle(useInstr) and
1515
strictcount(Construction::getRegisterOperandDefinition(useInstr, tag)) = 1
1616
} or
17-
TNonPhiMemoryOperand(
18-
Instruction useInstr, MemoryOperandTag tag, Instruction defInstr, Overlap overlap
19-
) {
20-
defInstr = Construction::getMemoryOperandDefinition(useInstr, tag, overlap) and
21-
not Construction::isInCycle(useInstr) and
22-
strictcount(Construction::getMemoryOperandDefinition(useInstr, tag, _)) = 1
17+
TNonPhiMemoryOperand(Instruction useInstr, MemoryOperandTag tag) {
18+
useInstr.getOpcode().hasOperand(tag)
2319
} or
2420
TPhiOperand(
2521
PhiInstruction useInstr, Instruction defInstr, IRBlock predecessorBlock, Overlap overlap
@@ -45,10 +41,8 @@ private class NonPhiMemoryOperandBase extends OperandBase, TNonPhiMemoryOperand
4541
abstract override string toString();
4642
}
4743

48-
private NonPhiMemoryOperandBase nonPhiMemoryOperand(
49-
Instruction useInstr, MemoryOperandTag tag, Instruction defInstr, Overlap overlap
50-
) {
51-
result = TNonPhiMemoryOperand(useInstr, tag, defInstr, overlap)
44+
private NonPhiMemoryOperandBase nonPhiMemoryOperand(Instruction useInstr, MemoryOperandTag tag) {
45+
result = TNonPhiMemoryOperand(useInstr, tag)
5246
}
5347

5448
private class PhiOperandBase extends OperandBase, TPhiOperand {
@@ -234,18 +228,15 @@ class MemoryOperand extends Operand {
234228
*/
235229
class NonPhiOperand extends Operand {
236230
Instruction useInstr;
237-
Instruction defInstr;
238231
OperandTag tag;
239232

240233
NonPhiOperand() {
241-
this = registerOperand(useInstr, tag, defInstr) or
242-
this = nonPhiMemoryOperand(useInstr, tag, defInstr, _)
234+
this = registerOperand(useInstr, tag, _) or
235+
this = nonPhiMemoryOperand(useInstr, tag)
243236
}
244237

245238
final override Instruction getUse() { result = useInstr }
246239

247-
final override Instruction getAnyDef() { result = defInstr }
248-
249240
final override string getDumpLabel() { result = tag.getLabel() }
250241

251242
final override int getDumpSortOrder() { result = tag.getSortOrder() }
@@ -258,9 +249,14 @@ class NonPhiOperand extends Operand {
258249
*/
259250
class RegisterOperand extends NonPhiOperand, RegisterOperandBase {
260251
override RegisterOperandTag tag;
252+
Instruction defInstr;
253+
254+
RegisterOperand() { this = registerOperand(useInstr, tag, defInstr) }
261255

262256
final override string toString() { result = tag.toString() }
263257

258+
final override Instruction getAnyDef() { result = defInstr }
259+
264260
final override Overlap getDefinitionOverlap() {
265261
// All register results overlap exactly with their uses.
266262
result instanceof MustExactlyOverlap
@@ -269,13 +265,21 @@ class RegisterOperand extends NonPhiOperand, RegisterOperandBase {
269265

270266
class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, NonPhiMemoryOperandBase {
271267
override MemoryOperandTag tag;
272-
Overlap overlap;
273268

274-
NonPhiMemoryOperand() { this = TNonPhiMemoryOperand(useInstr, tag, defInstr, overlap) }
269+
NonPhiMemoryOperand() { this = nonPhiMemoryOperand(useInstr, tag) }
275270

276271
final override string toString() { result = tag.toString() }
277272

278-
final override Overlap getDefinitionOverlap() { result = overlap }
273+
final override Instruction getAnyDef() { hasDefinition(result, _) }
274+
275+
final override Overlap getDefinitionOverlap() { hasDefinition(_, result) }
276+
277+
pragma[noinline]
278+
private predicate hasDefinition(Instruction defInstr, Overlap overlap) {
279+
defInstr = Construction::getMemoryOperandDefinition(useInstr, tag, overlap) and
280+
not Construction::isInCycle(useInstr) and
281+
strictcount(Construction::getMemoryOperandDefinition(useInstr, tag, _)) = 1
282+
}
279283
}
280284

281285
class TypedOperand extends NonPhiMemoryOperand {

cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Operand.qll

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,8 @@ private newtype TOperand =
1414
not Construction::isInCycle(useInstr) and
1515
strictcount(Construction::getRegisterOperandDefinition(useInstr, tag)) = 1
1616
} or
17-
TNonPhiMemoryOperand(
18-
Instruction useInstr, MemoryOperandTag tag, Instruction defInstr, Overlap overlap
19-
) {
20-
defInstr = Construction::getMemoryOperandDefinition(useInstr, tag, overlap) and
21-
not Construction::isInCycle(useInstr) and
22-
strictcount(Construction::getMemoryOperandDefinition(useInstr, tag, _)) = 1
17+
TNonPhiMemoryOperand(Instruction useInstr, MemoryOperandTag tag) {
18+
useInstr.getOpcode().hasOperand(tag)
2319
} or
2420
TPhiOperand(
2521
PhiInstruction useInstr, Instruction defInstr, IRBlock predecessorBlock, Overlap overlap
@@ -45,10 +41,8 @@ private class NonPhiMemoryOperandBase extends OperandBase, TNonPhiMemoryOperand
4541
abstract override string toString();
4642
}
4743

48-
private NonPhiMemoryOperandBase nonPhiMemoryOperand(
49-
Instruction useInstr, MemoryOperandTag tag, Instruction defInstr, Overlap overlap
50-
) {
51-
result = TNonPhiMemoryOperand(useInstr, tag, defInstr, overlap)
44+
private NonPhiMemoryOperandBase nonPhiMemoryOperand(Instruction useInstr, MemoryOperandTag tag) {
45+
result = TNonPhiMemoryOperand(useInstr, tag)
5246
}
5347

5448
private class PhiOperandBase extends OperandBase, TPhiOperand {
@@ -234,18 +228,15 @@ class MemoryOperand extends Operand {
234228
*/
235229
class NonPhiOperand extends Operand {
236230
Instruction useInstr;
237-
Instruction defInstr;
238231
OperandTag tag;
239232

240233
NonPhiOperand() {
241-
this = registerOperand(useInstr, tag, defInstr) or
242-
this = nonPhiMemoryOperand(useInstr, tag, defInstr, _)
234+
this = registerOperand(useInstr, tag, _) or
235+
this = nonPhiMemoryOperand(useInstr, tag)
243236
}
244237

245238
final override Instruction getUse() { result = useInstr }
246239

247-
final override Instruction getAnyDef() { result = defInstr }
248-
249240
final override string getDumpLabel() { result = tag.getLabel() }
250241

251242
final override int getDumpSortOrder() { result = tag.getSortOrder() }
@@ -258,9 +249,14 @@ class NonPhiOperand extends Operand {
258249
*/
259250
class RegisterOperand extends NonPhiOperand, RegisterOperandBase {
260251
override RegisterOperandTag tag;
252+
Instruction defInstr;
253+
254+
RegisterOperand() { this = registerOperand(useInstr, tag, defInstr) }
261255

262256
final override string toString() { result = tag.toString() }
263257

258+
final override Instruction getAnyDef() { result = defInstr }
259+
264260
final override Overlap getDefinitionOverlap() {
265261
// All register results overlap exactly with their uses.
266262
result instanceof MustExactlyOverlap
@@ -269,13 +265,21 @@ class RegisterOperand extends NonPhiOperand, RegisterOperandBase {
269265

270266
class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, NonPhiMemoryOperandBase {
271267
override MemoryOperandTag tag;
272-
Overlap overlap;
273268

274-
NonPhiMemoryOperand() { this = TNonPhiMemoryOperand(useInstr, tag, defInstr, overlap) }
269+
NonPhiMemoryOperand() { this = nonPhiMemoryOperand(useInstr, tag) }
275270

276271
final override string toString() { result = tag.toString() }
277272

278-
final override Overlap getDefinitionOverlap() { result = overlap }
273+
final override Instruction getAnyDef() { hasDefinition(result, _) }
274+
275+
final override Overlap getDefinitionOverlap() { hasDefinition(_, result) }
276+
277+
pragma[noinline]
278+
private predicate hasDefinition(Instruction defInstr, Overlap overlap) {
279+
defInstr = Construction::getMemoryOperandDefinition(useInstr, tag, overlap) and
280+
not Construction::isInCycle(useInstr) and
281+
strictcount(Construction::getMemoryOperandDefinition(useInstr, tag, _)) = 1
282+
}
279283
}
280284

281285
class TypedOperand extends NonPhiMemoryOperand {

cpp/ql/test/library-tests/ir/ssa/aliased_ssa_consistency_unsound.expected

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
missingOperand
22
unexpectedOperand
33
duplicateOperand
4-
| ssa.cpp:301:27:301:30 | ReturnIndirection: argv | Instruction has 2 operands with tag 'SideEffect' in function '$@'. | ssa.cpp:301:5:301:8 | IR: main | int main(int, char**) |
54
missingPhiOperand
65
missingOperandType
76
duplicateChiOperand

cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir_unsound.expected

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1480,7 +1480,7 @@ ssa.cpp:
14801480
# 304| r304_5(char) = Load : &:r304_4, ~m303_8
14811481
# 304| r304_6(int) = Convert : r304_5
14821482
# 304| m304_7(int) = Store : &:r304_1, r304_6
1483-
# 301| v301_12(void) = ReturnIndirection[argv] : &:r301_10, ~m303_11, m303_11
1483+
# 301| v301_12(void) = ReturnIndirection[argv] : &:r301_10, m303_11
14841484
# 301| r301_13(glval<int>) = VariableAddress[#return] :
14851485
# 301| v301_14(void) = ReturnValue : &:r301_13, m304_7
14861486
# 301| v301_15(void) = AliasedUse : ~m303_8

csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Operand.qll

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,8 @@ private newtype TOperand =
1414
not Construction::isInCycle(useInstr) and
1515
strictcount(Construction::getRegisterOperandDefinition(useInstr, tag)) = 1
1616
} or
17-
TNonPhiMemoryOperand(
18-
Instruction useInstr, MemoryOperandTag tag, Instruction defInstr, Overlap overlap
19-
) {
20-
defInstr = Construction::getMemoryOperandDefinition(useInstr, tag, overlap) and
21-
not Construction::isInCycle(useInstr) and
22-
strictcount(Construction::getMemoryOperandDefinition(useInstr, tag, _)) = 1
17+
TNonPhiMemoryOperand(Instruction useInstr, MemoryOperandTag tag) {
18+
useInstr.getOpcode().hasOperand(tag)
2319
} or
2420
TPhiOperand(
2521
PhiInstruction useInstr, Instruction defInstr, IRBlock predecessorBlock, Overlap overlap
@@ -45,10 +41,8 @@ private class NonPhiMemoryOperandBase extends OperandBase, TNonPhiMemoryOperand
4541
abstract override string toString();
4642
}
4743

48-
private NonPhiMemoryOperandBase nonPhiMemoryOperand(
49-
Instruction useInstr, MemoryOperandTag tag, Instruction defInstr, Overlap overlap
50-
) {
51-
result = TNonPhiMemoryOperand(useInstr, tag, defInstr, overlap)
44+
private NonPhiMemoryOperandBase nonPhiMemoryOperand(Instruction useInstr, MemoryOperandTag tag) {
45+
result = TNonPhiMemoryOperand(useInstr, tag)
5246
}
5347

5448
private class PhiOperandBase extends OperandBase, TPhiOperand {
@@ -234,18 +228,15 @@ class MemoryOperand extends Operand {
234228
*/
235229
class NonPhiOperand extends Operand {
236230
Instruction useInstr;
237-
Instruction defInstr;
238231
OperandTag tag;
239232

240233
NonPhiOperand() {
241-
this = registerOperand(useInstr, tag, defInstr) or
242-
this = nonPhiMemoryOperand(useInstr, tag, defInstr, _)
234+
this = registerOperand(useInstr, tag, _) or
235+
this = nonPhiMemoryOperand(useInstr, tag)
243236
}
244237

245238
final override Instruction getUse() { result = useInstr }
246239

247-
final override Instruction getAnyDef() { result = defInstr }
248-
249240
final override string getDumpLabel() { result = tag.getLabel() }
250241

251242
final override int getDumpSortOrder() { result = tag.getSortOrder() }
@@ -258,9 +249,14 @@ class NonPhiOperand extends Operand {
258249
*/
259250
class RegisterOperand extends NonPhiOperand, RegisterOperandBase {
260251
override RegisterOperandTag tag;
252+
Instruction defInstr;
253+
254+
RegisterOperand() { this = registerOperand(useInstr, tag, defInstr) }
261255

262256
final override string toString() { result = tag.toString() }
263257

258+
final override Instruction getAnyDef() { result = defInstr }
259+
264260
final override Overlap getDefinitionOverlap() {
265261
// All register results overlap exactly with their uses.
266262
result instanceof MustExactlyOverlap
@@ -269,13 +265,21 @@ class RegisterOperand extends NonPhiOperand, RegisterOperandBase {
269265

270266
class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, NonPhiMemoryOperandBase {
271267
override MemoryOperandTag tag;
272-
Overlap overlap;
273268

274-
NonPhiMemoryOperand() { this = TNonPhiMemoryOperand(useInstr, tag, defInstr, overlap) }
269+
NonPhiMemoryOperand() { this = nonPhiMemoryOperand(useInstr, tag) }
275270

276271
final override string toString() { result = tag.toString() }
277272

278-
final override Overlap getDefinitionOverlap() { result = overlap }
273+
final override Instruction getAnyDef() { hasDefinition(result, _) }
274+
275+
final override Overlap getDefinitionOverlap() { hasDefinition(_, result) }
276+
277+
pragma[noinline]
278+
private predicate hasDefinition(Instruction defInstr, Overlap overlap) {
279+
defInstr = Construction::getMemoryOperandDefinition(useInstr, tag, overlap) and
280+
not Construction::isInCycle(useInstr) and
281+
strictcount(Construction::getMemoryOperandDefinition(useInstr, tag, _)) = 1
282+
}
279283
}
280284

281285
class TypedOperand extends NonPhiMemoryOperand {

0 commit comments

Comments
 (0)