Skip to content

Commit 3a51e02

Browse files
authored
Merge pull request #1923 from AndreiDiaconu1/ircsharp-pointers-typespec
C# IR: Fix loads and assign ops, add pointers, ref, in, out params
2 parents 6f2e485 + c64db77 commit 3a51e02

File tree

11 files changed

+827
-226
lines changed

11 files changed

+827
-226
lines changed

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

Lines changed: 68 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,15 @@ ArrayType getArrayOfDim(int dim, Type type) {
2626
}
2727

2828
private predicate canCreateCompilerGeneratedElement(Element generatedBy, int nth) {
29-
generatedBy instanceof ForeachStmt and nth in [0 .. ForeachElements::noGeneratedElements()]
29+
generatedBy instanceof ForeachStmt and nth in [0 .. ForeachElements::noGeneratedElements() - 1]
3030
or
31-
generatedBy instanceof LockStmt and nth in [0 .. LockElements::noGeneratedElements()]
31+
generatedBy instanceof LockStmt and nth in [0 .. LockElements::noGeneratedElements() - 1]
3232
or
3333
generatedBy instanceof DelegateCreation and
34-
nth in [0 .. DelegateElements::noGeneratedElements(generatedBy)]
34+
nth in [0 .. DelegateElements::noGeneratedElements(generatedBy) - 1]
3535
or
3636
generatedBy instanceof DelegateCall and
37-
nth in [0 .. DelegateElements::noGeneratedElements(generatedBy)]
37+
nth in [0 .. DelegateElements::noGeneratedElements(generatedBy) - 1]
3838
}
3939

4040
/**
@@ -75,7 +75,12 @@ private predicate ignoreExprAndDescendants(Expr expr) {
7575
expr instanceof LocalVariableDeclExpr and
7676
expr.getParent() instanceof ForeachStmt
7777
or
78-
ignoreExprAndDescendants(getRealParent(expr)) // recursive case
78+
// recursive case
79+
ignoreExprAndDescendants(getRealParent(expr)) and
80+
// The two children of an `AssignOperation` should not be ignored, but since they are also
81+
// descendants of an orphan node (the expanded form of the `AssignOperation` is also retrieved by
82+
// the extractor, which is rooted in an AST node without parents) they would be
83+
not expr.getParent() instanceof AssignOperation
7984
}
8085

8186
/**
@@ -167,6 +172,63 @@ private predicate usedAsCondition(Expr expr) {
167172
)
168173
}
169174

175+
/**
176+
* Holds if we should have a `Load` instruction for `expr` when generating the IR.
177+
*/
178+
private predicate mayNeedLoad(Expr expr) {
179+
expr instanceof AssignableRead
180+
or
181+
// We need an extra load for the `PointerIndirectionExpr`
182+
expr instanceof PointerIndirectionExpr and
183+
// If the dereferencing happens on the lhs of an
184+
// assignment we shouldn't have a load instruction
185+
not exists(Assignment a | a.getLValue() = expr)
186+
}
187+
188+
predicate needsLoad(Expr expr) {
189+
mayNeedLoad(expr) and
190+
not ignoreLoad(expr)
191+
}
192+
193+
/**
194+
* Holds if we should ignore the `Load` instruction for `expr` when generating IR.
195+
*/
196+
private predicate ignoreLoad(Expr expr) {
197+
// No load needed for the qualifier
198+
// in an array access
199+
expr = any(ArrayAccess aa).getQualifier()
200+
or
201+
// No load is needed for the lvalue in an assignment such as:
202+
// Eg. `Object obj = oldObj`;
203+
expr = any(Assignment a).getLValue() and
204+
expr.getType() instanceof RefType
205+
or
206+
// Since the loads for a crement operation is handled by the translation
207+
// of the operation, we ignore the load here
208+
expr.getParent() instanceof MutatorOperation
209+
or
210+
// The `&` operator does not need a load, since the
211+
// address is the final value of the expression
212+
expr.getParent() instanceof AddressOfExpr
213+
or
214+
// If expr is a variable access used as the qualifier for a field access and
215+
// its target variable is a value type variable,
216+
// ignore the load since the address of a variable that is a value type is
217+
// given by a single `VariableAddress` instruction.
218+
expr = any(FieldAccess fa).getQualifier() and
219+
expr = any(VariableAccess va |
220+
va.getType().isValueType() and
221+
not va.getTarget() = any(Parameter p | p.isOutOrRef() or p.isIn())
222+
)
223+
or
224+
// If expr is passed as an `out,`ref` or `in` argument,
225+
// no load should take place since we pass the address, not the
226+
// value of the variable
227+
expr.(AssignableAccess).isOutOrRefArgument()
228+
or
229+
expr.(AssignableAccess).isInArgument()
230+
}
231+
170232
newtype TTranslatedElement =
171233
// An expression that is not being consumed as a condition
172234
TTranslatedValueExpr(Expr expr) {
@@ -182,17 +244,8 @@ newtype TTranslatedElement =
182244
// A separate element to handle the lvalue-to-rvalue conversion step of an
183245
// expression.
184246
TTranslatedLoad(Expr expr) {
185-
// TODO: Revisit and make sure Loads are only used when needed
186247
not ignoreExpr(expr) and
187-
expr instanceof AssignableRead and
188-
not expr.getParent() instanceof ArrayAccess and
189-
not (
190-
expr.getParent() instanceof Assignment and
191-
expr.getType() instanceof RefType
192-
) and
193-
// Ignore loads for reads in `++` and `--` since their
194-
// translated elements handle them
195-
not expr.getParent() instanceof MutatorOperation
248+
needsLoad(expr)
196249
} or
197250
// An expression most naturally translated as control flow.
198251
TTranslatedNativeCondition(Expr expr) {
@@ -250,15 +303,6 @@ newtype TTranslatedElement =
250303
not ignoreExpr(initList) and
251304
exists(initList.getElement(elementIndex))
252305
} or
253-
// The value initialization of a range of array elements that were omitted
254-
// from an initializer list.
255-
TTranslatedElementValueInitialization(
256-
ArrayInitializer initList, int elementIndex, int elementCount
257-
) {
258-
not ignoreExpr(initList) and
259-
isFirstValueInitializedElementInRange(initList, elementIndex) and
260-
elementCount = getEndOfValueInitializedRange(initList, elementIndex) - elementIndex
261-
} or
262306
// The initialization of a base class from within a constructor.
263307
TTranslatedConstructorInitializer(ConstructorInitializer init) { not ignoreExpr(init) } or
264308
// A statement
@@ -284,47 +328,6 @@ newtype TTranslatedElement =
284328
canCreateCompilerGeneratedElement(generatedBy, index)
285329
}
286330

287-
/**
288-
* Gets the index of the first explicitly initialized element in `initList`
289-
* whose index is greater than `afterElementIndex`, where `afterElementIndex`
290-
* is a first value-initialized element in a value-initialized range in
291-
* `initList`. If there are no remaining explicitly initialized elements in
292-
* `initList`, the result is the total number of elements in the array being
293-
* initialized.
294-
*/
295-
private int getEndOfValueInitializedRange(ArrayInitializer initList, int afterElementIndex) {
296-
result = getNextExplicitlyInitializedElementAfter(initList, afterElementIndex)
297-
or
298-
isFirstValueInitializedElementInRange(initList, afterElementIndex) and
299-
not exists(getNextExplicitlyInitializedElementAfter(initList, afterElementIndex)) and
300-
result = initList.getNumberOfElements()
301-
}
302-
303-
/**
304-
* Gets the index of the first explicitly initialized element in `initList`
305-
* whose index is greater than `afterElementIndex`, where `afterElementIndex`
306-
* is a first value-initialized element in a value-initialized range in
307-
* `initList`.
308-
*/
309-
private int getNextExplicitlyInitializedElementAfter(
310-
ArrayInitializer initList, int afterElementIndex
311-
) {
312-
isFirstValueInitializedElementInRange(initList, afterElementIndex) and
313-
result = min(int i | exists(initList.getElement(i)) and i > afterElementIndex)
314-
}
315-
316-
/**
317-
* Holds if element `elementIndex` is the first value-initialized element in a
318-
* range of one or more consecutive value-initialized elements in `initList`.
319-
*/
320-
private predicate isFirstValueInitializedElementInRange(ArrayInitWithMod initList, int elementIndex) {
321-
initList.isValueInitialized(elementIndex) and
322-
(
323-
elementIndex = 0 or
324-
not initList.isValueInitialized(elementIndex - 1)
325-
)
326-
}
327-
328331
/**
329332
* Represents an AST node for which IR needs to be generated.
330333
*

0 commit comments

Comments
 (0)