Skip to content

Commit 8041804

Browse files
committed
C#: Include TValueNumber in internal files
1 parent 2f91778 commit 8041804

File tree

1 file changed

+269
-1
lines changed

1 file changed

+269
-1
lines changed
Lines changed: 269 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,270 @@
1-
import semmle.code.csharp.ir.implementation.raw.IR as IR
1+
private import ValueNumberingImports
22
import semmle.code.csharp.ir.internal.IRCSharpLanguage as Language
3+
import semmle.code.csharp.ir.implementation.raw.IR
4+
5+
newtype TValueNumber =
6+
TVariableAddressValueNumber(IRFunction irFunc, IRVariable var) {
7+
variableAddressValueNumber(_, irFunc, var)
8+
} or
9+
TInitializeParameterValueNumber(IRFunction irFunc, IRVariable var) {
10+
initializeParameterValueNumber(_, irFunc, var)
11+
} or
12+
TInitializeThisValueNumber(IRFunction irFunc) { initializeThisValueNumber(_, irFunc) } or
13+
TConstantValueNumber(IRFunction irFunc, IRType type, string value) {
14+
constantValueNumber(_, irFunc, type, value)
15+
} or
16+
TStringConstantValueNumber(IRFunction irFunc, IRType type, string value) {
17+
stringConstantValueNumber(_, irFunc, type, value)
18+
} or
19+
TFieldAddressValueNumber(IRFunction irFunc, Language::Field field, TValueNumber objectAddress) {
20+
fieldAddressValueNumber(_, irFunc, field, objectAddress)
21+
} or
22+
TBinaryValueNumber(
23+
IRFunction irFunc, Opcode opcode, IRType type, TValueNumber leftOperand,
24+
TValueNumber rightOperand
25+
) {
26+
binaryValueNumber(_, irFunc, opcode, type, leftOperand, rightOperand)
27+
} or
28+
TPointerArithmeticValueNumber(
29+
IRFunction irFunc, Opcode opcode, IRType type, int elementSize, TValueNumber leftOperand,
30+
TValueNumber rightOperand
31+
) {
32+
pointerArithmeticValueNumber(_, irFunc, opcode, type, elementSize, leftOperand, rightOperand)
33+
} or
34+
TUnaryValueNumber(IRFunction irFunc, Opcode opcode, IRType type, TValueNumber operand) {
35+
unaryValueNumber(_, irFunc, opcode, type, operand)
36+
} or
37+
TInheritanceConversionValueNumber(
38+
IRFunction irFunc, Opcode opcode, Language::Class baseClass, Language::Class derivedClass,
39+
TValueNumber operand
40+
) {
41+
inheritanceConversionValueNumber(_, irFunc, opcode, baseClass, derivedClass, operand)
42+
} or
43+
TUniqueValueNumber(IRFunction irFunc, Instruction instr) { uniqueValueNumber(instr, irFunc) }
44+
45+
/**
46+
* A `CopyInstruction` whose source operand's value is congruent to the definition of that source
47+
* operand.
48+
* For example:
49+
* ```
50+
* Point p = { 1, 2 };
51+
* Point q = p;
52+
* int a = p.x;
53+
* ```
54+
* The use of `p` on line 2 is linked to the definition of `p` on line 1, and is congruent to that
55+
* definition because it accesses the exact same memory.
56+
* The use of `p.x` on line 3 is linked to the definition of `p` on line 1 as well, but is not
57+
* congruent to that definition because `p.x` accesses only a subset of the memory defined by `p`.
58+
*/
59+
private class CongruentCopyInstruction extends CopyInstruction {
60+
CongruentCopyInstruction() {
61+
this.getSourceValueOperand().getDefinitionOverlap() instanceof MustExactlyOverlap
62+
}
63+
}
64+
65+
/**
66+
* Holds if this library knows how to assign a value number to the specified instruction, other than
67+
* a `unique` value number that is never shared by multiple instructions.
68+
*/
69+
private predicate numberableInstruction(Instruction instr) {
70+
instr instanceof VariableAddressInstruction
71+
or
72+
instr instanceof InitializeParameterInstruction
73+
or
74+
instr instanceof InitializeThisInstruction
75+
or
76+
instr instanceof ConstantInstruction
77+
or
78+
instr instanceof StringConstantInstruction
79+
or
80+
instr instanceof FieldAddressInstruction
81+
or
82+
instr instanceof BinaryInstruction
83+
or
84+
instr instanceof UnaryInstruction and not instr instanceof CopyInstruction
85+
or
86+
instr instanceof PointerArithmeticInstruction
87+
or
88+
instr instanceof CongruentCopyInstruction
89+
}
90+
91+
private predicate variableAddressValueNumber(
92+
VariableAddressInstruction instr, IRFunction irFunc, IRVariable var
93+
) {
94+
instr.getEnclosingIRFunction() = irFunc and
95+
instr.getIRVariable() = var
96+
}
97+
98+
private predicate initializeParameterValueNumber(
99+
InitializeParameterInstruction instr, IRFunction irFunc, IRVariable var
100+
) {
101+
instr.getEnclosingIRFunction() = irFunc and
102+
instr.getIRVariable() = var
103+
}
104+
105+
private predicate initializeThisValueNumber(InitializeThisInstruction instr, IRFunction irFunc) {
106+
instr.getEnclosingIRFunction() = irFunc
107+
}
108+
109+
private predicate constantValueNumber(
110+
ConstantInstruction instr, IRFunction irFunc, IRType type, string value
111+
) {
112+
instr.getEnclosingIRFunction() = irFunc and
113+
instr.getResultIRType() = type and
114+
instr.getValue() = value
115+
}
116+
117+
private predicate stringConstantValueNumber(
118+
StringConstantInstruction instr, IRFunction irFunc, IRType type, string value
119+
) {
120+
instr.getEnclosingIRFunction() = irFunc and
121+
instr.getResultIRType() = type and
122+
instr.getValue().getValue() = value
123+
}
124+
125+
private predicate fieldAddressValueNumber(
126+
FieldAddressInstruction instr, IRFunction irFunc, Language::Field field,
127+
TValueNumber objectAddress
128+
) {
129+
instr.getEnclosingIRFunction() = irFunc and
130+
instr.getField() = field and
131+
tvalueNumber(instr.getObjectAddress()) = objectAddress
132+
}
133+
134+
private predicate binaryValueNumber(
135+
BinaryInstruction instr, IRFunction irFunc, Opcode opcode, IRType type, TValueNumber leftOperand,
136+
TValueNumber rightOperand
137+
) {
138+
instr.getEnclosingIRFunction() = irFunc and
139+
not instr instanceof PointerArithmeticInstruction and
140+
instr.getOpcode() = opcode and
141+
instr.getResultIRType() = type and
142+
tvalueNumber(instr.getLeft()) = leftOperand and
143+
tvalueNumber(instr.getRight()) = rightOperand
144+
}
145+
146+
private predicate pointerArithmeticValueNumber(
147+
PointerArithmeticInstruction instr, IRFunction irFunc, Opcode opcode, IRType type,
148+
int elementSize, TValueNumber leftOperand, TValueNumber rightOperand
149+
) {
150+
instr.getEnclosingIRFunction() = irFunc and
151+
instr.getOpcode() = opcode and
152+
instr.getResultIRType() = type and
153+
instr.getElementSize() = elementSize and
154+
tvalueNumber(instr.getLeft()) = leftOperand and
155+
tvalueNumber(instr.getRight()) = rightOperand
156+
}
157+
158+
private predicate unaryValueNumber(
159+
UnaryInstruction instr, IRFunction irFunc, Opcode opcode, IRType type, TValueNumber operand
160+
) {
161+
instr.getEnclosingIRFunction() = irFunc and
162+
not instr instanceof InheritanceConversionInstruction and
163+
not instr instanceof CopyInstruction and
164+
instr.getOpcode() = opcode and
165+
instr.getResultIRType() = type and
166+
tvalueNumber(instr.getUnary()) = operand
167+
}
168+
169+
private predicate inheritanceConversionValueNumber(
170+
InheritanceConversionInstruction instr, IRFunction irFunc, Opcode opcode,
171+
Language::Class baseClass, Language::Class derivedClass, TValueNumber operand
172+
) {
173+
instr.getEnclosingIRFunction() = irFunc and
174+
instr.getOpcode() = opcode and
175+
instr.getBaseClass() = baseClass and
176+
instr.getDerivedClass() = derivedClass and
177+
tvalueNumber(instr.getUnary()) = operand
178+
}
179+
180+
/**
181+
* Holds if `instr` should be assigned a unique value number because this library does not know how
182+
* to determine if two instances of that instruction are equivalent.
183+
*/
184+
private predicate uniqueValueNumber(Instruction instr, IRFunction irFunc) {
185+
instr.getEnclosingIRFunction() = irFunc and
186+
not instr.getResultIRType() instanceof IRVoidType and
187+
not numberableInstruction(instr)
188+
}
189+
190+
/**
191+
* Gets the value number assigned to `instr`, if any. Returns at most one result.
192+
*/
193+
cached
194+
TValueNumber tvalueNumber(Instruction instr) {
195+
result = nonUniqueValueNumber(instr)
196+
or
197+
exists(IRFunction irFunc |
198+
uniqueValueNumber(instr, irFunc) and
199+
result = TUniqueValueNumber(irFunc, instr)
200+
)
201+
}
202+
203+
/**
204+
* Gets the value number assigned to `instr`, if any, unless that instruction is assigned a unique
205+
* value number.
206+
*/
207+
private TValueNumber nonUniqueValueNumber(Instruction instr) {
208+
exists(IRFunction irFunc |
209+
irFunc = instr.getEnclosingIRFunction() and
210+
(
211+
exists(IRVariable var |
212+
variableAddressValueNumber(instr, irFunc, var) and
213+
result = TVariableAddressValueNumber(irFunc, var)
214+
)
215+
or
216+
exists(IRVariable var |
217+
initializeParameterValueNumber(instr, irFunc, var) and
218+
result = TInitializeParameterValueNumber(irFunc, var)
219+
)
220+
or
221+
initializeThisValueNumber(instr, irFunc) and
222+
result = TInitializeThisValueNumber(irFunc)
223+
or
224+
exists(IRType type, string value |
225+
constantValueNumber(instr, irFunc, type, value) and
226+
result = TConstantValueNumber(irFunc, type, value)
227+
)
228+
or
229+
exists(IRType type, string value |
230+
stringConstantValueNumber(instr, irFunc, type, value) and
231+
result = TStringConstantValueNumber(irFunc, type, value)
232+
)
233+
or
234+
exists(Language::Field field, TValueNumber objectAddress |
235+
fieldAddressValueNumber(instr, irFunc, field, objectAddress) and
236+
result = TFieldAddressValueNumber(irFunc, field, objectAddress)
237+
)
238+
or
239+
exists(Opcode opcode, IRType type, TValueNumber leftOperand, TValueNumber rightOperand |
240+
binaryValueNumber(instr, irFunc, opcode, type, leftOperand, rightOperand) and
241+
result = TBinaryValueNumber(irFunc, opcode, type, leftOperand, rightOperand)
242+
)
243+
or
244+
exists(Opcode opcode, IRType type, TValueNumber operand |
245+
unaryValueNumber(instr, irFunc, opcode, type, operand) and
246+
result = TUnaryValueNumber(irFunc, opcode, type, operand)
247+
)
248+
or
249+
exists(
250+
Opcode opcode, Language::Class baseClass, Language::Class derivedClass, TValueNumber operand
251+
|
252+
inheritanceConversionValueNumber(instr, irFunc, opcode, baseClass, derivedClass, operand) and
253+
result = TInheritanceConversionValueNumber(irFunc, opcode, baseClass, derivedClass, operand)
254+
)
255+
or
256+
exists(
257+
Opcode opcode, IRType type, int elementSize, TValueNumber leftOperand,
258+
TValueNumber rightOperand
259+
|
260+
pointerArithmeticValueNumber(instr, irFunc, opcode, type, elementSize, leftOperand,
261+
rightOperand) and
262+
result =
263+
TPointerArithmeticValueNumber(irFunc, opcode, type, elementSize, leftOperand, rightOperand)
264+
)
265+
or
266+
// The value number of a copy is just the value number of its source value.
267+
result = tvalueNumber(instr.(CongruentCopyInstruction).getSourceValue())
268+
)
269+
)
270+
}

0 commit comments

Comments
 (0)