Module MachIR
Require Mach.
Import Coqlib Maps.
Import AST Op Events.
Import Memory.
Import Values Integers.
Import Mach.
Import Machregs.
Import Annotations.
Notation "
a ##
b" := (
List.map a b) (
at level 1).
Definition node :=
positive.
Inductive instruction:
Type :=
|
MIop:
operation ->
list mreg ->
mreg ->
node ->
instruction
|
MIload:
annotation ->
memory_chunk ->
addressing ->
list mreg ->
mreg ->
node ->
instruction
|
MIstore:
annotation ->
memory_chunk ->
addressing ->
list mreg ->
mreg ->
node ->
instruction
|
MIbuiltin:
external_function ->
list (
builtin_arg mreg) ->
builtin_res mreg ->
node ->
instruction
|
MIgoto:
node ->
instruction
|
MIcond:
condition ->
list mreg ->
node ->
node ->
instruction
|
MIcall:
signature ->
ident ->
node ->
instruction
|
MIgetparam:
int ->
typ ->
mreg ->
node ->
instruction
|
MIreturn:
instruction.
Definition code :=
PTree.t instruction.
Record function:
Type :=
mkfunction
{
fn_sig:
signature;
fn_code:
code;
fn_entrypoint :
node;
fn_stackdata:
Z;
fn_stacksize:
Z;
fn_link_ofs:
int;
fn_retaddr_ofs:
int }.
Definition fundef :=
AST.fundef function.
Definition program :=
AST.program fundef unit.
Definition funsig (
fd:
fundef) :=
match fd with
|
Internal f =>
fn_sig f
|
External ef =>
ef_sig ef
end.
Definition successors (
i:
instruction) :
list node :=
match i with
|
MIop _ _ _ s
|
MIload _ _ _ _ _ s
|
MIstore _ _ _ _ _ s
|
MIbuiltin _ _ _ s
|
MIgetparam _ _ _ s
|
MIcall _ _ s
|
MIgoto s =>
s ::
nil
|
MIcond _ _ ifso ifnot =>
ifso ::
ifnot ::
nil
|
MIreturn =>
nil
end.
Section RELSEM.
Variable ge:
genv.
Variable f:
function.
Variable sp:
val.
Mach execution states.
Inductive state:
Type :=
|
State:
forall (
pc:
node)
(
rs:
regset)
(* register state *)
(
m:
mem),
(* memory state *)
state.
Inductive step:
state ->
trace ->
state ->
Prop :=
|
exec_MIop:
forall op args res rs m v pc pc',
(
fn_code f)!
pc =
Some (
MIop op args res pc') ->
eval_operation ge sp op rs##
args m =
Some v ->
step (
State pc rs m)
E0 (
State pc' (
rs#
res <-
v)
m)
|
exec_MIload:
forall α
chunk addr args dst rs m a v pc pc',
(
fn_code f)!
pc =
Some (
MIload α
chunk addr args dst pc') ->
eval_addressing ge sp addr rs##
args =
Some a ->
Mem.loadv chunk m a =
Some v ->
step (
State pc rs m)
E0 (
State pc' (
rs#
dst <-
v)
m)
|
exec_MIstore:
forall α
chunk addr args src rs m m'
a pc pc',
(
fn_code f)!
pc =
Some (
MIstore α
chunk addr args src pc') ->
eval_addressing ge sp addr rs##
args =
Some a ->
Mem.storev chunk m a (
rs src) =
Some m' ->
step (
State pc rs m)
E0 (
State pc'
rs m')
|
exec_MIgoto:
forall rs m pc pc',
(
fn_code f)!
pc =
Some (
MIgoto pc') ->
step (
State pc rs m)
E0 (
State pc'
rs m)
|
exec_MIcond_true:
forall cond args rs m pc pc1 pc2,
(
fn_code f)!
pc =
Some (
MIcond cond args pc1 pc2) ->
eval_condition cond rs##
args m =
Some true ->
step (
State pc rs m)
E0 (
State pc1 rs m)
|
exec_MIcond_false:
forall cond args rs m pc pc1 pc2,
(
fn_code f)!
pc =
Some (
MIcond cond args pc1 pc2) ->
eval_condition cond rs##
args m =
Some false ->
step (
State pc rs m)
E0 (
State pc2 rs m)
|
exec_MIreturn:
forall rs m pc,
(
fn_code f)!
pc =
Some MIreturn ->
step (
State pc rs m)
E0 (
State pc rs m).
End RELSEM.
Definition find_pc_label (
lbl:
label) (
f:
Mach.function) :
option node :=
match find_label lbl (
Mach.fn_code f)
with
|
None =>
None
|
Some c =>
Some (
Ppred (
Pos.of_succ_nat (
length c)))
end.
Definition stack_annot f ofs :
annotation :=
let ofs :=
Int.sub ofs (
Int.repr (
Mach.fn_stackdata f))
in
(
xH,
ABlocal O xH (
ofs,
ofs) ::
nil).
Import Globalenvs.
Definition transl_instr (
ge:
Mach.genv) (
f:
Mach.function) (
pc:
node) (
i:
Mach.instruction) :=
let pc' :=
Ppred pc in
match i with
|
Mgetstack ofs ty dst =>
Some (
MIload (
stack_annot f ofs) (
chunk_of_type ty) (
Ainstack ofs)
nil dst pc')
|
Msetstack src ofs ty =>
Some (
MIstore (
stack_annot f ofs) (
chunk_of_type ty) (
Ainstack ofs)
nil src pc')
|
Mgetparam ofs ty dst =>
Some (
MIgetparam ofs ty dst pc')
|
Mop op args res =>
Some (
MIop op args res pc')
|
Mload α
chunk addr args dst =>
Some (
MIload α
chunk addr args dst pc')
|
Mstore α
chunk addr args src =>
Some (
MIstore α
chunk addr args src pc')
|
Mcall sg (
inr f) =>
Some (
MIcall sg f pc')
|
Mcall _ (
inl _) =>
None
|
Mtailcall sig _ =>
None
|
Mlabel lbl =>
Some (
MIgoto pc')
|
Mgoto lbl =>
match find_pc_label lbl f with
|
None =>
None
|
Some pc_lbl =>
Some (
MIgoto pc_lbl)
end
|
Mcond cond args lbl =>
match find_pc_label lbl f with
|
None =>
None
|
Some pc_lbl =>
Some (
MIcond cond args pc_lbl pc')
end
|
Mjumptable arg tbl =>
None
|
Mreturn =>
Some MIreturn
|
Mbuiltin ef args dst =>
Some (
MIbuiltin ef args dst pc')
end.
Fixpoint transl_fun_aux ge (
f:
Mach.function) (
c:
Mach.code)
:
option (
node *
code) :=
match c with
|
nil =>
Some (
xH,
PTree.empty _)
|
i::
q =>
match transl_fun_aux ge f q with
|
None =>
None
|
Some (
pc,
c') =>
match transl_instr ge f pc i with
|
None =>
None
|
Some i' =>
Some (
Psucc pc,
PTree.set pc i'
c')
end
end
end.
Definition transl_fun ge (
f:
Mach.function) :
option (
node*
code) :=
transl_fun_aux ge f f.(
Mach.fn_code) .
Definition checker (
ge:
Mach.genv) (
f:
Mach.function) :
bool :=
match Mach.fn_code f with
|
nil =>
false
|
code =>
List.forallb
(
fun ins =>
match ins with
|
Mach.Mcall _ (
inl _)
|
Mach.Mtailcall _ _
|
Mach.Mjumptable _ _
=>
false
|
Mach.Mgoto lbl
|
Mach.Mcond _ _ lbl =>
match find_label lbl f.(
Mach.fn_code)
with
|
Some _ =>
true
|
None =>
false
end
|
Mach.Mop _ _ _
|
Mach.Mload _ _ _ _ _
|
Mach.Mstore _ _ _ _ _
|
Mach.Mlabel _
|
Mach.Mcall _ (
inr _)
|
Mach.Mgetparam _ _ _
|
Mach.Mreturn
|
Mach.Mgetstack _ _ _
|
Mach.Msetstack _ _ _
|
Mach.Mbuiltin _ _ _
=>
true
end)
code
end.
Import Errors.
Local Open Scope error_monad_scope.
Definition transl_function ge (
f:
Mach.function) :
res function :=
if checker ge f then
match transl_fun ge f with
|
None =>
Errors.Error (
Errors.MSG "
MachIR conversion failed" ::
nil)
|
Some (
pc,
c) =>
Errors.OK {|
fn_sig :=
f.(
Mach.fn_sig);
fn_code :=
c;
fn_entrypoint :=
Ppred pc;
fn_stackdata :=
f.(
Mach.fn_stackdata);
fn_stacksize :=
f.(
Mach.fn_stacksize);
fn_link_ofs :=
f.(
Mach.fn_link_ofs);
fn_retaddr_ofs :=
f.(
Mach.fn_retaddr_ofs)
|}
end
else Errors.Error (
Errors.MSG "
MachIR conversion failed :
checker" ::
nil).
Definition transl_fundef ge (
fd:
Mach.fundef) :
res fundef :=
match fd with
|
Internal fn =>
do fn' <-
transl_function ge fn;
OK (
Internal fn')
|
External ef =>
OK (
External ef)
end.
Definition transl_program (
p:
Mach.program) :
res program :=
let ge :=
Genv.globalenv p in
transform_partial_program (
transl_fundef ge)
p.