Skip to content

Commit 27cee9b

Browse files
C++: Handle inheritance conversions in IR GVN
1 parent bd15675 commit 27cee9b

File tree

6 files changed

+132
-24
lines changed

6 files changed

+132
-24
lines changed

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

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ newtype TValueNumber =
4545
TUnaryValueNumber(FunctionIR funcIR, Opcode opcode, Type type, ValueNumber operand) {
4646
unaryValueNumber(_, funcIR, opcode, type, operand)
4747
} or
48+
TInheritanceConversionValueNumber(FunctionIR funcIR, Opcode opcode, Class baseClass,
49+
Class derivedClass, ValueNumber operand) {
50+
inheritanceConversionValueNumber(_, funcIR, opcode, baseClass, derivedClass, operand)
51+
} or
4852
TUniqueValueNumber(FunctionIR funcIR, Instruction instr) {
4953
uniqueValueNumber(instr, funcIR)
5054
}
@@ -81,13 +85,6 @@ class ValueNumber extends TValueNumber {
8185
}
8286
}
8387

84-
class BinaryValueNumber extends ValueNumber, TBinaryValueNumber {}
85-
class UnaryValueNumber extends ValueNumber, TUnaryValueNumber {}
86-
class ConstantValueNumber extends ValueNumber, TConstantValueNumber {}
87-
class FieldAddressValueNumber extends ValueNumber, TFieldAddressValueNumber {}
88-
class PointerArithmeticValueNumber extends ValueNumber, TPointerArithmeticValueNumber {}
89-
class UniqueValueNumber extends ValueNumber, TUniqueValueNumber {}
90-
9188
/**
9289
* A `CopyInstruction` whose source operand's value is congruent to the definition of that source
9390
* operand.
@@ -187,12 +184,20 @@ private predicate unaryValueNumber(UnaryInstruction instr, FunctionIR funcIR, Op
187184
Type type, ValueNumber operand) {
188185
instr.getFunctionIR() = funcIR and
189186
(not instr instanceof InheritanceConversionInstruction) and
190-
(not instr instanceof FieldAddressInstruction) and
191187
instr.getOpcode() = opcode and
192188
instr.getResultType() = type and
193189
valueNumber(instr.getOperand()) = operand
194190
}
195191

192+
private predicate inheritanceConversionValueNumber(InheritanceConversionInstruction instr,
193+
FunctionIR funcIR, Opcode opcode, Class baseClass, Class derivedClass, ValueNumber operand) {
194+
instr.getFunctionIR() = funcIR and
195+
instr.getOpcode() = opcode and
196+
instr.getBaseClass() = baseClass and
197+
instr.getDerivedClass() = derivedClass and
198+
valueNumber(instr.getOperand()) = operand
199+
}
200+
196201
/**
197202
* Holds if `instr` should be assigned a unique value number because this library does not know how
198203
* to determine if two instances of that instruction are equivalent.
@@ -250,6 +255,11 @@ private ValueNumber nonUniqueValueNumber(Instruction instr) {
250255
unaryValueNumber(instr, funcIR, opcode, type, operand) and
251256
result = TUnaryValueNumber(funcIR, opcode, type, operand)
252257
) or
258+
exists(Opcode opcode, Class baseClass, Class derivedClass, ValueNumber operand |
259+
inheritanceConversionValueNumber(instr, funcIR, opcode, baseClass, derivedClass,
260+
operand) and
261+
result = TInheritanceConversionValueNumber(funcIR, opcode, baseClass, derivedClass, operand)
262+
) or
253263
exists(Opcode opcode, Type type, int elementSize, ValueNumber leftOperand,
254264
ValueNumber rightOperand |
255265
pointerArithmeticValueNumber(instr, funcIR, opcode, type, elementSize, leftOperand,

cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/gvn/ValueNumber.qll

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ newtype TValueNumber =
4545
TUnaryValueNumber(FunctionIR funcIR, Opcode opcode, Type type, ValueNumber operand) {
4646
unaryValueNumber(_, funcIR, opcode, type, operand)
4747
} or
48+
TInheritanceConversionValueNumber(FunctionIR funcIR, Opcode opcode, Class baseClass,
49+
Class derivedClass, ValueNumber operand) {
50+
inheritanceConversionValueNumber(_, funcIR, opcode, baseClass, derivedClass, operand)
51+
} or
4852
TUniqueValueNumber(FunctionIR funcIR, Instruction instr) {
4953
uniqueValueNumber(instr, funcIR)
5054
}
@@ -81,13 +85,6 @@ class ValueNumber extends TValueNumber {
8185
}
8286
}
8387

84-
class BinaryValueNumber extends ValueNumber, TBinaryValueNumber {}
85-
class UnaryValueNumber extends ValueNumber, TUnaryValueNumber {}
86-
class ConstantValueNumber extends ValueNumber, TConstantValueNumber {}
87-
class FieldAddressValueNumber extends ValueNumber, TFieldAddressValueNumber {}
88-
class PointerArithmeticValueNumber extends ValueNumber, TPointerArithmeticValueNumber {}
89-
class UniqueValueNumber extends ValueNumber, TUniqueValueNumber {}
90-
9188
/**
9289
* A `CopyInstruction` whose source operand's value is congruent to the definition of that source
9390
* operand.
@@ -187,12 +184,20 @@ private predicate unaryValueNumber(UnaryInstruction instr, FunctionIR funcIR, Op
187184
Type type, ValueNumber operand) {
188185
instr.getFunctionIR() = funcIR and
189186
(not instr instanceof InheritanceConversionInstruction) and
190-
(not instr instanceof FieldAddressInstruction) and
191187
instr.getOpcode() = opcode and
192188
instr.getResultType() = type and
193189
valueNumber(instr.getOperand()) = operand
194190
}
195191

192+
private predicate inheritanceConversionValueNumber(InheritanceConversionInstruction instr,
193+
FunctionIR funcIR, Opcode opcode, Class baseClass, Class derivedClass, ValueNumber operand) {
194+
instr.getFunctionIR() = funcIR and
195+
instr.getOpcode() = opcode and
196+
instr.getBaseClass() = baseClass and
197+
instr.getDerivedClass() = derivedClass and
198+
valueNumber(instr.getOperand()) = operand
199+
}
200+
196201
/**
197202
* Holds if `instr` should be assigned a unique value number because this library does not know how
198203
* to determine if two instances of that instruction are equivalent.
@@ -250,6 +255,11 @@ private ValueNumber nonUniqueValueNumber(Instruction instr) {
250255
unaryValueNumber(instr, funcIR, opcode, type, operand) and
251256
result = TUnaryValueNumber(funcIR, opcode, type, operand)
252257
) or
258+
exists(Opcode opcode, Class baseClass, Class derivedClass, ValueNumber operand |
259+
inheritanceConversionValueNumber(instr, funcIR, opcode, baseClass, derivedClass,
260+
operand) and
261+
result = TInheritanceConversionValueNumber(funcIR, opcode, baseClass, derivedClass, operand)
262+
) or
253263
exists(Opcode opcode, Type type, int elementSize, ValueNumber leftOperand,
254264
ValueNumber rightOperand |
255265
pointerArithmeticValueNumber(instr, funcIR, opcode, type, elementSize, leftOperand,

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

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ newtype TValueNumber =
4545
TUnaryValueNumber(FunctionIR funcIR, Opcode opcode, Type type, ValueNumber operand) {
4646
unaryValueNumber(_, funcIR, opcode, type, operand)
4747
} or
48+
TInheritanceConversionValueNumber(FunctionIR funcIR, Opcode opcode, Class baseClass,
49+
Class derivedClass, ValueNumber operand) {
50+
inheritanceConversionValueNumber(_, funcIR, opcode, baseClass, derivedClass, operand)
51+
} or
4852
TUniqueValueNumber(FunctionIR funcIR, Instruction instr) {
4953
uniqueValueNumber(instr, funcIR)
5054
}
@@ -81,13 +85,6 @@ class ValueNumber extends TValueNumber {
8185
}
8286
}
8387

84-
class BinaryValueNumber extends ValueNumber, TBinaryValueNumber {}
85-
class UnaryValueNumber extends ValueNumber, TUnaryValueNumber {}
86-
class ConstantValueNumber extends ValueNumber, TConstantValueNumber {}
87-
class FieldAddressValueNumber extends ValueNumber, TFieldAddressValueNumber {}
88-
class PointerArithmeticValueNumber extends ValueNumber, TPointerArithmeticValueNumber {}
89-
class UniqueValueNumber extends ValueNumber, TUniqueValueNumber {}
90-
9188
/**
9289
* A `CopyInstruction` whose source operand's value is congruent to the definition of that source
9390
* operand.
@@ -187,12 +184,20 @@ private predicate unaryValueNumber(UnaryInstruction instr, FunctionIR funcIR, Op
187184
Type type, ValueNumber operand) {
188185
instr.getFunctionIR() = funcIR and
189186
(not instr instanceof InheritanceConversionInstruction) and
190-
(not instr instanceof FieldAddressInstruction) and
191187
instr.getOpcode() = opcode and
192188
instr.getResultType() = type and
193189
valueNumber(instr.getOperand()) = operand
194190
}
195191

192+
private predicate inheritanceConversionValueNumber(InheritanceConversionInstruction instr,
193+
FunctionIR funcIR, Opcode opcode, Class baseClass, Class derivedClass, ValueNumber operand) {
194+
instr.getFunctionIR() = funcIR and
195+
instr.getOpcode() = opcode and
196+
instr.getBaseClass() = baseClass and
197+
instr.getDerivedClass() = derivedClass and
198+
valueNumber(instr.getOperand()) = operand
199+
}
200+
196201
/**
197202
* Holds if `instr` should be assigned a unique value number because this library does not know how
198203
* to determine if two instances of that instruction are equivalent.
@@ -250,6 +255,11 @@ private ValueNumber nonUniqueValueNumber(Instruction instr) {
250255
unaryValueNumber(instr, funcIR, opcode, type, operand) and
251256
result = TUnaryValueNumber(funcIR, opcode, type, operand)
252257
) or
258+
exists(Opcode opcode, Class baseClass, Class derivedClass, ValueNumber operand |
259+
inheritanceConversionValueNumber(instr, funcIR, opcode, baseClass, derivedClass,
260+
operand) and
261+
result = TInheritanceConversionValueNumber(funcIR, opcode, baseClass, derivedClass, operand)
262+
) or
253263
exists(Opcode opcode, Type type, int elementSize, ValueNumber leftOperand,
254264
ValueNumber rightOperand |
255265
pointerArithmeticValueNumber(instr, funcIR, opcode, type, elementSize, leftOperand,

cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/GlobalValueNumbering.expected

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,6 @@
2727
| test.cpp:62:5:62:10 | result | 62:c5-c10 65:c10-c15 |
2828
| test.cpp:77:20:77:30 | (signed short)... | 77:c20-c30 79:c7-c7 |
2929
| test.cpp:79:11:79:14 | vals | 79:c11-c14 79:c24-c27 |
30+
| test.cpp:105:11:105:12 | (Base *)... | 105:c11-c12 106:c14-c35 107:c11-c12 |
31+
| test.cpp:105:11:105:12 | pd | 105:c11-c12 106:c33-c34 |
32+
| test.cpp:105:15:105:15 | b | 105:c15-c15 107:c15-c15 109:c10-c10 |

cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -653,3 +653,62 @@ test.cpp:
653653
# 91| v0_12(void) = ReturnValue : r0_11, m0_10
654654
# 91| v0_13(void) = UnmodeledUse : mu*
655655
# 91| v0_14(void) = ExitFunction :
656+
657+
# 104| inheritanceConversions(Derived *) -> int
658+
# 104| Block 0
659+
# 104| v0_0(void) = EnterFunction :
660+
# 104| mu0_1(unknown) = UnmodeledDefinition :
661+
# 104| valnum = unique
662+
# 104| r0_2(glval<Derived *>) = VariableAddress[pd] :
663+
# 104| valnum = r0_2
664+
# 104| m0_3(Derived *) = InitializeParameter[pd] : r0_2
665+
# 104| valnum = m0_3
666+
# 105| r0_4(glval<int>) = VariableAddress[x] :
667+
# 105| valnum = unique
668+
# 105| r0_5(glval<Derived *>) = VariableAddress[pd] :
669+
# 105| valnum = r0_2
670+
# 105| r0_6(Derived *) = Load : r0_5, m0_3
671+
# 105| valnum = m0_3
672+
# 105| r0_7(Base *) = ConvertToBase[Derived : Base] : r0_6
673+
# 105| valnum = r0_7
674+
# 105| r0_8(glval<int>) = FieldAddress[b] : r0_7
675+
# 105| valnum = r0_8
676+
# 105| r0_9(int) = Load : r0_8, mu0_1
677+
# 105| valnum = r0_9
678+
# 105| m0_10(int) = Store : r0_4, r0_9
679+
# 105| valnum = r0_9
680+
# 106| r0_11(glval<Base *>) = VariableAddress[pb] :
681+
# 106| valnum = r0_11
682+
# 106| r0_12(glval<Derived *>) = VariableAddress[pd] :
683+
# 106| valnum = r0_2
684+
# 106| r0_13(Derived *) = Load : r0_12, m0_3
685+
# 106| valnum = m0_3
686+
# 106| r0_14(Base *) = ConvertToBase[Derived : Base] : r0_13
687+
# 106| valnum = r0_7
688+
# 106| m0_15(Base *) = Store : r0_11, r0_14
689+
# 106| valnum = r0_7
690+
# 107| r0_16(glval<int>) = VariableAddress[y] :
691+
# 107| valnum = r0_16
692+
# 107| r0_17(glval<Base *>) = VariableAddress[pb] :
693+
# 107| valnum = r0_11
694+
# 107| r0_18(Base *) = Load : r0_17, m0_15
695+
# 107| valnum = r0_7
696+
# 107| r0_19(glval<int>) = FieldAddress[b] : r0_18
697+
# 107| valnum = r0_8
698+
# 107| r0_20(int) = Load : r0_19, mu0_1
699+
# 107| valnum = r0_20
700+
# 107| m0_21(int) = Store : r0_16, r0_20
701+
# 107| valnum = r0_20
702+
# 109| r0_22(glval<int>) = VariableAddress[#return] :
703+
# 109| valnum = r0_22
704+
# 109| r0_23(glval<int>) = VariableAddress[y] :
705+
# 109| valnum = r0_16
706+
# 109| r0_24(int) = Load : r0_23, m0_21
707+
# 109| valnum = r0_20
708+
# 109| m0_25(int) = Store : r0_22, r0_24
709+
# 109| valnum = r0_20
710+
# 104| r0_26(glval<int>) = VariableAddress[#return] :
711+
# 104| valnum = r0_22
712+
# 104| v0_27(void) = ReturnValue : r0_26, m0_25
713+
# 104| v0_28(void) = UnmodeledUse : mu*
714+
# 104| v0_29(void) = ExitFunction :

cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/test.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,3 +92,19 @@ int regression_test00() {
9292
int x = x = 10;
9393
return x;
9494
}
95+
96+
struct Base {
97+
int b;
98+
};
99+
100+
struct Derived : Base {
101+
int d;
102+
};
103+
104+
int inheritanceConversions(Derived* pd) {
105+
int x = pd->b;
106+
Base* pb = static_cast<Base*>(pd);
107+
int y = pb->b;
108+
109+
return y;
110+
}

0 commit comments

Comments
 (0)