Skip to content

Add document for lvalue bounds checking generalization #970

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Feb 2, 2021

Conversation

kkjeer
Copy link
Contributor

@kkjeer kkjeer commented Jan 30, 2021

This document summarizes the proposed work necessary to generalize bounds checking from variables to lvalue expressions.

Copy link
Contributor

@sulekhark sulekhark left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the detailed document! Looks great overall. Please see inline for a few review comments.


1. The widened bounds for `v`, if `v` has widened bounds within the current CFG
block `B`, or:
2. The declared bounds for `v`, if `v` has declared bounds, or:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might perhaps be more clear to reword this sentence as "The declared bounds for v, if v is declared in S" (as is stated in line 116 above).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

v here could be a variable that was declared prior to S. For example:

void f() {
  _Array_ptr<int> a : count(1) = 0;

  // Statement S
  // Before checking S, the ObservedBounds context is { a => bounds(a, a + 1), b => bounds(b, b + 2) }
  _Array_ptr<int> b : count(2) = 0;
}

I moved this description of the initial ObservedBounds to the end of the section describing ResetKilledBounds, since at that point all the methods that are involved in setting the initial ObservedBounds have been described.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, thanks for the clarification!


After checking a statement `S`, this method checks that, for each variable
declaration `v` in `ObservedBounds`, the inferred bounds `ObservedBounds[v]`
`ObservedBounds[v]` imply the declared bounds of `v` (`v->getBoundsExpr()`).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: ObservedBounds[v] is repeated.

occurs immediately after checking an assignment to the expression. The goal
is to generalize the work that was previously done for variables so that the
bounds checking behavior is the same for all lvalue expressions.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

General question: Are bounds on global/static/extern variables declared in the compilation unit, being checked?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are checked in TraverseTopLevelVarDecl. This method itself doesn't do anything to the CheckingState members, including ObservedBounds and EquivExprs - it just initializes an empty CheckingState and checks the bounds immediately after traversing its VarDecl * argument.

How much detail on bounds checking do you think would be helpful in this document? Initially I didn't include TraverseTopLevelVarDecl here since it doesn't directly interact with ObservedBounds (or EquivExprs). I have another document in progress in #945 that describes bounds checking in general. I would propose that I move most of the detail in this "Bounds Checking for Variables" section into that document so that this document can focus more on lvalue generalization. The "Bounds Checking for Variables" section in this document can then just briefly list the places where ObservedBounds is updated or used since this is relevant to changing the ObservedBounds keys, and reference the other bounds checking document for more detail. What are your thoughts on this?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I agree that most of the detail on bounds checking can be in the other document (#945) and this document can focus on lvalue generalization.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. I've moved most of this section into the #945 document and just included a list of methods where it will be necessary to change the keys of ObservedBounds in this section


In general, for lvalue expressions `e1` and `e2`, updating the inferred bounds
of `e1` should also update the bounds of `e2` if and only if `e1` and `e2`
are guranteed to be **identical lvalue expressions**. That is, if:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: guranteed -> guaranteed.


This definition does not account for aliasing concerns. It is possible for
lvalue expressions to partially or completely overlap (for example, struct
variables `a` and `b` may share some or all of their fields). For the initial
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think these two sentences must be removed from here. The definition, as it is stated above in lines 178 and 179, does not ignore aliasing concerns - we are ignoring aliasing concerns while determining identical lvalue expressions. Also see my comment below.

lvalue expressions to partially or completely overlap (for example, struct
variables `a` and `b` may share some or all of their fields). For the initial
planned work for lvalue generalization, we will only consider lvalue identity
as defined above. We may consider aliasing issues in future work.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that the last-but-one sentence above must be reworded along the lines of:
"For the initial planned work for lvalue generalization, we will only generalize across lvalue expressions that the we are able to determine as identical based on the definition stated above. Further, while determining identical lvalue expressions, we will initially ignore aliasing concerns and ignore lvalue expressions that do not fully overlap in memory."

### ObservedBounds Keys

Currently, the `ObservedBounds` map uses `VarDecl *` as its keys. This ensures
that updating the inferred bounds for a `DeclExpr *` `x` updates the inferred
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: DeclExpr * -> DeclRefExpr *.

@sulekhark
Copy link
Contributor

LGTM.

Copy link
Contributor

@sulekhark sulekhark left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants