Module Fang_asm
Manipulate and pretty-print assembly instructions.
Assembly instructions are defined by how they are pretty-printed but can be altered after construction to "swap out" different registers. This is useful, for example, for assigning real processor registers to the temporary storage locations in assembly emitted by earlier stages of the compiler ("coloring").
Instructions are annotated in a limited way so that they can analyzed by different stages of the compiler. For example, registers are marked as being read ("use") and/or written to ("def") by the instruction.
An example might be helpful.
type asm
A single assembly instruction.
All instructions are distinct, even if they are pretty-printed identically to other instructions.
module Asm : sig ... end
Assembly instructions.
Example
Suppose we wish to represent the instruction
add x, y
(which adds the value in the register x
to the value in the register y
and stores the result back in x
) for some registers x
and y
defined as follows:
let x = box ()
and y = box ()
The instruction can be defined as
let t =
Asm.v ~use:[x; y] ~def:[x] (fun ~use ~def pp_box ppf () ->
Fmt.pf ppf "@[<h>add@ %a,@ %a@]" pp_box (use 0) pp_box (use 1) )
x
and y
have been marked as "use" because the instruction reads their values. Only x
has been marked as "def" ("defined") because only x
is written to (y
is unchanged by the instruction).
The instruction is defined by specifying a pretty-printer for it. Instead of referring to the registers x
and y
directly we use the pp_box
formatter that is provided and refer to the registers by their index in the use
and def
lists.
The reason for this complexity is to make it easier to "swap out" different registers without having to reconstruct the instruction.
For example, here's a pretty-printer for our registers x
and y
let pp_reg ppf b =
if Box.equal b x then Fmt.text ppf "x"
else if Box.equal b y then Fmt.text ppf "y"
else Box.pp ppf b
with which we can pretty-print the instruction:
Fmt.strf "%a" (Asm.pp pp_reg) t
The result is "add x, y"
.
Now, let's replace y
with x
:
let t2 = Asm.replace ~target:y x t
The result of
Fmt.strf "%a" (Asm.pp pp_reg) t2
is "add x, x"
.