(** Convert a composite definition to its internal representation. The size and alignment of the composite are determined at this time. The alignment takes into account the [__Alignas] attributes associated with the definition.  The size is rounded up to a multiple of the alignment.  The conversion fails if a type of a member is not complete.  This rules out incorrect recursive definitions such as << struct s { int x; struct s next; } >> Here, when we process the definition of [struct s], the identifier [s] is not bound yet in the composite environment, hence field [next] has an incomplete type.  However, recursions that go through a pointer type are correctly handled: << struct s { int x; struct s * next; } >> Here, [next] has a pointer type, which is always complete, even though [s] is not yet bound to a composite. *)
Program Definition composite_of_def
(env: composite_env) (id: ident) (su: struct_or_union) (m: members) (a: attr)
: res composite :=
match env!id, complete_members env m return _ with
| Some _, _ =>
Error (MSG "Multiple definitions of struct or union " :: CTX id :: nil)
| None, false =>
Error (MSG "Incomplete struct or union " :: CTX id :: nil)
| None, true =>
let al := align_attr a (alignof_composite env m) in
OK {| co_su := su;
co_members := m;
co_attr := a;
co_sizeof := align (sizeof_composite env su m) al;
co_alignof := al;
co_rank := rank_members env m;
co_sizeof_pos := _;
co_alignof_two_p := _;
co_sizeof_alignof := _ |}
end.
Next Obligation.
apply Z.le_ge. eapply Z.le_trans. eapply sizeof_composite_pos.
apply align_le; apply alignof_composite_pos.
Defined.
Next Obligation.
apply align_attr_two_p. apply alignof_composite_two_p.
Defined.
Next Obligation.
apply align_divides. apply alignof_composite_pos.
Defined.
(** The composite environment for a program is obtained by entering its composite definitions in sequence.  The definitions are assumed to be listed in dependency order: the definition of a composite must precede all uses of this composite, unless the use is under a pointer or function type. *)
Local Open Scope error_monad_scope.
Fixpoint add_composite_definitions (env: composite_env) (defs: list composite_definition) : res composite_env :=
match defs with
| nil => OK env
| Composite id su m a :: defs =>
do co <- composite_of_def env id su m a;
add_composite_definitions (PTree.set id co env) defs
end.
Definition build_composite_env (defs: list composite_definition) :=
add_composite_definitions (PTree.empty _) defs.
(** Stability properties for alignments, sizes, and ranks.  If the type is complete in a composite environment [env], its size, alignment, and rank are unchanged if we add more definitions to [env]. *)
Section STABILITY.
Variables env env': composite_env.
Hypothesis extends: forall id co, env!id = Some co -> env'!id = Some co.

Lemma sizeof_composite_stable:
forall su m, complete_members env m = true -> sizeof_composite env' su m = sizeof_composite env su m.