Skip to content

Commit 80b7512

Browse files
author
AndreiDiaconu1
committed
Initial restructure
The `raw/internal` folder has been restructured to better enhance code sharing between compiler generated elements and AST generated elements. The translated calls classes have been refactored to better fit the C# library. A new folder has been added, `common` that provides blueprints for the classes that deal with translations of calls, declarations, exprs and conditions. Several `TranslatedX.qll` files have been modified so that they use those blueprint classes.
1 parent aa009d0 commit 80b7512

File tree

14 files changed

+1043
-485
lines changed

14 files changed

+1043
-485
lines changed

csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/InstructionTag.qll

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ newtype TInstructionTag =
5454
BoolConversionConstantTag() or
5555
BoolConversionCompareTag() or
5656
LoadTag() or // Implicit load due to lvalue-to-rvalue conversion
57+
AddressTag() or
5758
CatchTag() or
5859
ThrowTag() or
5960
UnwindTag() or
@@ -192,16 +193,8 @@ string getInstructionTagId(TInstructionTag tag) {
192193
or
193194
tag = GeneratedBranchTag() and result = "GeneratedBranchTag"
194195
or
195-
// TODO: Reread
196-
// exists(Field field, Class cls, int index, string tagName |
197-
// field = cls.getCanonicalMember(index) and
198-
// (
199-
// tag = InitializerFieldAddressTag(field) and tagName = "InitFieldAddr" or
200-
// tag = InitializerFieldDefaultValueTag(field) and tagName = "InitFieldDefVal" or
201-
// tag = InitializerFieldDefaultValueStoreTag(field) and tagName = "InitFieldDefValStore"
202-
// ) and
203-
// result = tagName + "(" + index + ")"
204-
// ) or
196+
tag = AddressTag() and result = "AddressTag"
197+
or
205198
exists(int index, string tagName |
206199
(
207200
tag = InitializerElementIndexTag(index) and tagName = "InitElemIndex"

csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/TranslatedCall.qll

Lines changed: 70 additions & 251 deletions
Original file line numberDiff line numberDiff line change
@@ -5,267 +5,67 @@ private import InstructionTag
55
private import TranslatedElement
66
private import TranslatedExpr
77
private import semmle.code.csharp.ir.Util
8+
private import semmle.code.csharp.ir.implementation.raw.internal.common.TranslatedCallBlueprint
89
private 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

Comments
 (0)