(** * Relational specification of the translation of initializers *)
Definition tr_padding (frm to: Z) : list init_data :=
if zlt frm to then Init_space (to - frm) :: nil else nil.
Inductive tr_init: type -> initializer -> list init_data -> Prop :=
| tr_init_sgl: forall ty a d,
transl_init_single ge ty a = OK d ->
tr_init ty (Init_single a) (d :: nil)
| tr_init_arr: forall tyelt nelt attr il d,
tr_init_array tyelt il (Z.max 0 nelt) d ->
tr_init (Tarray tyelt nelt attr) (Init_array il) d
| tr_init_str: forall id attr il co d,
lookup_composite ge id = OK co -> co_su co = Struct ->
tr_init_struct (Tstruct id attr) (co_members co) il 0 d ->
tr_init (Tstruct id attr) (Init_struct il) d
| tr_init_uni: forall id attr f i1 co ty1 d,
lookup_composite ge id = OK co -> co_su co = Union -> field_type f (co_members co) = OK ty1 ->
tr_init ty1 i1 d ->
tr_init (Tunion id attr) (Init_union f i1)
(d ++ tr_padding (sizeof ge ty1) (sizeof ge (Tunion id attr)))
with tr_init_array: type -> initializer_list -> Z -> list init_data -> Prop :=
| tr_init_array_nil_0: forall ty,
tr_init_array ty Init_nil 0 nil
| tr_init_array_nil_pos: forall ty sz,
0 < sz ->
tr_init_array ty Init_nil sz (Init_space (sz * sizeof ge ty) :: nil)
| tr_init_array_cons: forall ty i il sz d1 d2,
tr_init ty i d1 -> tr_init_array ty il (sz - 1) d2 ->
tr_init_array ty (Init_cons i il) sz (d1 ++ d2)
with tr_init_struct: type -> members -> initializer_list -> Z -> list init_data -> Prop :=
| tr_init_struct_nil: forall ty pos,
tr_init_struct ty nil Init_nil pos (tr_padding pos (sizeof ge ty))
| tr_init_struct_cons: forall ty f1 ty1 fl i1 il pos d1 d2,
let pos1 := align pos (alignof ge ty1) in
tr_init ty1 i1 d1 ->
tr_init_struct ty fl il (pos1 + sizeof ge ty1) d2 ->
tr_init_struct ty ((f1, ty1) :: fl) (Init_cons i1 il)
pos (tr_padding pos pos1 ++ d1 ++ d2).

Lemma transl_init_rec_spec:
forall i ty k res,
transl_init_rec ge ty i k = OK res ->
exists d, tr_init ty i d /\ res = rev d ++ k
with transl_init_array_spec:
forall il ty sz k res,
transl_init_array ge ty il sz k = OK res ->
exists d, tr_init_array ty il sz d /\ res = rev d ++ k
with transl_init_struct_spec:
forall il ty fl pos k res,
transl_init_struct ge ty fl il pos k = OK res ->
exists d, tr_init_struct ty fl il pos d /\ res = rev d ++ k.