2 (** This module provides an interpreter for the RTL language. *)
5 let error_prefix = "RTL interpret"
6 let error s = Error.global_error error_prefix s
9 module Mem = Driver.RTLMemory
10 module Val = Mem.Value
11 let chunk = Driver.RTLMemory.int_size
12 module Eval = I8051.Eval (Val)
15 type memory = RTL.function_def Mem.memory
18 (* Local environments. They associate a value to the registers of the function
21 type local_env = Val.t Register.Map.t
23 (* Call frames. The execution state has a call stack, each element of the stack
24 being composed of the return registers to store the result of the callee, the
25 graph, the node, the local environment and the value of the carry to resume
26 the execution of the caller. *)
29 { ret_regs : Register.t list ;
36 (* Execution states. There are three possible states :
37 - The constructor [State] represents a state when executing a function
38 - The constructor [CallState] represents a state when calling a function
39 - The constructor [ReturnState] represents a state when leaving a function *)
42 | State of stack_frame list * RTL.graph * Label.t * Val.address (* sp *) *
43 local_env * Val.t (* carry *) * memory * CostLabel.t list
44 | CallState of stack_frame list * RTL.function_def *
45 Val.t list (* args *) * memory * CostLabel.t list
46 | ReturnState of stack_frame list * Val.t list (* return values *) *
47 memory * CostLabel.t list
49 let string_of_local_env lenv =
52 (if Val.eq v Val.undef then ""
53 else (Register.print x) ^ " = " ^ (Val.to_string v) ^ " ") in
54 Register.Map.fold f lenv ""
56 let string_of_args args =
57 let f s v = s ^ " " ^ (Val.to_string v) in
58 List.fold_left f "" args
60 let print_state = function
61 | State (_, _, lbl, sp, lenv, carry, mem, _) ->
62 Printf.printf "Stack pointer: %s\n\nCarry: %s\n\nLocal environment:\n%s\n\nMemory:%s\nRegular state: %s\n\n%!"
63 (Val.string_of_address sp)
65 (string_of_local_env lenv)
68 | CallState (_, _, args, mem, _) ->
69 Printf.printf "Memory:%s\nCall state: %s\n\n%!"
72 | ReturnState (_, vs, mem, _) ->
73 Printf.printf "Memory:%s\nReturn state: %s\n\n%!"
78 let find_function mem f =
79 let addr = Mem.find_global mem f in
80 Mem.find_fun_def mem addr
82 let get_local_value (lenv : local_env) (r : Register.t) : Val.t =
83 if Register.Map.mem r lenv then Register.Map.find r lenv
84 else error ("Unknown local register \"" ^ (Register.print r) ^ "\".")
85 let get_arg_values lenv args = List.map (get_local_value lenv) args
87 let get_local_addr lenv f1 f2 =
88 List.map (get_local_value lenv) [f1 ; f2]
92 let f lenv r v = Register.Map.add r v lenv in
93 List.fold_left2 f lenv rs vs
96 (* Assign a value to some destinations registers. *)
98 let assign_state sfrs graph lbl sp lenv carry mem trace destrs vs =
99 let lenv = adds destrs vs lenv in
100 State (sfrs, graph, lbl, sp, lenv, carry, mem, trace)
102 (* Branch on a value. *)
104 let branch_state sfrs graph lbl_true lbl_false sp lenv carry mem trace v =
106 if Val.is_true v then lbl_true
108 if Val.is_false v then lbl_false
109 else error "Undefined conditional value." in
110 State (sfrs, graph, next_lbl, sp, lenv, carry, mem, trace)
113 (* Interpret statements. *)
115 let interpret_statement
116 (sfrs : stack_frame list)
122 (stmt : RTL.statement)
123 (trace : CostLabel.t list) :
124 state = match stmt with
127 State (sfrs, graph, lbl, sp, lenv, carry, mem, trace)
129 | RTL.St_cost (cost_lbl, lbl) ->
130 State (sfrs, graph, lbl, sp, lenv, carry, mem, cost_lbl :: trace)
132 | RTL.St_addr (r1, r2, x, lbl) ->
133 assign_state sfrs graph lbl sp lenv carry mem trace [r1 ; r2]
134 (Mem.find_global mem x)
136 | RTL.St_stackaddr (r1, r2, lbl) ->
137 assign_state sfrs graph lbl sp lenv carry mem trace [r1 ; r2] sp
139 | RTL.St_int (r, i, lbl) ->
140 assign_state sfrs graph lbl sp lenv carry mem trace [r] [Val.of_int i]
142 | RTL.St_move (destr, srcr, lbl) ->
143 assign_state sfrs graph lbl sp lenv carry mem trace [destr]
144 [get_local_value lenv srcr]
146 | RTL.St_opaccs (opaccs, destr1, destr2, srcr1, srcr2, lbl) ->
149 (get_local_value lenv srcr1)
150 (get_local_value lenv srcr2) in
151 assign_state sfrs graph lbl sp lenv carry mem trace
152 [destr1 ; destr2] [v1 ; v2]
154 | RTL.St_op1 (op1, destr, srcr, lbl) ->
155 let v = Eval.op1 op1 (get_local_value lenv srcr) in
156 assign_state sfrs graph lbl sp lenv carry mem trace [destr] [v]
158 | RTL.St_op2 (op2, destr, srcr1, srcr2, lbl) ->
161 (get_local_value lenv srcr1)
162 (get_local_value lenv srcr2) in
163 assign_state sfrs graph lbl sp lenv carry mem trace [destr] [v]
165 | RTL.St_clear_carry lbl ->
166 State (sfrs, graph, lbl, sp, lenv, Val.zero, mem, trace)
168 | RTL.St_set_carry lbl ->
169 State (sfrs, graph, lbl, sp, lenv, Val.of_int 1, mem, trace)
171 | RTL.St_load (destr, addr1, addr2, lbl) ->
172 let addr = get_local_addr lenv addr1 addr2 in
173 let v = Mem.load mem chunk addr in
174 assign_state sfrs graph lbl sp lenv carry mem trace [destr] [v]
176 | RTL.St_store (addr1, addr2, srcr, lbl) ->
177 let addr = get_local_addr lenv addr1 addr2 in
178 let mem = Mem.store mem chunk addr (get_local_value lenv srcr) in
179 State (sfrs, graph, lbl, sp, lenv, carry, mem, trace)
181 | RTL.St_call_id (f, args, ret_regs, lbl) ->
182 let f_def = find_function mem f in
183 let args = get_arg_values lenv args in
185 { ret_regs = ret_regs ; graph = graph ; pc = lbl ;
186 sp = sp ; lenv = lenv ; carry = carry }
188 CallState (sf :: sfrs, f_def, args, mem, trace)
190 | RTL.St_call_ptr (f1, f2, args, ret_regs, lbl) ->
191 let addr = get_local_addr lenv f1 f2 in
192 let f_def = Mem.find_fun_def mem addr in
193 let args = get_arg_values lenv args in
194 let sf = { ret_regs = ret_regs ; graph = graph ; pc = lbl ;
195 sp = sp ; lenv = lenv ; carry = carry } in
196 CallState (sf :: sfrs, f_def, args, mem, trace)
198 | RTL.St_tailcall_id (f, args) ->
199 let f_def = find_function mem f in
200 let args = get_arg_values lenv args in
201 let mem = Mem.free mem sp in
202 CallState (sfrs, f_def, args, mem, trace)
204 | RTL.St_tailcall_ptr (f1, f2, args) ->
205 let addr = get_local_addr lenv f1 f2 in
206 let f_def = Mem.find_fun_def mem addr in
207 let args = get_arg_values lenv args in
208 let mem = Mem.free mem sp in
209 CallState (sfrs, f_def, args, mem, trace)
211 | RTL.St_cond (srcr, lbl_true, lbl_false) ->
212 let v = get_local_value lenv srcr in
213 branch_state sfrs graph lbl_true lbl_false sp lenv carry mem trace v
215 | RTL.St_return rl ->
216 let vl = List.map (get_local_value lenv) rl in
217 let mem = Mem.free mem sp in
218 ReturnState (sfrs, vl, mem, trace)
221 module InterpretExternal = Primitive.Interpret (Mem)
223 let interpret_external mem f args = match InterpretExternal.t mem f args with
224 | (mem', InterpretExternal.V vs) -> (mem', vs)
225 | (mem', InterpretExternal.A addr) -> (mem', addr)
228 (locals : Register.Set.t)
229 (params : Register.t list)
230 (args : Val.t list) :
232 let f r lenv = Register.Map.add r Val.undef lenv in
233 let lenv = Register.Set.fold f locals Register.Map.empty in
234 let f lenv r v = Register.Map.add r v lenv in
235 List.fold_left2 f lenv params args
238 (sfrs : stack_frame list)
239 (f_def : RTL.function_def)
242 (trace : CostLabel.t list) :
246 let (mem', sp) = Mem.alloc mem def.RTL.f_stacksize in
247 State (sfrs, def.RTL.f_graph, def.RTL.f_entry, sp,
248 init_locals def.RTL.f_locals def.RTL.f_params args,
249 Val.undef, mem', trace)
251 let (mem', vs) = interpret_external mem def.AST.ef_tag args in
252 ReturnState (sfrs, vs, mem', trace)
254 let state_after_return
256 (sfrs : stack_frame list)
257 (ret_vals : Val.t list)
259 (trace : CostLabel.t list) :
261 let f i lenv r = Register.Map.add r (List.nth ret_vals i) lenv in
262 let lenv = MiscPottier.foldi f sf.lenv sf.ret_regs in
263 State (sfrs, sf.graph, sf.pc, sf.sp, lenv, sf.carry, mem, trace)
266 let small_step (st : state) : state = match st with
267 | State (sfrs, graph, pc, sp, lenv, carry, mem, trace) ->
268 let stmt = Label.Map.find pc graph in
269 interpret_statement sfrs graph sp lenv carry mem stmt trace
270 | CallState (sfrs, f_def, args, mem, trace) ->
271 state_after_call sfrs f_def args mem trace
272 | ReturnState ([], ret_vals, mem, trace) ->
273 assert false (* End of execution; handled in iter_small_step. *)
274 | ReturnState (sf :: sfrs, ret_vals, mem, trace) ->
275 state_after_return sf sfrs ret_vals mem trace
278 let compute_result vs =
279 let f res v = res && (Val.is_int v) in
280 let is_int vs = (List.length vs > 0) && (List.fold_left f true vs) in
283 List.map (fun v -> IntValue.Int32.cast (Val.to_int_repr v)) vs in
284 IntValue.Int32.merge chunks
285 else IntValue.Int32.zero
287 let rec iter_small_step debug st =
288 let print_and_return_result (res, cost_labels) =
289 if debug then Printf.printf "Result = %s\n%!"
290 (IntValue.Int32.to_string res) ;
291 (res, cost_labels) in
292 if debug then print_state st ;
293 match small_step st with
294 | ReturnState ([], vs, mem, trace) ->
295 print_and_return_result (compute_result vs, List.rev trace)
296 | st' -> iter_small_step debug st'
299 let add_global_vars =
301 (fun mem (id, size) -> Mem.add_var mem id (AST.SQ (AST.QInt size)) None)
304 List.fold_left (fun mem (f_id, f_def) -> Mem.add_fun_def mem f_id f_def)
307 (* The memory is initialized by loading the code into it, and by reserving space
308 for the global variables. *)
310 let init_mem (p : RTL.program) : memory =
311 add_global_vars (add_fun_defs Mem.empty p.RTL.functs) p.RTL.vars
314 (* Interpret the program only if it has a main. *)
316 let interpret debug p =
317 Printf.printf "*** RTL interpret ***\n%!" ;
318 match p.RTL.main with
319 | None -> (IntValue.Int32.zero, [])
321 let mem = init_mem p in
322 let main_def = find_function mem main in
323 let st = CallState ([], main_def, [], mem, []) in
324 iter_small_step debug st