38 lines
1.1 KiB
OCaml
38 lines
1.1 KiB
OCaml
type t = {
|
|
size : int;
|
|
(* alignment = 1 << align_exp *)
|
|
align_exp : char;
|
|
}
|
|
|
|
open Int
|
|
|
|
let alignment_of_exp x = shift_left 1 (Char.code x)
|
|
|
|
let alignment x = alignment_of_exp x.align_exp
|
|
|
|
let max_size_for_align_exp x =
|
|
let y = alignment_of_exp x in
|
|
let isz_max_sc = shift_right max_int 1 |> succ in
|
|
isz_max_sc - y
|
|
|
|
(** appends a layout to this one, returns new layout and the offset **)
|
|
let push orig next =
|
|
let align_exp = max (Char.code orig.align_exp) (Char.code next.align_exp) |> Char.chr in
|
|
|
|
(* fill up ourselves so that the other element is correctly aligned *)
|
|
let smask_sh = alignment next in
|
|
let smask = pred smask_sh in
|
|
let smasked = logand orig.size smask in
|
|
|
|
(* align size *)
|
|
let size = if compare smasked zero == 0 then orig.size else (
|
|
add (sub orig.size smasked) smask_sh
|
|
) in
|
|
|
|
let offset = size in
|
|
let size = size + next.size in
|
|
if size <= max_size_for_align_exp align_exp
|
|
then Option.some ({ size; align_exp; }, offset)
|
|
else Option.none
|
|
|
|
let finish orig = push orig { size = 0; align_exp = orig.align_exp }
|