aboutsummaryrefslogtreecommitdiffstats
path: root/cfrontend/Csem.v
diff options
context:
space:
mode:
Diffstat (limited to 'cfrontend/Csem.v')
-rw-r--r--cfrontend/Csem.v119
1 files changed, 67 insertions, 52 deletions
diff --git a/cfrontend/Csem.v b/cfrontend/Csem.v
index 6d2b470f..6698c56f 100644
--- a/cfrontend/Csem.v
+++ b/cfrontend/Csem.v
@@ -6,10 +6,11 @@
(* *)
(* Copyright Institut National de Recherche en Informatique et en *)
(* Automatique. All rights reserved. This file is distributed *)
-(* under the terms of the GNU General Public License as published by *)
-(* the Free Software Foundation, either version 2 of the License, or *)
-(* (at your option) any later version. This file is also distributed *)
-(* under the terms of the INRIA Non-Commercial License Agreement. *)
+(* under the terms of the GNU Lesser General Public License as *)
+(* published by the Free Software Foundation, either version 2.1 of *)
+(* the License, or (at your option) any later version. *)
+(* This file is also distributed under the terms of the *)
+(* INRIA Non-Commercial License Agreement. *)
(* *)
(* *********************************************************************)
@@ -45,49 +46,59 @@ Section SEMANTICS.
Variable ge: genv.
-(** [deref_loc ty m b ofs t v] computes the value of a datum
- of type [ty] residing in memory [m] at block [b], offset [ofs].
+(** [deref_loc ty m b ofs bf t v] computes the value of a datum
+ of type [ty] residing in memory [m] at block [b], offset [ofs],
+ and bitfield designation [bf].
If the type [ty] indicates an access by value, the corresponding
memory load is performed. If the type [ty] indicates an access by
reference, the pointer [Vptr b ofs] is returned. [v] is the value
returned, and [t] the trace of observables (nonempty if this is
a volatile access). *)
-Inductive deref_loc (ty: type) (m: mem) (b: block) (ofs: ptrofs) : trace -> val -> Prop :=
+Inductive deref_loc (ty: type) (m: mem) (b: block) (ofs: ptrofs) :
+ bitfield -> trace -> val -> Prop :=
| deref_loc_value: forall chunk v,
access_mode ty = By_value chunk ->
type_is_volatile ty = false ->
Mem.loadv chunk m (Vptr b ofs) = Some v ->
- deref_loc ty m b ofs E0 v
+ deref_loc ty m b ofs Full E0 v
| deref_loc_volatile: forall chunk t v,
access_mode ty = By_value chunk -> type_is_volatile ty = true ->
volatile_load ge chunk m b ofs t v ->
- deref_loc ty m b ofs t v
+ deref_loc ty m b ofs Full t v
| deref_loc_reference:
access_mode ty = By_reference ->
- deref_loc ty m b ofs E0 (Vptr b ofs)
+ deref_loc ty m b ofs Full E0 (Vptr b ofs)
| deref_loc_copy:
access_mode ty = By_copy ->
- deref_loc ty m b ofs E0 (Vptr b ofs).
+ deref_loc ty m b ofs Full E0 (Vptr b ofs)
+ | deref_loc_bitfield: forall sz sg pos width v,
+ load_bitfield ty sz sg pos width m (Vptr b ofs) v ->
+ deref_loc ty m b ofs (Bits sz sg pos width) E0 v.
-(** Symmetrically, [assign_loc ty m b ofs v t m'] returns the
+(** Symmetrically, [assign_loc ty m b ofs bf v t m' v'] returns the
memory state after storing the value [v] in the datum
- of type [ty] residing in memory [m] at block [b], offset [ofs].
+ of type [ty] residing in memory [m] at block [b], offset [ofs],
+ and bitfield designation [bf].
This is allowed only if [ty] indicates an access by value or by copy.
[m'] is the updated memory state and [t] the trace of observables
- (nonempty if this is a volatile store). *)
+ (nonempty if this is a volatile store).
+ [v'] is the result value of the assignment. It is equal to [v]
+ if [bf] is [Full], and to [v] normalized to the width and signedness
+ of the bitfield [bf] otherwise.
+*)
Inductive assign_loc (ty: type) (m: mem) (b: block) (ofs: ptrofs):
- val -> trace -> mem -> Prop :=
+ bitfield -> val -> trace -> mem -> val -> Prop :=
| assign_loc_value: forall v chunk m',
access_mode ty = By_value chunk ->
type_is_volatile ty = false ->
Mem.storev chunk m (Vptr b ofs) v = Some m' ->
- assign_loc ty m b ofs v E0 m'
+ assign_loc ty m b ofs Full v E0 m' v
| assign_loc_volatile: forall v chunk t m',
access_mode ty = By_value chunk -> type_is_volatile ty = true ->
volatile_store ge chunk m b ofs v t m' ->
- assign_loc ty m b ofs v t m'
+ assign_loc ty m b ofs Full v t m' v
| assign_loc_copy: forall b' ofs' bytes m',
access_mode ty = By_copy ->
(alignof_blockcopy ge ty | Ptrofs.unsigned ofs') ->
@@ -97,7 +108,10 @@ Inductive assign_loc (ty: type) (m: mem) (b: block) (ofs: ptrofs):
\/ Ptrofs.unsigned ofs + sizeof ge ty <= Ptrofs.unsigned ofs' ->
Mem.loadbytes m b' (Ptrofs.unsigned ofs') (sizeof ge ty) = Some bytes ->
Mem.storebytes m b (Ptrofs.unsigned ofs) bytes = Some m' ->
- assign_loc ty m b ofs (Vptr b' ofs') E0 m'.
+ assign_loc ty m b ofs Full (Vptr b' ofs') E0 m' (Vptr b' ofs')
+ | assign_loc_bitfield: forall sz sg pos width v m' v',
+ store_bitfield ty sz sg pos width m (Vptr b ofs) v m' v' ->
+ assign_loc ty m b ofs (Bits sz sg pos width) v E0 m' v'.
(** Allocation of function-local variables.
[alloc_variables e1 m1 vars e2 m2] allocates one memory block
@@ -130,9 +144,9 @@ Inductive bind_parameters (e: env):
forall m,
bind_parameters e m nil nil m
| bind_parameters_cons:
- forall m id ty params v1 vl b m1 m2,
+ forall m id ty params v1 vl v1' b m1 m2,
PTree.get id e = Some(b, ty) ->
- assign_loc ty m b Ptrofs.zero v1 E0 m1 ->
+ assign_loc ty m b Ptrofs.zero Full v1 E0 m1 v1' ->
bind_parameters e m1 params vl m2 ->
bind_parameters e m ((id, ty) :: params) (v1 :: vl) m2.
@@ -201,34 +215,35 @@ Inductive lred: expr -> mem -> expr -> mem -> Prop :=
| red_var_local: forall x ty m b,
e!x = Some(b, ty) ->
lred (Evar x ty) m
- (Eloc b Ptrofs.zero ty) m
+ (Eloc b Ptrofs.zero Full ty) m
| red_var_global: forall x ty m b,
e!x = None ->
Genv.find_symbol ge x = Some b ->
lred (Evar x ty) m
- (Eloc b Ptrofs.zero ty) m
+ (Eloc b Ptrofs.zero Full ty) m
| red_deref: forall b ofs ty1 ty m,
lred (Ederef (Eval (Vptr b ofs) ty1) ty) m
- (Eloc b ofs ty) m
- | red_field_struct: forall b ofs id co a f ty m delta,
+ (Eloc b ofs Full ty) m
+ | red_field_struct: forall b ofs id co a f ty m delta bf,
ge.(genv_cenv)!id = Some co ->
- field_offset ge f (co_members co) = OK delta ->
+ field_offset ge f (co_members co) = OK (delta, bf) ->
lred (Efield (Eval (Vptr b ofs) (Tstruct id a)) f ty) m
- (Eloc b (Ptrofs.add ofs (Ptrofs.repr delta)) ty) m
- | red_field_union: forall b ofs id co a f ty m,
+ (Eloc b (Ptrofs.add ofs (Ptrofs.repr delta)) bf ty) m
+ | red_field_union: forall b ofs id co a f ty m delta bf,
ge.(genv_cenv)!id = Some co ->
+ union_field_offset ge f (co_members co) = OK (delta, bf) ->
lred (Efield (Eval (Vptr b ofs) (Tunion id a)) f ty) m
- (Eloc b ofs ty) m.
+ (Eloc b (Ptrofs.add ofs (Ptrofs.repr delta)) bf ty) m.
(** Head reductions for r-values *)
Inductive rred: expr -> mem -> trace -> expr -> mem -> Prop :=
- | red_rvalof: forall b ofs ty m t v,
- deref_loc ty m b ofs t v ->
- rred (Evalof (Eloc b ofs ty) ty) m
+ | red_rvalof: forall b ofs bf ty m t v,
+ deref_loc ty m b ofs bf t v ->
+ rred (Evalof (Eloc b ofs bf ty) ty) m
t (Eval v ty) m
| red_addrof: forall b ofs ty1 ty m,
- rred (Eaddrof (Eloc b ofs ty1) ty) m
+ rred (Eaddrof (Eloc b ofs Full ty1) ty) m
E0 (Eval (Vptr b ofs) ty) m
| red_unop: forall op v1 ty1 ty m v,
sem_unary_operation op v1 ty1 m = Some v ->
@@ -268,21 +283,21 @@ Inductive rred: expr -> mem -> trace -> expr -> mem -> Prop :=
| red_alignof: forall ty1 ty m,
rred (Ealignof ty1 ty) m
E0 (Eval (Vptrofs (Ptrofs.repr (alignof ge ty1))) ty) m
- | red_assign: forall b ofs ty1 v2 ty2 m v t m',
+ | red_assign: forall b ofs ty1 bf v2 ty2 m v t m' v',
sem_cast v2 ty2 ty1 m = Some v ->
- assign_loc ty1 m b ofs v t m' ->
- rred (Eassign (Eloc b ofs ty1) (Eval v2 ty2) ty1) m
- t (Eval v ty1) m'
- | red_assignop: forall op b ofs ty1 v2 ty2 tyres m t v1,
- deref_loc ty1 m b ofs t v1 ->
- rred (Eassignop op (Eloc b ofs ty1) (Eval v2 ty2) tyres ty1) m
- t (Eassign (Eloc b ofs ty1)
+ assign_loc ty1 m b ofs bf v t m' v' ->
+ rred (Eassign (Eloc b ofs bf ty1) (Eval v2 ty2) ty1) m
+ t (Eval v' ty1) m'
+ | red_assignop: forall op b ofs ty1 bf v2 ty2 tyres m t v1,
+ deref_loc ty1 m b ofs bf t v1 ->
+ rred (Eassignop op (Eloc b ofs bf ty1) (Eval v2 ty2) tyres ty1) m
+ t (Eassign (Eloc b ofs bf ty1)
(Ebinop op (Eval v1 ty1) (Eval v2 ty2) tyres) ty1) m
- | red_postincr: forall id b ofs ty m t v1 op,
- deref_loc ty m b ofs t v1 ->
+ | red_postincr: forall id b ofs ty bf m t v1 op,
+ deref_loc ty m b ofs bf t v1 ->
op = match id with Incr => Oadd | Decr => Osub end ->
- rred (Epostincr id (Eloc b ofs ty) ty) m
- t (Ecomma (Eassign (Eloc b ofs ty)
+ rred (Epostincr id (Eloc b ofs bf ty) ty) m
+ t (Ecomma (Eassign (Eloc b ofs bf ty)
(Ebinop op (Eval v1 ty)
(Eval (Vint Int.one) type_int32s)
(incrdecr_type ty))
@@ -408,8 +423,8 @@ with contextlist: kind -> (expr -> exprlist) -> Prop :=
Inductive imm_safe: kind -> expr -> mem -> Prop :=
| imm_safe_val: forall v ty m,
imm_safe RV (Eval v ty) m
- | imm_safe_loc: forall b ofs ty m,
- imm_safe LV (Eloc b ofs ty) m
+ | imm_safe_loc: forall b ofs bf ty m,
+ imm_safe LV (Eloc b ofs bf ty) m
| imm_safe_lred: forall to C e m e' m',
lred e m e' m' ->
context LV to C ->
@@ -838,12 +853,12 @@ Lemma semantics_single_events:
Proof.
unfold semantics; intros; red; simpl; intros.
set (ge := globalenv p) in *.
- assert (DEREF: forall chunk m b ofs t v, deref_loc ge chunk m b ofs t v -> (length t <= 1)%nat).
- intros. inv H0; simpl; try omega. inv H3; simpl; try omega.
- assert (ASSIGN: forall chunk m b ofs t v m', assign_loc ge chunk m b ofs v t m' -> (length t <= 1)%nat).
- intros. inv H0; simpl; try omega. inv H3; simpl; try omega.
+ assert (DEREF: forall chunk m b ofs bf t v, deref_loc ge chunk m b ofs bf t v -> (length t <= 1)%nat).
+ { intros. inv H0; simpl; try lia. inv H3; simpl; try lia. }
+ assert (ASSIGN: forall chunk m b ofs bf t v m' v', assign_loc ge chunk m b ofs bf v t m' v' -> (length t <= 1)%nat).
+ { intros. inv H0; simpl; try lia. inv H3; simpl; try lia. }
destruct H.
- inv H; simpl; try omega. inv H0; eauto; simpl; try omega.
+ inv H; simpl; try lia. inv H0; eauto; simpl; try lia.
eapply external_call_trace_length; eauto.
- inv H; simpl; try omega. eapply external_call_trace_length; eauto.
+ inv H; simpl; try lia. eapply external_call_trace_length; eauto.
Qed.