| [4b8f94a3] | 1 | #ifndef _CIVL_LOOP_ASSIGNS_GEN_
|
|---|
| 2 | #define _CIVL_LOOP_ASSIGNS_GEN_
|
|---|
| 3 |
|
|---|
| 4 | #include <civlc.cvh>
|
|---|
| 5 | #include <loop_assigns_gen.cvh>
|
|---|
| 6 | #include <mem.cvh>
|
|---|
| 7 |
|
|---|
| 8 | #pragma CIVL ACSL
|
|---|
| 9 |
|
|---|
| 10 | struct _loop_write_set {
|
|---|
| 11 | $mem widened; // all the widened references
|
|---|
| 12 | $mem havocables; // the references that can be safely havoced at the current state
|
|---|
| 13 | $mem samples; // all the collected memory location references, some of them may have been widened
|
|---|
| 14 | };
|
|---|
| 15 |
|
|---|
| 16 | /*@ depends_on \nothing;
|
|---|
| 17 | @ executes_when \true;
|
|---|
| 18 | @*/
|
|---|
| 19 | $state_f $loop_write_set $loop_write_set_new() {
|
|---|
| 20 | $mem m = $mem_new();
|
|---|
| 21 | $loop_write_set ws;
|
|---|
| 22 |
|
|---|
| 23 | ws.widened = m;
|
|---|
| 24 | ws.havocables = m;
|
|---|
| 25 | ws.samples = m;
|
|---|
| 26 | return ws;
|
|---|
| 27 | }
|
|---|
| 28 |
|
|---|
| 29 | $state_f $loop_write_set $loop_write_set_union($loop_write_set ws, $mem iter_mem) {
|
|---|
| 30 | ws.samples = $mem_union(ws.samples, iter_mem);
|
|---|
| 31 | ws.havocables = $mem_union(ws.widened, iter_mem);
|
|---|
| 32 | return ws;
|
|---|
| 33 | }
|
|---|
| 34 |
|
|---|
| [724e418] | 35 | $atomic_f _Bool $loop_write_set_havoc($loop_write_set ws) {
|
|---|
| 36 | return $mem_havoc(ws.havocables);
|
|---|
| [4b8f94a3] | 37 | }
|
|---|
| 38 |
|
|---|
| 39 | /* Implementation details for widening a $loop_write_set ws:
|
|---|
| 40 | * For each group g in samples, 1) if the group has no change after
|
|---|
| 41 | * last time it got widening, do not widening it again, no updates
|
|---|
| 42 | * for it ; 2) if the group has changed but the widening makes no
|
|---|
| 43 | * difference, no updates for it; 3) otherwise, widening the group,
|
|---|
| 44 | * update the group in sample set, widened set and the havocable
|
|---|
| 45 | * set.
|
|---|
| 46 | *
|
|---|
| 47 | */
|
|---|
| 48 | $state_f $loop_write_set $loop_write_set_widening($loop_write_set ws) {
|
|---|
| 49 | int num_sample_groups = $mem_num_groups(ws.samples);
|
|---|
| 50 | $mem * sample_groups = ($mem *)$malloc($here, sizeof($mem) * num_sample_groups);
|
|---|
| 51 | $mem widened_samples = $mem_new();
|
|---|
| 52 |
|
|---|
| 53 | $mem_groups(ws.samples, sample_groups);
|
|---|
| 54 | for (int i = 0; i < num_sample_groups; i++) {
|
|---|
| 55 | $mem old_widened_group = $mem_get_group(ws.widened, sample_groups[i]);
|
|---|
| 56 |
|
|---|
| 57 | if (!$mem_equals(old_widened_group, sample_groups[i])) {
|
|---|
| 58 | // if the group has changed from the last time widening, do the
|
|---|
| 59 | // widening again ...
|
|---|
| 60 | $mem widened_sample_group = $mem_widening(sample_groups[i]);
|
|---|
| 61 |
|
|---|
| 62 | if (!$mem_equals(widened_sample_group, sample_groups[i]))
|
|---|
| 63 | // if widening succeeds, unions the widened group into the widened set
|
|---|
| 64 | ws.widened = $mem_union(widened_sample_group, ws.widened);
|
|---|
| 65 | widened_samples = $mem_union(widened_samples, widened_sample_group);
|
|---|
| 66 | } else
|
|---|
| 67 | widened_samples = $mem_union(widened_samples, sample_groups[i]);
|
|---|
| 68 | }
|
|---|
| 69 | ws.havocables = $mem_union(ws.havocables, ws.widened);
|
|---|
| 70 | ws.samples = widened_samples;
|
|---|
| 71 | $free(sample_groups);
|
|---|
| 72 | return ws;
|
|---|
| 73 | }
|
|---|
| 74 |
|
|---|
| 75 | #endif
|
|---|
| 76 |
|
|---|