aboutsummaryrefslogtreecommitdiffstats
path: root/cfrontend/Cshmgen.v
diff options
context:
space:
mode:
Diffstat (limited to 'cfrontend/Cshmgen.v')
-rw-r--r--cfrontend/Cshmgen.v139
1 files changed, 95 insertions, 44 deletions
diff --git a/cfrontend/Cshmgen.v b/cfrontend/Cshmgen.v
index 5bd12d00..9e804176 100644
--- a/cfrontend/Cshmgen.v
+++ b/cfrontend/Cshmgen.v
@@ -372,19 +372,56 @@ Definition make_cmp (c: comparison) (e1: expr) (ty1: type) (e2: expr) (ty2: type
e1 ty1 e2 ty2
end.
+(** Auxiliary for translating bitfield accesses *)
+
+Definition make_extract_bitfield (sz: intsize) (sg: signedness) (pos width: Z)
+ (addr: expr) : res expr :=
+ if zle 0 pos && zlt 0 width && zle (pos + width) (bitsize_carrier sz) then
+ let amount1 := Int.repr (Int.zwordsize - first_bit sz pos width - width) in
+ let amount2 := Int.repr (Int.zwordsize - width) in
+ let e1 := Eload (chunk_for_carrier sz) addr in
+ let e2 := Ebinop Oshl e1 (make_intconst amount1) in
+ let e3 := Ebinop (if intsize_eq sz IBool
+ || signedness_eq sg Unsigned then Oshru else Oshr)
+ e2 (make_intconst amount2) in
+ OK e3
+ else
+ Error(msg "Cshmgen.extract_bitfield").
+
(** [make_load addr ty_res] loads a value of type [ty_res] from
- the memory location denoted by the Csharpminor expression [addr].
+ the memory location denoted by the Csharpminor expression [addr]
+ and the bitfield designator [bf].
If [ty_res] is an array or function type, returns [addr] instead,
as consistent with C semantics.
*)
-Definition make_load (addr: expr) (ty_res: type) :=
- match (access_mode ty_res) with
- | By_value chunk => OK (Eload chunk addr)
- | By_reference => OK addr
- | By_copy => OK addr
- | By_nothing => Error (msg "Cshmgen.make_load")
- end.
+Definition make_load (addr: expr) (ty_res: type) (bf: bitfield) :=
+ match bf with
+ | Full =>
+ match access_mode ty_res with
+ | By_value chunk => OK (Eload chunk addr)
+ | By_reference => OK addr
+ | By_copy => OK addr
+ | By_nothing => Error (msg "Cshmgen.make_load")
+ end
+ | Bits sz sg pos width =>
+ make_extract_bitfield sz sg pos width addr
+ end.
+
+(** Auxiliary for translating bitfield updates *)
+
+Definition make_store_bitfield (sz: intsize) (sg: signedness) (pos width: Z)
+ (addr val: expr) : res stmt :=
+ if zle 0 pos && zlt 0 width && zle (pos + width) (bitsize_carrier sz) then
+ let amount := first_bit sz pos width in
+ let mask := Int.shl (Int.repr (two_p width - 1)) (Int.repr amount) in
+ let e1 := Eload (chunk_for_carrier sz) addr in
+ let e2 := Ebinop Oshl val (make_intconst (Int.repr amount)) in
+ let e3 := Ebinop Oor (Ebinop Oand e2 (make_intconst mask))
+ (Ebinop Oand e1 (make_intconst (Int.not mask))) in
+ OK (Sstore (chunk_for_carrier sz) addr e3)
+ else
+ Error(msg "Cshmgen.make_store_bitfield").
(** [make_memcpy dst src ty] returns a [memcpy] builtin appropriate for
by-copy assignment of a value of Clight type [ty]. *)
@@ -394,16 +431,21 @@ Definition make_memcpy (ce: composite_env) (dst src: expr) (ty: type) :=
OK (Sbuiltin None (EF_memcpy sz (Ctypes.alignof_blockcopy ce ty))
(dst :: src :: nil)).
-(** [make_store addr ty rhs] stores the value of the
+(** [make_store addr ty bf rhs] stores the value of the
Csharpminor expression [rhs] into the memory location denoted by the
Csharpminor expression [addr].
- [ty] is the type of the memory location. *)
-
-Definition make_store (ce: composite_env) (addr: expr) (ty: type) (rhs: expr) :=
- match access_mode ty with
- | By_value chunk => OK (Sstore chunk addr rhs)
- | By_copy => make_memcpy ce addr rhs ty
- | _ => Error (msg "Cshmgen.make_store")
+ [ty] is the type of the memory location and [bf] a bitfield designator. *)
+
+Definition make_store (ce: composite_env) (addr: expr) (ty: type) (bf: bitfield) (rhs: expr) :=
+ match bf with
+ | Full =>
+ match access_mode ty with
+ | By_value chunk => OK (Sstore chunk addr rhs)
+ | By_copy => make_memcpy ce addr rhs ty
+ | _ => Error (msg "Cshmgen.make_store")
+ end
+ | Bits sz sg pos width =>
+ make_store_bitfield sz sg pos width addr rhs
end.
(** ** Translation of operators *)
@@ -441,23 +483,27 @@ Definition transl_binop (ce: composite_env)
(** ** Translation of field accesses *)
-Definition make_field_access (ce: composite_env) (ty: type) (f: ident) (a: expr) : res expr :=
- match ty with
- | Tstruct id _ =>
- match ce!id with
- | None =>
- Error (MSG "Undefined struct " :: CTX id :: nil)
- | Some co =>
- do ofs <- field_offset ce f (co_members co);
- OK (if Archi.ptr64
- then Ebinop Oaddl a (make_longconst (Int64.repr ofs))
- else Ebinop Oadd a (make_intconst (Int.repr ofs)))
- end
- | Tunion id _ =>
- OK a
- | _ =>
- Error(msg "Cshmgen.make_field_access")
- end.
+Definition make_field_access (ce: composite_env) (ty: type) (f: ident) (a: expr) : res (expr * bitfield) :=
+ do (ofs, bf) <-
+ match ty with
+ | Tstruct id _ =>
+ match ce!id with
+ | None => Error (MSG "Undefined struct " :: CTX id :: nil)
+ | Some co => field_offset ce f (co_members co)
+ end
+ | Tunion id _ =>
+ match ce!id with
+ | None => Error (MSG "Undefined union " :: CTX id :: nil)
+ | Some co => union_field_offset ce f (co_members co)
+ end
+ | _ =>
+ Error(msg "Cshmgen.make_field_access")
+ end;
+ let a' :=
+ if Archi.ptr64
+ then Ebinop Oaddl a (make_longconst (Int64.repr ofs))
+ else Ebinop Oadd a (make_intconst (Int.repr ofs)) in
+ OK (a', bf).
(** * Translation of expressions *)
@@ -476,14 +522,18 @@ Fixpoint transl_expr (ce: composite_env) (a: Clight.expr) {struct a} : res expr
| Clight.Econst_long n _ =>
OK(make_longconst n)
| Clight.Evar id ty =>
- make_load (Eaddrof id) ty
+ make_load (Eaddrof id) ty Full
| Clight.Etempvar id ty =>
OK(Evar id)
| Clight.Ederef b ty =>
do tb <- transl_expr ce b;
- make_load tb ty
+ make_load tb ty Full
| Clight.Eaddrof b _ =>
- transl_lvalue ce b
+ do (tb, bf) <- transl_lvalue ce b;
+ match bf with
+ | Full => OK tb
+ | Bits _ _ _ _ => Error (msg "Cshmgen.transl_expr: addrof bitfield")
+ end
| Clight.Eunop op b _ =>
do tb <- transl_expr ce b;
transl_unop op tb (typeof b)
@@ -496,8 +546,8 @@ Fixpoint transl_expr (ce: composite_env) (a: Clight.expr) {struct a} : res expr
make_cast (typeof b) ty tb
| Clight.Efield b i ty =>
do tb <- transl_expr ce b;
- do addr <- make_field_access ce (typeof b) i tb;
- make_load addr ty
+ do (addr, bf) <- make_field_access ce (typeof b) i tb;
+ make_load addr ty bf
| Clight.Esizeof ty' ty =>
do sz <- sizeof ce ty'; OK(make_ptrofsconst sz)
| Clight.Ealignof ty' ty =>
@@ -506,15 +556,16 @@ Fixpoint transl_expr (ce: composite_env) (a: Clight.expr) {struct a} : res expr
(** [transl_lvalue a] returns the Csharpminor code that evaluates
[a] as a lvalue, that is, code that returns the memory address
- where the value of [a] is stored.
+ where the value of [a] is stored. It also returns the bitfield to be
+ accessed at this address, if appropriate.
*)
-with transl_lvalue (ce: composite_env) (a: Clight.expr) {struct a} : res expr :=
+with transl_lvalue (ce: composite_env) (a: Clight.expr) {struct a} : res (expr * bitfield) :=
match a with
| Clight.Evar id _ =>
- OK (Eaddrof id)
+ OK (Eaddrof id, Full)
| Clight.Ederef b _ =>
- transl_expr ce b
+ do tb <- transl_expr ce b; OK (tb, Full)
| Clight.Efield b i ty =>
do tb <- transl_expr ce b;
make_field_access ce (typeof b) i tb
@@ -618,10 +669,10 @@ Fixpoint transl_statement (ce: composite_env) (tyret: type) (nbrk ncnt: nat)
| Clight.Sskip =>
OK Sskip
| Clight.Sassign b c =>
- do tb <- transl_lvalue ce b;
+ do (tb, bf) <- transl_lvalue ce b;
do tc <- transl_expr ce c;
do tc' <- make_cast (typeof c) (typeof b) tc;
- make_store ce tb (typeof b) tc'
+ make_store ce tb (typeof b) bf tc'
| Clight.Sset x b =>
do tb <- transl_expr ce b;
OK(Sset x tb)