The Linear intermediate language: abstract syntax and semantcs 
The Linear language is a variant of LTL where control-flow is not
    expressed as a graph of basic blocks, but as a linear list of
    instructions with explicit labels and ``goto'' instructions. 
Require Import Coqlib.
Require Import AST Integers Values Memory Events Globalenvs Smallstep.
Require Import Op Locations LTL Conventions.
 Abstract syntax 
Definition label := 
positive.
Inductive instruction: 
Type :=
  | 
Lgetstack: 
slot -> 
Z -> 
typ -> 
mreg -> 
instruction
  | 
Lsetstack: 
mreg -> 
slot -> 
Z -> 
typ -> 
instruction
  | 
Lop: 
operation -> 
list mreg -> 
mreg -> 
instruction
  | 
Lload: 
memory_chunk -> 
addressing -> 
list mreg -> 
mreg -> 
instruction
  | 
Lstore: 
memory_chunk -> 
addressing -> 
list mreg -> 
mreg -> 
instruction
  | 
Lcall: 
signature -> 
mreg + 
ident -> 
instruction
  | 
Ltailcall: 
signature -> 
mreg + 
ident -> 
instruction
  | 
Lbuiltin: 
external_function -> 
list (
builtin_arg loc) -> 
builtin_res mreg -> 
instruction
  | 
Llabel: 
label -> 
instruction
  | 
Lgoto: 
label -> 
instruction
  | 
Lcond: 
condition -> 
list mreg -> 
label -> 
instruction
  | 
Ljumptable: 
mreg -> 
list label -> 
instruction
  | 
Lreturn: 
instruction.
Definition code: 
Type := 
list instruction.
Record function: 
Type := 
mkfunction {
  
fn_sig: 
signature;
  
fn_stacksize: 
Z;
  
fn_code: 
code
}.
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 genv := 
Genv.t fundef unit.
Definition locset := 
Locmap.t.
 Operational semantics 
Looking up labels in the instruction list.  
Definition is_label (
lbl: 
label) (
instr: 
instruction) : 
bool :=
  
match instr with
  | 
Llabel lbl' => 
if peq lbl lbl' 
then true else false
  | 
_ => 
false
  end.
Lemma is_label_correct:
  
forall lbl instr,
  
if is_label lbl instr then instr = 
Llabel lbl else instr <> 
Llabel lbl.
Proof.
  intros.  
destruct instr; 
simpl; 
try discriminate.
  
case (
peq lbl l); 
intro; 
congruence.
Qed.
 
find_label lbl c returns a list of instruction, suffix of the
  code c, that immediately follows the Llabel lbl pseudo-instruction.
  If the label lbl is multiply-defined, the first occurrence is
  retained.  If the label lbl is not defined, None is returned. 
Fixpoint find_label (
lbl: 
label) (
c: 
code) {
struct c} : 
option code :=
  
match c with
  | 
nil => 
None
  | 
i1 :: 
il => 
if is_label lbl i1 then Some il else find_label lbl il
  end.
Section RELSEM.
Variable ge: 
genv.
Definition find_function (
ros: 
mreg + 
ident) (
rs: 
locset) : 
option fundef :=
  
match ros with
  | 
inl r => 
Genv.find_funct ge (
rs (
R r))
  | 
inr symb =>
      
match Genv.find_symbol ge symb with
      | 
None => 
None
      | 
Some b => 
Genv.find_funct_ptr ge b
      end
  end.
Linear execution states. 
Inductive stackframe: 
Type :=
  | 
Stackframe:
      
forall (
f: 
function)         
(* calling function  *)
             (
sp: 
val)             
(* stack pointer in calling function  *)
             (
rs: 
locset)          
(* location state in calling function  *)
             (
c: 
code),            
(* program point in calling function  *)
      stackframe.
Inductive state: 
Type :=
  | 
State:
      
forall (
stack: 
list stackframe) 
(* call stack  *)
             (
f: 
function)            
(* function currently executing  *)
             (
sp: 
val)                
(* stack pointer  *)
             (
c: 
code)                
(* current program point  *)
             (
rs: 
locset)             
(* location state  *)
             (
m: 
mem),                
(* memory state  *)
      state
  | 
Callstate:
      
forall (
stack: 
list stackframe) 
(* call stack  *)
             (
f: 
fundef)              
(* function to call  *)
             (
rs: 
locset)             
(* location state at point of call  *)
             (
m: 
mem),                
(* memory state  *)
      state
  | 
Returnstate:
      
forall (
stack: 
list stackframe) 
(* call stack  *)
             (
rs: 
locset)             
(* location state at point of return  *)
             (
m: 
mem),                
(* memory state  *)
      state.
parent_locset cs returns the mapping of values for locations
  of the caller function. 
Definition parent_locset (
stack: 
list stackframe) : 
locset :=
  
match stack with
  | 
nil => 
Locmap.init Vundef
  | 
Stackframe f sp ls c :: 
stack' => 
ls
  end.
Inductive step: 
state -> 
trace -> 
state -> 
Prop :=
  | 
exec_Lgetstack:
      
forall s f sp sl ofs ty dst b rs m rs',
      
rs' = 
Locmap.set (
R dst) (
rs (
S sl ofs ty)) (
undef_regs (
destroyed_by_getstack sl) 
rs) ->
      
step (
State s f sp (
Lgetstack sl ofs ty dst :: 
b) 
rs m)
        
E0 (
State s f sp b rs' 
m)
  | 
exec_Lsetstack:
      
forall s f sp src sl ofs ty b rs m rs',
      
rs' = 
Locmap.set (
S sl ofs ty) (
rs (
R src)) (
undef_regs (
destroyed_by_setstack ty) 
rs) ->
      
step (
State s f sp (
Lsetstack src sl ofs ty :: 
b) 
rs m)
        
E0 (
State s f sp b rs' 
m)
  | 
exec_Lop:
      
forall s f sp op args res b rs m v rs',
      
eval_operation ge sp op (
reglist rs args) 
m = 
Some v ->
      
rs' = 
Locmap.set (
R res) 
v (
undef_regs (
destroyed_by_op op) 
rs) ->
      
step (
State s f sp (
Lop op args res :: 
b) 
rs m)
        
E0 (
State s f sp b rs' 
m)
  | 
exec_Lload:
      
forall s f sp chunk addr args dst b rs m a v rs',
      
eval_addressing ge sp addr (
reglist rs args) = 
Some a ->
      
Mem.loadv chunk m a = 
Some v ->
      
rs' = 
Locmap.set (
R dst) 
v (
undef_regs (
destroyed_by_load chunk addr) 
rs) ->
      
step (
State s f sp (
Lload chunk addr args dst :: 
b) 
rs m)
        
E0 (
State s f sp b rs' 
m)
  | 
exec_Lstore:
      
forall s f sp chunk addr args src b rs m m' 
a rs',
      
eval_addressing ge sp addr (
reglist rs args) = 
Some a ->
      
Mem.storev chunk m a (
rs (
R src)) = 
Some m' ->
      
rs' = 
undef_regs (
destroyed_by_store chunk addr) 
rs ->
      
step (
State s f sp (
Lstore chunk addr args src :: 
b) 
rs m)
        
E0 (
State s f sp b rs' 
m')
  | 
exec_Lcall:
      
forall s f sp sig ros b rs m f',
      
find_function ros rs = 
Some f' ->
      
sig = 
funsig f' ->
      
step (
State s f sp (
Lcall sig ros :: 
b) 
rs m)
        
E0 (
Callstate (
Stackframe f sp rs b:: 
s) 
f' 
rs m)
  | 
exec_Ltailcall:
      
forall s f stk sig ros b rs m rs' 
f' 
m',
      
rs' = 
return_regs (
parent_locset s) 
rs ->
      
find_function ros rs' = 
Some f' ->
      
sig = 
funsig f' ->
      
Mem.free m stk 0 
f.(
fn_stacksize) = 
Some m' ->
      
step (
State s f (
Vptr stk Ptrofs.zero) (
Ltailcall sig ros :: 
b) 
rs m)
        
E0 (
Callstate s f' 
rs' 
m')
  | 
exec_Lbuiltin:
      
forall s f sp rs m ef args res b vargs t vres rs' 
m',
      
eval_builtin_args ge rs sp m args vargs ->
      
external_call ef ge vargs m t vres m' ->
      
rs' = 
Locmap.setres res vres (
undef_regs (
destroyed_by_builtin ef) 
rs) ->
      
step (
State s f sp (
Lbuiltin ef args res :: 
b) 
rs m)
         
t (
State s f sp b rs' 
m')
  | 
exec_Llabel:
      
forall s f sp lbl b rs m,
      
step (
State s f sp (
Llabel lbl :: 
b) 
rs m)
        
E0 (
State s f sp b rs m)
  | 
exec_Lgoto:
      
forall s f sp lbl b rs m b',
      
find_label lbl f.(
fn_code) = 
Some b' ->
      
step (
State s f sp (
Lgoto lbl :: 
b) 
rs m)
        
E0 (
State s f sp b' 
rs m)
  | 
exec_Lcond_true:
      
forall s f sp cond args lbl b rs m rs' 
b',
      
eval_condition cond (
reglist rs args) 
m = 
Some true ->
      
rs' = 
undef_regs (
destroyed_by_cond cond) 
rs ->
      
find_label lbl f.(
fn_code) = 
Some b' ->
      
step (
State s f sp (
Lcond cond args lbl :: 
b) 
rs m)
        
E0 (
State s f sp b' 
rs' 
m)
  | 
exec_Lcond_false:
      
forall s f sp cond args lbl b rs m rs',
      
eval_condition cond (
reglist rs args) 
m = 
Some false ->
      
rs' = 
undef_regs (
destroyed_by_cond cond) 
rs ->
      
step (
State s f sp (
Lcond cond args lbl :: 
b) 
rs m)
        
E0 (
State s f sp b rs' 
m)
  | 
exec_Ljumptable:
      
forall s f sp arg tbl b rs m n lbl b' 
rs',
      
rs (
R arg) = 
Vint n ->
      
list_nth_z tbl (
Int.unsigned n) = 
Some lbl ->
      
find_label lbl f.(
fn_code) = 
Some b' ->
      
rs' = 
undef_regs (
destroyed_by_jumptable) 
rs ->
      
step (
State s f sp (
Ljumptable arg tbl :: 
b) 
rs m)
        
E0 (
State s f sp b' 
rs' 
m)
  | 
exec_Lreturn:
      
forall s f stk b rs m m',
      
Mem.free m stk 0 
f.(
fn_stacksize) = 
Some m' ->
      
step (
State s f (
Vptr stk Ptrofs.zero) (
Lreturn :: 
b) 
rs m)
        
E0 (
Returnstate s (
return_regs (
parent_locset s) 
rs) 
m')
  | 
exec_function_internal:
      
forall s f rs m rs' 
m' 
stk,
      
Mem.alloc m 0 
f.(
fn_stacksize) = (
m', 
stk) ->
      
rs' = 
undef_regs destroyed_at_function_entry (
call_regs rs) ->
      
step (
Callstate s (
Internal f) 
rs m)
        
E0 (
State s f (
Vptr stk Ptrofs.zero) 
f.(
fn_code) 
rs' 
m')
  | 
exec_function_external:
      
forall s ef args res rs1 rs2 m t m',
      
args = 
map (
fun p => 
Locmap.getpair p rs1) (
loc_arguments (
ef_sig ef)) ->
      
external_call ef ge args m t res m' ->
      
rs2 = 
Locmap.setpair (
loc_result (
ef_sig ef)) 
res rs1 ->
      
step (
Callstate s (
External ef) 
rs1 m)
         
t (
Returnstate s rs2 m')
  | 
exec_return:
      
forall s f sp rs0 c rs m,
      
step (
Returnstate (
Stackframe f sp rs0 c :: 
s) 
rs m)
        
E0 (
State s f sp c rs m).
End RELSEM.
Inductive initial_state (
p: 
program): 
state -> 
Prop :=
  | 
initial_state_intro: 
forall b f m0,
      
let ge := 
Genv.globalenv p in
      Genv.init_mem p = 
Some m0 ->
      
Genv.find_symbol ge p.(
prog_main) = 
Some b ->
      
Genv.find_funct_ptr ge b = 
Some f ->
      
funsig f = 
signature_main ->
      
initial_state p (
Callstate nil f (
Locmap.init Vundef) 
m0).
Inductive final_state: 
state -> 
int -> 
Prop :=
  | 
final_state_intro: 
forall rs m retcode,
      
Locmap.getpair (
map_rpair R (
loc_result signature_main)) 
rs = 
Vint retcode ->
      
final_state (
Returnstate nil rs m) 
retcode.
Definition semantics (
p: 
program) :=
  
Semantics step (
initial_state p) 
final_state (
Genv.globalenv p).