-
Notifications
You must be signed in to change notification settings - Fork 26
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
Unique specifier for types leading to using different fields in the backend #1219
base: dev
Are you sure you want to change the base?
Conversation
Nice! You should know that @superaxander (and sometimes me) are working on some proposed silicon changes that address similar concerns, although we've focused on singleton heap chunks (i.e. plain permission without quantification), but I don't see a strong reason why e.g. the proposed chunk ordering heuristics would not improve things. Maybe we should have a look at some slow array examples again with our recently gained knowledge. |
Yes this would be quite useful. Ideally there'd be a way we could give Viper a better view of which fields may alias and which may not instead of simply relying on the name of the field. For example I want to be able to say the field int_1 and int_2 never alias but both of them may alias with int_3 which would drastically reduce the amount of heap chunks viper has to consider when dealing with a pointer to a field int_1 or int_2. (additionally during state consolidation Viper will take every combination of two heap chunks with the same field name to attempt to prove that they do or don't alias, this generates an exponential amount of proof goals) Your example of wanting to specify that the two fields are unique is basically the exact thing I've been working on for the past two weeks with my by-value classes. Because I'm encoding structs as ADTs with pointers inside of them we have for a struct: struct A {
int a;
int b;
} That we know that As for specifying a ghost type of e.g. void pointers I have also been thinking about that since this kind of pattern occurs everywhere in LLVM. (all pointers are untyped in LLVM) My idea so far was to extend the notion of permission to being "permission to access as if it were a certain type". For example: //@ requires Perm(a, write, int)
void foo(void *a) {
int b = *((int *) a)
} You could then call this function with many different kinds of values which can all be treated as int pointers: struct A a;
a.a = 5;
// A pointer to a value "struct A" can be treated as an int pointer
foo(&a);
// This is already an int pointer
foo(&a.b); |
PR Description
Having many arrays in scope at the same time leads to poor performance in Silicon, to the point where it is not possible to verify files with many arrays present. A workaround is to use different fields for different arrays if you are sure the arrays will never overlap.
With this pull request, I want to add the ability to do this, by marking the type of an array as unique, indicating that it does not overlap with other arrays. In the backend, this will generate different types of fields for each array.
In the frontend it looks like this
In the generated viper file we would like to have the following fields and permissions:
I want to start by verifying the above simple example.
Internal I probably want to add a new Array Type, which is unique. To make sure that we do not mix-up arrays of different
unique
s.Extensions
Further options I want to consider are the following.
Called functions with unique arrays as arguments, will need their own versions. E.g.
should verify. But then we need 3 versions of
f
. The normal version, and two versions that work forunique<0>
andunique<1>
. I intend that the two other versions are abstract functions with the same signature and annotations, such that we do not do extra verification.I first consider this only for C, since that is my use case. We could extend this to PVL as well? And the other languages if we want.
We could consider adding an automatic program pass, which we can call via an extra option in VerCors, which automatically marks all declared arrays unique, except when this is not possible and we know they overlap. For instance with recursive functions or we see that the code makes the arrays overlap somehow. This is then not the default behavior, but allows the user to use this without annotation effort.
I want to start with arrays. But this is also useful for other references where we use fields. So for examples attributes from classes or structs.
When we do want to support struct we do have the following pattern:
Where I might want to indicate that a.xs is unique and b.xs is unique. I'm unsure how I want to do this yet. Maybe like:
/*@ unique_field<0>(xs) @*/ struct d a
. Maybe any comments on this?