@@ -5,267 +5,67 @@ private import InstructionTag
55private import TranslatedElement
66private import TranslatedExpr
77private import semmle.code.csharp.ir.Util
8+ private import semmle.code.csharp.ir.implementation.raw.internal.common.TranslatedCallBlueprint
89private import semmle.code.csharp.ir.internal.IRCSharpLanguage as Language
910
1011/**
11- * The IR translation of a call to a function. The call may be from an actual
12- * call in the source code, or could be a call that is part of the translation
13- * of a higher-level constructor (e.g. the allocator call in a `NewExpr`).
12+ * The IR translation of a call to a function. The function can be a normal function
13+ * (eg. `MethodCall`) or a constructor call (eg. `ObjectCreation`). Notice that the
14+ * AST generated translated calls are tied to an expression (unlike compiler generated ones,
15+ * which can be attached to either a statement or an expression).
1416 */
15- abstract class TranslatedCall extends TranslatedExpr {
16- final override TranslatedElement getChild ( int id ) {
17- // We choose the child's id in the order of evaluation.
18- // The qualifier is evaluated before the call target, because the value of
19- // the call target may depend on the value of the qualifier for virtual
20- // calls.
21- id = - 2 and result = this .getQualifier ( )
22- or
23- id = - 1 and result = this .getCallTarget ( )
24- or
25- result = this .getArgument ( id )
26- }
27-
28- final override Instruction getFirstInstruction ( ) {
29- if exists ( this .getQualifier ( ) )
30- then result = this .getQualifier ( ) .getFirstInstruction ( )
31- else result = this .getFirstCallTargetInstruction ( )
32- }
33-
34- override predicate hasInstruction (
35- Opcode opcode , InstructionTag tag , Type resultType , boolean isLValue
36- ) {
37- tag = CallTag ( ) and
38- opcode instanceof Opcode:: Call and
39- resultType = getCallResultType ( ) and
40- isLValue = false
41- or
42- hasSideEffect ( ) and
43- tag = CallSideEffectTag ( ) and
44- (
45- if hasWriteSideEffect ( )
46- then (
47- opcode instanceof Opcode:: CallSideEffect and
48- resultType instanceof Language:: UnknownType
49- ) else (
50- opcode instanceof Opcode:: CallReadSideEffect and
51- resultType instanceof Language:: UnknownType
52- )
53- ) and
54- isLValue = false
55- }
5617
57- override Instruction getChildSuccessor ( TranslatedElement child ) {
58- child = this .getQualifier ( ) and
59- result = this .getFirstCallTargetInstruction ( )
60- or
61- child = this .getCallTarget ( ) and
62- result = this .getFirstArgumentOrCallInstruction ( )
63- or
64- exists ( int argIndex |
65- child = this .getArgument ( argIndex ) and
66- if exists ( this .getArgument ( argIndex + 1 ) )
67- then result = this .getArgument ( argIndex + 1 ) .getFirstInstruction ( )
68- else result = this .getInstruction ( CallTag ( ) )
69- )
70- }
71-
72- override Instruction getInstructionSuccessor ( InstructionTag tag , EdgeKind kind ) {
73- kind instanceof GotoEdge and
74- (
75- (
76- tag = CallTag ( ) and
77- if this .hasSideEffect ( )
78- then result = this .getInstruction ( CallSideEffectTag ( ) )
79- else result = this .getParent ( ) .getChildSuccessor ( this )
80- )
81- or
82- this .hasSideEffect ( ) and
83- tag = CallSideEffectTag ( ) and
84- result = this .getParent ( ) .getChildSuccessor ( this )
85- )
18+ abstract class TranslatedCall extends TranslatedExpr , TranslatedCallBlueprint {
19+ final override Instruction getResult ( ) {
20+ result = TranslatedCallBlueprint .super .getResult ( )
8621 }
87-
88- override Instruction getInstructionOperand ( InstructionTag tag , OperandTag operandTag ) {
89- tag = CallTag ( ) and
90- (
91- tag = CallTag ( ) and
92- (
93- operandTag instanceof CallTargetOperandTag and
94- result = this .getCallTargetResult ( )
95- or
96- operandTag instanceof ThisArgumentOperandTag and
97- result = this .getQualifierResult ( )
98- or
99- exists ( PositionalArgumentOperandTag argTag |
100- argTag = operandTag and
101- result = this .getArgument ( argTag .getArgIndex ( ) ) .getResult ( )
102- )
103- )
104- )
105- or
106- tag = CallSideEffectTag ( ) and
107- this .hasSideEffect ( ) and
108- operandTag instanceof SideEffectOperandTag and
22+
23+ override Instruction getUnmodeledDefinitionInstruction ( ) {
10924 result = this .getEnclosingFunction ( ) .getUnmodeledDefinitionInstruction ( )
110- or
111- tag = CallSideEffectTag ( ) and
112- hasSideEffect ( ) and
113- operandTag instanceof SideEffectOperandTag and
114- result = getEnclosingFunction ( ) .getUnmodeledDefinitionInstruction ( )
115- }
116-
117- final override Type getInstructionOperandType ( InstructionTag tag , TypedOperandTag operandTag ) {
118- tag = CallSideEffectTag ( ) and
119- this .hasSideEffect ( ) and
120- operandTag instanceof SideEffectOperandTag and
121- result instanceof Language:: UnknownType
122- }
123-
124- final override Instruction getResult ( ) { result = this .getInstruction ( CallTag ( ) ) }
125-
126- /**
127- * Gets the result type of the call.
128- */
129- abstract Type getCallResultType ( ) ;
130-
131- /**
132- * Holds if the call has a `this` argument.
133- */
134- predicate hasQualifier ( ) { exists ( this .getQualifier ( ) ) }
135-
136- /**
137- * Gets the `TranslatedExpr` for the indirect target of the call, if any.
138- */
139- TranslatedExpr getCallTarget ( ) { none ( ) }
140-
141- /**
142- * Gets the first instruction of the sequence to evaluate the call target.
143- * By default, this is just the first instruction of `getCallTarget()`, but
144- * it can be overridden by a subclass for cases where there is a call target
145- * that is not computed from an expression (e.g. a direct call).
146- */
147- Instruction getFirstCallTargetInstruction ( ) {
148- result = this .getCallTarget ( ) .getFirstInstruction ( )
149- }
150-
151- /**
152- * Gets the instruction whose result value is the target of the call. By
153- * default, this is just the result of `getCallTarget()`, but it can be
154- * overridden by a subclass for cases where there is a call target that is not
155- * computed from an expression (e.g. a direct call).
156- */
157- Instruction getCallTargetResult ( ) { result = this .getCallTarget ( ) .getResult ( ) }
158-
159- /**
160- * Gets the `TranslatedExpr` for the qualifier of the call (i.e. the value
161- * that is passed as the `this` argument.
162- */
163- abstract TranslatedExpr getQualifier ( ) ;
164-
165- /**
166- * Gets the instruction whose result value is the `this` argument of the call.
167- * By default, this is just the result of `getQualifier()`, but it can be
168- * overridden by a subclass for cases where there is a `this` argument that is
169- * not computed from a child expression (e.g. a constructor call).
170- */
171- Instruction getQualifierResult ( ) { result = this .getQualifier ( ) .getResult ( ) }
172-
173- /**
174- * Gets the argument with the specified `index`. Does not include the `this`
175- * argument.
176- */
177- abstract TranslatedExpr getArgument ( int index ) ;
178-
179- /**
180- * If there are any arguments, gets the first instruction of the first
181- * argument. Otherwise, returns the call instruction.
182- */
183- final Instruction getFirstArgumentOrCallInstruction ( ) {
184- if this .hasArguments ( )
185- then result = this .getArgument ( 0 ) .getFirstInstruction ( )
186- else result = this .getInstruction ( CallTag ( ) )
187- }
188-
189- /**
190- * Holds if the call has any arguments, not counting the `this` argument.
191- */
192- abstract predicate hasArguments ( ) ;
193-
194- // TODO: Fix side effects
195- predicate hasReadSideEffect ( ) { any ( ) }
196-
197- predicate hasWriteSideEffect ( ) { any ( ) }
198-
199- private predicate hasSideEffect ( ) { hasReadSideEffect ( ) or hasWriteSideEffect ( ) }
200-
201- override Instruction getPrimaryInstructionForSideEffect ( InstructionTag tag ) {
202- this .hasSideEffect ( ) and
203- tag = CallSideEffectTag ( ) and
204- result = this .getResult ( )
20525 }
20626}
20727
20828/**
209- * IR translation of a direct call to a specific function. Used for both
210- * explicit calls and implicit calls.
29+ * Represents the IR translation of a direct function call. The call can be one of the following:
30+ * `MethodCall`, `LocalFunctionCall`, `AccessorCall`, `OperatorCall`.
31+ * Note that `DelegateCall`s are not treated here since they need
21132 */
212- abstract class TranslatedDirectCall extends TranslatedCall {
213- final override Instruction getFirstCallTargetInstruction ( ) {
214- result = this .getInstruction ( CallTargetTag ( ) )
215- }
216-
217- final override Instruction getCallTargetResult ( ) { result = this .getInstruction ( CallTargetTag ( ) ) }
21833
219- override predicate hasInstruction (
220- Opcode opcode , InstructionTag tag , Type resultType , boolean isLValue
221- ) {
222- TranslatedCall .super .hasInstruction ( opcode , tag , resultType , isLValue )
223- or
224- tag = CallTargetTag ( ) and
225- opcode instanceof Opcode:: FunctionAddress and
226- resultType = expr .getType ( ) and
227- isLValue = true
34+ class TranslatedFunctionCall extends TranslatedNonConstantExpr , TranslatedCall {
35+ override Call expr ;
36+
37+ TranslatedFunctionCall ( ) {
38+ expr instanceof MethodCall or
39+ expr instanceof LocalFunctionCall or
40+ expr instanceof AccessorCall or
41+ expr instanceof OperatorCall
22842 }
22943
230- override Instruction getInstructionSuccessor ( InstructionTag tag , EdgeKind kind ) {
231- result = TranslatedCall .super .getInstructionSuccessor ( tag , kind )
232- or
233- tag = CallTargetTag ( ) and
234- kind instanceof GotoEdge and
235- result = this .getFirstArgumentOrCallInstruction ( )
44+ override Callable getInstructionFunction ( InstructionTag tag ) {
45+ tag = CallTargetTag ( ) and result = expr .getTarget ( )
23646 }
237- }
23847
239- /**
240- * The IR translation of a call to a function.
241- */
242- abstract class TranslatedCallExpr extends TranslatedNonConstantExpr , TranslatedCall {
243- override Call expr ;
244-
245- override Type getCallResultType ( ) { result = this .getResultType ( ) }
246-
247- final override predicate hasArguments ( ) { exists ( expr .getArgument ( 0 ) ) }
248-
249- final override TranslatedExpr getQualifier ( ) {
48+ override predicate hasArguments ( ) {
49+ exists ( expr .getArgument ( 0 ) )
50+ }
51+
52+ override TranslatedExpr getArgument ( int index ) {
53+ result = getTranslatedExpr ( expr .getArgument ( index ) )
54+ }
55+
56+ override TranslatedExpr getQualifier ( ) {
25057 expr instanceof QualifiableExpr and
25158 result = getTranslatedExpr ( expr .( QualifiableExpr ) .getQualifier ( ) )
25259 }
253-
254- final override TranslatedExpr getArgument ( int index ) {
255- result = getTranslatedExpr ( expr . getArgument ( index ) )
60+
61+ override Instruction getQualifierResult ( ) {
62+ result = this . getQualifier ( ) . getResult ( )
25663 }
257- }
258-
259- /**
260- * Represents the IR translation of a direct function call.
261- */
262- class TranslatedFunctionCall extends TranslatedCallExpr , TranslatedDirectCall {
263- override Call expr ;
264-
265- override Callable getInstructionFunction ( InstructionTag tag ) {
266- tag = CallTargetTag ( ) and result = expr .getTarget ( )
64+
65+ override Type getCallResultType ( ) {
66+ result = expr .getTarget ( ) .getReturnType ( )
26767 }
268-
68+
26969 override predicate hasReadSideEffect ( ) {
27070 not expr .getTarget ( ) .( SideEffectFunction ) .neverReadsMemory ( )
27171 }
@@ -276,26 +76,45 @@ class TranslatedFunctionCall extends TranslatedCallExpr, TranslatedDirectCall {
27676}
27777
27878/**
279- * Represents the IR translation of a call to a constructor.
280- * The target of the call is a newly allocated object whose address, after
281- * the constructor call, address will be passed to a variable declaration.
79+ * Represents the IR translation of a call to a constructor or to a constructor initializer.
80+ * The qualifier of the call is obtained from the constructor call context.
81+ * Note that `DelegateCreation` is not present here, since the call to a delegate constructor is
82+ * compiler generated.
28283 */
283- class TranslatedConstructorCall extends TranslatedFunctionCall {
284- TranslatedConstructorCall ( ) {
84+ class TranslatedConstructorCall extends TranslatedNonConstantExpr , TranslatedCall {
85+ override Call expr ;
86+
87+ TranslatedConstructorCall ( ) {
28588 expr instanceof ObjectCreation or
28689 expr instanceof ConstructorInitializer
28790 }
28891
92+ override Callable getInstructionFunction ( InstructionTag tag ) {
93+ tag = CallTargetTag ( ) and result = expr .getTarget ( )
94+ }
95+
96+ override predicate hasArguments ( ) {
97+ exists ( expr .getArgument ( 0 ) )
98+ }
99+
100+ override TranslatedExpr getArgument ( int index ) {
101+ result = getTranslatedExpr ( expr .getArgument ( index ) )
102+ }
103+
104+ // The qualifier for a constructor call has already been generated
105+ // (the `NewObj` instruction)
106+ override TranslatedExpr getQualifier ( ) {
107+ none ( )
108+ }
109+
110+ override Type getCallResultType ( ) {
111+ result instanceof VoidType
112+ }
113+
289114 override Instruction getQualifierResult ( ) {
290- // We must retrieve the qualifier from the context the
291- // constructor call happened
292- exists ( StructorCallContext context |
115+ exists ( ConstructorCallContext context |
293116 context = this .getParent ( ) and
294117 result = context .getReceiver ( )
295118 )
296119 }
297-
298- override Type getCallResultType ( ) { result instanceof VoidType }
299-
300- override predicate hasQualifier ( ) { any ( ) }
301120}
0 commit comments