summaryrefslogtreecommitdiff
path: root/src/codegen.ml
diff options
context:
space:
mode:
Diffstat (limited to 'src/codegen.ml')
-rw-r--r--src/codegen.ml204
1 files changed, 108 insertions, 96 deletions
diff --git a/src/codegen.ml b/src/codegen.ml
index cccf83c..5042339 100644
--- a/src/codegen.ml
+++ b/src/codegen.ml
@@ -155,7 +155,7 @@ let spare_reg2 = s1
soient maintenant fait en prenant en compte la relocalisation de ces valeurs
sur la pile. *)
let saver env save_regs =
- let save_code, load_code, env2 = List.fold_left
+ List.fold_left
(fun (code, more_code, env) r ->
let new_fp_used = env.c_fp_used + 4 in
let pos = - new_fp_used in
@@ -174,8 +174,6 @@ let saver env save_regs =
c_save_regs = (List.filter (fun k -> k <> r) env.c_save_regs) }
)
(nop, nop, env) save_regs
- in
- save_code, load_code, env2
(*
renvoie le résultat dans le premier registre de free_regs
@@ -185,7 +183,7 @@ let rec gen_expr env free_regs save_regs e =
(* register management *)
let r = List.hd free_regs in (* register where to put result *)
let more = List.tl free_regs in
- (* the generator... *)
+ (* generate the code... *)
match e.te_desc with
| TEInt(k) -> li r k, Copy
| TENull -> nop, Value zero
@@ -265,36 +263,33 @@ let rec gen_expr env free_regs save_regs e =
| Ast.Plus -> t ++ cr r a, Copy
| Ast.Minus -> t ++ cr r a ++ neg r r, Copy
| Ast.Not -> t ++ cr r a ++ not_ r r, Copy
- | Ast.PreIncr ->
+ | Ast.PreIncr | Ast.PreDecr ->
+ let delta = if x = Ast.PreIncr then 1 else -1 in
begin match a with
- | Addr -> t ++ lw spare_reg areg (0, r) ++ add spare_reg spare_reg oi 1 ++ sw spare_reg areg (0, r), Addr
- | AddrByReg (k, rg) when t = nop -> t ++ lw r areg (k, rg) ++ add r r oi 1 ++ sw r areg (k, rg), Copy
- | Value v when t = nop && v <> r -> add v v oi 1 ++ move r v, Copy
+ | Addr ->
+ t ++ move spare_reg r ++ lw r areg (0, spare_reg)
+ ++ add r r oi delta ++ sw r areg (0, spare_reg), Copy
+ | AddrByReg (k, rg) when t = nop && r <> rg ->
+ lw r areg (k, rg)
+ ++ add r r oi delta ++ sw r areg (k, rg), Copy
+ | Value v when t = nop && v <> r ->
+ add v v oi delta ++ move r v, Copy
| _ -> assert false
end
- | Ast.PreDecr ->
+ | Ast.PostIncr | Ast.PostDecr ->
+ let delta = if x = Ast.PostIncr then 1 else -1 in
begin match a with
- | Addr -> t ++ lw spare_reg areg (0, r) ++ sub spare_reg spare_reg oi 1 ++ sw spare_reg areg (0, r), Addr
- | AddrByReg (k, rg) when t = nop -> lw r areg (k, rg) ++ sub r r oi 1 ++ sw r areg (k, rg), Copy
- | Value v when t = nop && v <> r -> sub v v oi 1 ++ move r v, Copy
- | _ -> assert false
- end
- | Ast.PostIncr ->
- begin match a with
- | Addr -> t ++ move spare_reg r ++ lw spare_reg2 areg(0, spare_reg) ++ move r spare_reg2 ++
- add spare_reg2 spare_reg2 oi 1 ++ sw spare_reg2 areg(0, spare_reg), Copy
- | AddrByReg (k, rg) when t = nop ->
- lw r areg (k, rg) ++ add spare_reg r oi 1 ++ sw spare_reg areg (k, rg), Copy
- | Value v when t = nop && v <> r -> move r v ++ add v v oi 1, Copy
- | _ -> assert false
- end
- | Ast.PostDecr ->
- begin match a with
- | Addr -> t ++ move spare_reg r ++ lw spare_reg2 areg(0, spare_reg) ++ move r spare_reg2 ++
- sub spare_reg2 spare_reg2 oi 1 ++ sw spare_reg2 areg(0, spare_reg), Copy
- | AddrByReg (k, rg) when t = nop ->
- lw r areg (k, rg) ++ sub spare_reg r oi 1 ++ sw spare_reg areg (k, rg), Copy
- | Value v when t = nop && v <> r -> move r v ++ sub v v oi 1, Copy
+ | Addr ->
+ t ++ move spare_reg r
+ ++ lw r areg(0, spare_reg)
+ ++ add spare_reg2 r oi delta
+ ++ sw spare_reg2 areg(0, spare_reg), Copy
+ | AddrByReg (k, rg) when t = nop && r <> rg ->
+ lw r areg (k, rg)
+ ++ add spare_reg r oi delta
+ ++ sw spare_reg areg (k, rg), Copy
+ | Value v when t = nop && v <> r ->
+ move r v ++ add v v oi delta, Copy
| _ -> assert false
end
end
@@ -304,9 +299,9 @@ let rec gen_expr env free_regs save_regs e =
let env2, tspot = env_push 4 env in
let t1, ae1 = gen_expr env2 free_regs save_regs e1 in
let t2, ae2 = gen_expr env free_regs save_regs e2 in
- let t1 = t1 ++ cr r ae1 in
- let t2 = t2 ++ cr r ae2 in
- r, spare_reg, t2 ++ sw r areg (tspot, fp) ++ t1 ++ lw spare_reg areg (tspot, fp)
+ let t1, r1 = crb r t1 ae1 in
+ let t2, r2 = crb r t2 ae2 in
+ r1, spare_reg, t2 ++ sw r2 areg (tspot, fp) ++ t1 ++ lw spare_reg areg (tspot, fp)
| b::_ ->
let t1, ae1 = gen_expr env free_regs save_regs e1 in
let t2, ae2 = gen_expr env more (r::save_regs) e2 in
@@ -334,7 +329,8 @@ let rec gen_expr env free_regs save_regs e =
let t1 = t1 ++ cr r ae1 in
let t2 = t2 ++ cr r ae2 in
let lazy_lbl = id "_lazy" in
- t1 ++ (if op = Ast.Lor then bnez r lazy_lbl else beqz r lazy_lbl) ++ t2 ++ label lazy_lbl ++ sne r r zero, Copy
+ t1 ++ (if op = Ast.Lor then bnez r lazy_lbl else beqz r lazy_lbl)
+ ++ t2 ++ label lazy_lbl ++ sne r r zero, Copy
| TEMember(e, i) ->
let c, a = gen_expr env free_regs save_regs e in
if i <> 0 then begin
@@ -352,8 +348,8 @@ let rec gen_expr env free_regs save_regs e =
let args_code, _, env_args = code_for_args env_regs_saved args [ a1; a2; a3 ] in
code_save_regs ++ args_code
++ li v0 9 ++ li a0 cls.tc_size ++ syscall ++ move a0 v0
- ++ la sp areg (-env_args.c_fp_used, fp) ++ jal constr ++ (if r <> a0 then move r a0 else nop)
- ++ code_restore_regs, Copy
+ ++ la sp areg (-env_args.c_fp_used, fp) ++ jal constr
+ ++ (if r <> a0 then move r a0 else nop) ++ code_restore_regs, Copy
and code_for_args env arg_list regs =
(* assigne registers to possibly in-register arguments *)
let args_in_regs, args_in_stack, _ = List.fold_left
@@ -392,8 +388,8 @@ and code_for_args env arg_list regs =
c ++ cla reg addr ++ sw reg areg (pos, fp)
else
let tt, r2 = crb reg c addr in
- tt ++ sw r2 areg (pos, fp)
- ) ++ (mk_code_callz e2 more_args) ++ lw reg areg (pos, fp)
+ tt ++ sw r2 areg (pos, fp))
+ ++ (mk_code_callz e2 more_args) ++ lw reg areg (pos, fp)
in
let code_reg_do_call = mk_code_callz kenv arg_reg_do_call in
let code_reg_dont_call, _ =
@@ -416,7 +412,7 @@ let rec gen_stmt env = function
comment "expr" ++ (fst (gen_expr_v0 env e)), nop, env
| TSIf(cond, s1, s2) ->
let c, a = gen_expr_v0 env cond in
- let code, reg = crb v0 c a in
+ let c, reg = crb v0 c a in
let l_else = id "_cond_else" in
let l_end = id "_cond_end" in
let c_then, d_then, _ = gen_stmt env s1 in
@@ -428,12 +424,13 @@ let rec gen_stmt env = function
++ label l_end, d_then ++ d_else, env
| TSWhile(cond, body) ->
let c, a = gen_expr_v0 env cond in
+ let c, reg = crb v0 c a in
let l_begin = id "_while_begin" in
let l_cond = id "_while_cond" in
let c_body, d_body, _ = gen_stmt env body in
comment "while" ++ b l_cond
++ label l_begin ++ c_body
- ++ label l_cond ++ c ++ cr v0 a ++ bnez v0 l_begin, d_body, env
+ ++ label l_cond ++ c ++ bnez reg l_begin, d_body, env
| TSFor(before, cond, after, body) ->
let l_begin = id "_for_begin" in
let l_cond = id "_for_cond" in
@@ -443,8 +440,10 @@ let rec gen_stmt env = function
(fun code expr -> let c, _ = gen_expr_v0 env expr in code ++ c) nop after in
let c_cond = match cond with
| None -> b l_begin
- | Some x -> let c, a = gen_expr_v0 env x in
- c ++ cr v0 a ++ bnez v0 l_begin in
+ | Some x ->
+ let c, a = gen_expr_v0 env x in
+ let c, reg = crb v0 c a in
+ c ++ bnez reg l_begin in
let c_body, d_body, _ = gen_stmt env body in
comment "for"
++ c_before ++ b l_cond
@@ -457,8 +456,8 @@ let rec gen_stmt env = function
comment "return" ++ b env.c_ret_lbl, nop, env
| TSReturn (Some e) ->
let c, a = gen_expr_v0 env e in
- comment "return" ++ c
- ++ (if env.c_ret_ref then cla v0 a else cr v0 a)
+ comment "return"
+ ++ c ++ (if env.c_ret_ref then cla v0 a else cr v0 a)
++ b env.c_ret_lbl, nop, env
| TSDeclare (ty, id) ->
let s = type_size env.c_penv ty in
@@ -503,10 +502,10 @@ let rec gen_stmt env = function
), nop,
env_add_var id (if ref then VStackByRef pos else VStack pos) env2
| TSWriteCout(sl) ->
- let save_code, restore_code, env2 = saver env (if List.mem a0 env.c_save_regs then [a0] else []) in
+ let save_code, restore_code, env2 = saver env
+ (if List.mem a0 env.c_save_regs then [a0] else []) in
let text1, data1 = List.fold_left
- (fun (text, data) s ->
- match s with
+ (fun (text, data) -> function
| TSEExpr(e) ->
let t, a = gen_expr env2 (a0::use_regs) (env2.c_save_regs) e in
text ++ t ++ cr a0 a ++ li v0 1 ++ syscall, data
@@ -518,13 +517,15 @@ let rec gen_stmt env = function
let l = id "_s" in Hashtbl.add strings s l;
l, label l ++ asciiz s
in
- text ++ la a0 alab l ++ li v0 4 ++ syscall, data ++ d) (nop, nop) sl in
- comment "cout<<..." ++ save_code ++ text1 ++ restore_code, data1, env
+ text ++ la a0 alab l ++ li v0 4 ++ syscall, data ++ d)
+ (nop, nop) sl in
+ comment "cout<<..."
+ ++ save_code ++ text1 ++ restore_code, data1, env
and gen_block env b =
let text, data, fin_env =
List.fold_left (fun (t, d, e) s ->
- let tt, dd, e = gen_stmt e s in
- t ++ tt, d ++ dd, e)
+ let tt, dd, ee = gen_stmt e s in
+ t ++ tt, d ++ dd, ee)
(nop, nop, env) b
in
text, data
@@ -535,20 +536,21 @@ let gen_decl tenv decl = match decl with
let bytes = type_size tenv ty in
nop, (label id) ++ (dword (let rec a n = if n > 0 then 0::(a (n-4)) else [] in a bytes))
| TDFunction(proto, block) ->
- let regs_for_args = match proto.tp_class with | None -> [ a0; a1; a2; a3 ] | Some k -> [ a1; a2; a3 ] in
- let env0 = match proto.tp_class with | None -> !globals_env | Some _ -> Smap.add "this" (VRegister a0) !globals_env in
+ let regs_for_args, env0 = match proto.tp_class with
+ | None -> [ a0; a1; a2; a3 ], !globals_env
+ | Some k -> [ a1; a2; a3 ], Smap.add "this" (VRegister a0) !globals_env
+ in
let need_fp = ref false in
let names, _, free_regs = List.fold_left
- (fun (env, p, regs) ((ty, r), id) ->
- let s = (if r then 4 else type_size tenv ty) in
- assert (s = 4);
- match regs with
- | reg::more_regs ->
- Smap.add id (if r then VRegisterByRef reg else VRegister reg) env, p, more_regs
- | [] -> need_fp := true;
- Smap.add id (if r then VStackByRef p else VStack p) env, p + 4, regs
- )
- (env0, 0, regs_for_args) proto.tp_args in
+ (fun (env, p, regs) ((ty, r), id) ->
+ assert (r || type_size tenv ty = 4);
+ match regs with
+ | reg::more_regs ->
+ Smap.add id (if r then VRegisterByRef reg else VRegister reg) env, p, more_regs
+ | [] -> need_fp := true;
+ Smap.add id (if r then VStackByRef p else VStack p) env, p + 4, regs
+ )
+ (env0, 0, regs_for_args) proto.tp_args in
let env = {
c_penv = tenv;
c_names = names;
@@ -561,7 +563,8 @@ let gen_decl tenv decl = match decl with
let code_for_constructor, does_calls = match proto.tp_ret_type with
| Some _ -> nop, (List.exists stmt_does_call block)
| None -> let cls_name = (match proto.tp_class with | Some k -> k | None -> assert false) in
- la sp areg (-8, fp) ++ jal (cls_name ^ "0"), true in
+ la sp areg (-8, fp) ++ jal (cls_name ^ "0"), true
+ in
let code_for_virtual = match proto.tp_virtual with
| Some (c, _) when c.h_pos <> 0 ->
la a0 areg (-c.h_pos, a0)
@@ -574,27 +577,30 @@ let gen_decl tenv decl = match decl with
in
let text, data = gen_block env2 block in
label proto.tp_unique_ident
- ++ sw fp areg (-4, sp) ++ sw ra areg (-8, sp) ++ move fp sp
- ++ code_for_virtual ++ save_code ++ code_for_constructor ++ text ++ label env.c_ret_lbl
- ++ move sp fp ++ lw fp areg (-4, sp) ++ lw ra areg (-8, sp) ++ jr ra, data
+ ++ sw fp areg (-4, sp) ++ sw ra areg (-8, sp) ++ move fp sp
+ ++ code_for_virtual ++ save_code ++ code_for_constructor ++ text
+ ++ label env.c_ret_lbl ++ move sp fp ++ lw fp areg (-4, sp) ++ lw ra areg (-8, sp)
+ ++ jr ra, data
else
let text, data = gen_block env block in
label proto.tp_unique_ident
- ++ (if !need_fp then sw fp areg (-4, sp) ++ move fp sp else nop)
- ++ code_for_virtual ++ text ++ label env.c_ret_lbl
- ++ (if !need_fp then move sp fp ++ lw fp areg (-4, sp) else nop) ++ jr ra, data
+ ++ (if !need_fp then sw fp areg (-4, sp) ++ move fp sp else nop)
+ ++ code_for_virtual ++ text
+ ++ label env.c_ret_lbl ++ (if !need_fp then move sp fp ++ lw fp areg (-4, sp) else nop)
+ ++ jr ra, data
| TDClass(c) ->
- let calls_something = ref false in
+ let constructor_calls_something = ref false in
(* Call default constructor of parent classes *)
let code_parents = List.fold_left
(fun code parent ->
let cn = parent.h_class in
let c = get_c tenv cn in
- let proto = List.find (fun p -> p.tp_ret_type = None && p.tp_args = [] && p.tp_name = cn) c.tc_methods in
- calls_something := true;
+ let proto = List.find
+ (fun p -> p.tp_ret_type = None && p.tp_args = [] && p.tp_name = cn)
+ c.tc_methods in
+ constructor_calls_something := true;
code ++ (if parent.h_pos <> 0 then la a0 areg(parent.h_pos, a0) else nop)
- ++ jal proto.tp_unique_ident ++ (if parent.h_pos <> 0 then lw a0 areg (-12, fp) else nop)
- )
+ ++ jal proto.tp_unique_ident ++ (if parent.h_pos <> 0 then lw a0 areg (-12, fp) else nop))
nop c.tc_hier.h_supers in
(* Build vtables and build constructor *)
let rec make_vtables hh =
@@ -624,27 +630,30 @@ let gen_decl tenv decl = match decl with
(* Initialize members *)
let init_code_proper = Smap.fold
(fun _ (ty, pos) code ->
- (match ty with
+ code ++ (match ty with
| TClass(s) ->
let cs = get_c tenv s in
- let proto = List.find (fun p -> p.tp_ret_type = None && p.tp_args = [] && p.tp_name = s) cs.tc_methods in
- calls_something := true;
- (if pos <> 0 then la a0 areg (pos, a0) else nop)
- ++ la sp areg (-12, fp)
- ++ jal proto.tp_unique_ident ++ (if pos <> 0 then lw a0 areg (-12, fp) else nop)
- | _ -> sw zero areg (pos, a0)
- ) ++ code) c.tc_members nop
+ let proto = List.find
+ (fun p -> p.tp_ret_type = None && p.tp_args = [] && p.tp_name = s)
+ cs.tc_methods in
+ constructor_calls_something := true;
+ (if pos <> 0 then la a0 areg (pos, a0) else nop)
+ ++ la sp areg (-12, fp)
+ ++ jal proto.tp_unique_ident
+ ++ (if pos <> 0 then lw a0 areg (-12, fp) else nop)
+ | _ -> sw zero areg (pos, a0)))
+ c.tc_members nop
in (* Put it all together *)
label (c.tc_name ^ "0")
- ++ (if !calls_something then
- sw fp areg (-4, sp) ++ move fp sp ++
- sw ra areg (-8, fp) ++ sw a0 areg (-12, fp) ++ la sp areg (-12, fp)
- else nop)
- ++ code_parents ++ vtable_init_code ++ init_code_proper
- ++ (if !calls_something then
- lw ra areg (-8, fp) ++ move sp fp ++ lw fp areg (-4, sp)
- else nop)
- ++ jr ra, vtables
+ ++ (if !constructor_calls_something then
+ sw fp areg (-4, sp) ++ move fp sp ++ sw ra areg (-8, fp)
+ ++ sw a0 areg (-12, fp) ++ la sp areg (-12, fp)
+ else nop)
+ ++ code_parents ++ vtable_init_code ++ init_code_proper
+ ++ (if !constructor_calls_something then
+ lw ra areg (-8, fp) ++ move sp fp ++ lw fp areg (-4, sp)
+ else nop)
+ ++ jr ra, vtables
let generate p =
@@ -653,10 +662,11 @@ let generate p =
let more_text, more_data = gen_decl p.prog_env decl in
text ++ more_text, data ++ more_data) (nop, nop) p.prog_decls in
let text =
- label "main" ++ jal p.prog_main ++
- li v0 10 ++ syscall ++
- label "_nothing" ++ jr ra ++
- text in
+ label "main"
+ ++ jal p.prog_main
+ ++ li v0 10 ++ syscall
+ ++ label "_nothing" ++ jr ra
+ ++ text in
{ text = text;
data = data }
with
@@ -668,3 +678,5 @@ let generate p =
"(unexpected) Match failure: "^k^" at "^(string_of_int a)^":"^(string_of_int b)))
| Stack_overflow -> raise (Very_bad_error ("(unexpected) Stack overflow"))
| _ -> raise (Very_bad_error ("(unexpected) Other error"))
+
+