Skip to content

Commit 12affe1

Browse files
authored
Merge pull request #18 from AdUhTkJm/main
Basic match for integers; bugfix
2 parents ed167bd + 62caa6d commit 12affe1

11 files changed

+270
-160
lines changed

src/basic_vec.ml

+6
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,12 @@ let iter f d =
7373
f arr.!(i)
7474
done
7575

76+
let rev_iter f d =
77+
let arr = d.arr in
78+
for i = d.len - 1 downto 0 do
79+
f arr.!(i)
80+
done
81+
7682
let iteri d f =
7783
let arr = d.arr in
7884
for i = 0 to d.len - 1 do

src/riscv_generate.ml

+152-46
Original file line numberDiff line numberDiff line change
@@ -449,7 +449,8 @@ let deal_with_prim tac rd (prim: Primitive.prim) args =
449449
(* Load from the offset plus 4 for the tag *)
450450
Vec.push tac (Load { rd; rs = arg; offset = offset + 4; byte = size })
451451

452-
| Pignore -> ()
452+
| Pignore ->
453+
Vec.push tac (Assign { rd; rs = unit })
453454

454455
(* Calculates whether two references are equal; gets a boolean value *)
455456
| Prefeq ->
@@ -710,9 +711,9 @@ let rec do_convert tac (expr: Mcore.expr) =
710711

711712
(* If this is a `Join`, then we must jump to the corresponding letfn *)
712713
if kind = Join then (
713-
Vec.push tac (Jump !current_join);
714714
Vec.push tac (Assign { rd = !current_join_ret; rs = rd });
715-
unit
715+
Vec.push tac (Jump !current_join);
716+
!current_join_ret
716717
) else (
717718
Vec.append tac after;
718719
rd
@@ -1020,10 +1021,10 @@ let rec do_convert tac (expr: Mcore.expr) =
10201021

10211022
current_join := join;
10221023
current_join_ret := rd;
1024+
1025+
let ret = do_convert tac afterwards in
10231026

1024-
(* This is definitely a unit *)
1025-
let _ = do_convert tac afterwards in
1026-
1027+
Vec.push tac (Assign { rd; rs = ret });
10271028
Vec.push tac (Jump join);
10281029
Vec.push tac (Label join);
10291030

@@ -1072,68 +1073,82 @@ let rec do_convert tac (expr: Mcore.expr) =
10721073
let index = new_temp Mtype.T_int in
10731074
Vec.push tac (Load { rd = index; rs = obj; offset = 0; byte = 4 });
10741075

1076+
let tag_offsets = Hashtbl.find variants (nameof obj.ty) in
1077+
10751078
(* Generate a jump table *)
10761079
let label = new_label "jumptable_" in
1077-
let jumps = List.init (List.length cases) (fun _ -> new_label "jumptable_") in
1080+
let jumps = List.init (List.length tag_offsets) (fun _ -> new_label "jumptable_") in
10781081
let out = new_label "jumptable_out_" in
1079-
Vec.push global_inst (ExtArray { label; values = jumps; elem_size = 8 });
1082+
let default_lbl = new_label "jumptable_default_" in
10801083

10811084
(* Choose which place to jump to *)
10821085
let jtable = new_temp Mtype.T_bytes in
10831086
let ptr_sz = new_temp Mtype.T_int in
1084-
let off = new_temp Mtype.T_int in
1085-
let place = new_temp Mtype.T_bytes in
1087+
let off = new_temp Mtype.T_bytes in
1088+
let altered = new_temp Mtype.T_bytes in
10861089
let target = new_temp Mtype.T_bytes in
1090+
1091+
(* Assign all these different possibilities into rd *)
1092+
let rd = new_temp ty in
1093+
10871094
(* Load the address *)
10881095
Vec.push tac (AssignLabel { rd = jtable; imm = label });
10891096
Vec.push tac (AssignInt { rd = ptr_sz; imm = pointer_size });
10901097
Vec.push tac (Mul { rd = off; rs1 = index; rs2 = ptr_sz });
1091-
Vec.push tac (Add { rd = place; rs1 = jtable; rs2 = off });
1092-
Vec.push tac (Load { rd = target; rs = place; offset = 0; byte = pointer_size });
1093-
(* Jump to that address *)
1094-
Vec.push tac (JumpIndirect { rs = target; possibilities = jumps });
1098+
Vec.push tac (Add { rd = altered; rs1 = jtable; rs2 = off });
1099+
Vec.push tac (Load { rd = target; rs = altered; offset = 0; byte = pointer_size });
10951100

1096-
let tag_offsets = Hashtbl.find variants (nameof obj.ty) in
1097-
let returns = Vec.empty () in
10981101
let visited = Vec.empty () in
10991102
let correspondence = Array.make (List.length tag_offsets) "_uninit" in
1100-
(* For each label, generate the code for each label *)
1103+
1104+
(* For each label, generate the code of it *)
1105+
let tac_cases = Vec.empty () in
1106+
11011107
List.iter (fun ((tag: Tag.t), ident, expr) ->
11021108
let lbl = List.nth jumps tag.index in
11031109

1104-
Vec.push tac (Label lbl);
1110+
Vec.push tac_cases (Label lbl);
11051111
(match ident with
11061112
| None -> ()
11071113
| Some x ->
1108-
Vec.push tac (Assign { rd = { name = Ident.to_string x; ty = obj.ty }; rs = obj }));
1109-
let ret = do_convert tac expr in
1110-
Vec.push tac (Jump out);
1111-
Vec.push returns (ret, lbl);
1114+
Vec.push tac_cases (Assign { rd = { name = Ident.to_string x; ty = obj.ty }; rs = obj }));
1115+
let ret = do_convert tac_cases expr in
1116+
Vec.push tac_cases (Assign { rd; rs = ret });
1117+
Vec.push tac_cases (Jump out);
11121118
Vec.push visited tag.index;
11131119
correspondence.(tag.index) <- lbl
11141120
) cases;
11151121

11161122
(match default with
11171123
| None -> ()
11181124
| Some x ->
1119-
let default_lbl = new_label "jumptable_default_" in
11201125
let visited = visited |> Vec.to_list in
11211126

1122-
Vec.push tac (Label default_lbl);
1123-
let ret = do_convert tac expr in
1124-
Vec.push tac (Jump out);
1127+
Vec.push tac_cases (Label default_lbl);
1128+
let ret = do_convert tac_cases x in
1129+
Vec.push tac_cases (Assign { rd; rs = ret });
1130+
Vec.push tac_cases (Jump out);
1131+
11251132
List.iteri (fun i x ->
11261133
if not (List.mem i visited) then (
1127-
Vec.push returns (ret, default_lbl);
11281134
correspondence.(i) <- default_lbl
11291135
)
1130-
) tag_offsets);
1136+
) tag_offsets;);
11311137

1132-
(* Now assign all these different things into rd *)
1133-
let rd = new_temp ty in
1138+
Vec.push tac_cases (Label out);
1139+
1140+
(* Deduplicate all possible targets *)
1141+
let possibilities =
1142+
Array.to_list correspondence |> Stringset.of_list |> Stringset.to_seq |> List.of_seq
1143+
in
1144+
(* Jump to the correct target *)
1145+
Vec.push tac (JumpIndirect { rs = target; possibilities });
1146+
1147+
(* Emit all match cases *)
1148+
Vec.append tac tac_cases;
11341149

1135-
Vec.push tac (Label out);
1136-
Vec.push tac (Phi { rd; rs = Vec.to_list returns });
1150+
(* Record the correct label order *)
1151+
Vec.push global_inst (ExtArray { label; values = Array.to_list correspondence; elem_size = 8 });
11371152
rd
11381153

11391154
| Cexpr_letrec _ ->
@@ -1145,7 +1160,7 @@ let rec do_convert tac (expr: Mcore.expr) =
11451160
unit
11461161

11471162
| Cexpr_switch_constant { obj; cases; default; ty; _ } ->
1148-
let obj = do_convert tac obj in
1163+
let index = do_convert tac obj in
11491164

11501165
let die () =
11511166
failwith "riscv_generate.ml: bad match on constants"
@@ -1170,20 +1185,106 @@ let rec do_convert tac (expr: Mcore.expr) =
11701185
) cases
11711186
in
11721187

1173-
let mx = List.fold_left (fun mx x -> max mx x) 0 values in
1174-
let mn = List.fold_left (fun mn x -> min mx x) 0 values in
1175-
1176-
let value = new_temp Mtype.T_int in
1188+
let mx = List.fold_left (fun mx x -> max mx x) (-2147483647-1) values in
1189+
let mn = List.fold_left (fun mn x -> min mn x) 2147483647 values in
11771190

11781191
(* Sparse values, generate a hash function *)
1179-
if mx - mn >= 10 then (
1180-
failwith "TODO: large "
1181-
) else
1182-
Vec.push tac (Assign { rd = value; rs = obj });
1183-
1184-
(* Compile into jump table *)
1185-
failwith "TODO: jump table";
1186-
()
1192+
if mx - mn >= 20 then (
1193+
failwith "TODO: large"
1194+
)
1195+
1196+
(* Dense values, just get a jump table *)
1197+
else (
1198+
let table = new_label "jumptable_int_" in
1199+
let jump = new_label "do_jump_int_" in
1200+
let jumps = List.init (mx - mn + 1) (fun _ -> new_label "jumptable_int_") in
1201+
let out = new_label "jumptable_int_out_" in
1202+
let default_lbl = new_label "jumptable_default_" in
1203+
1204+
(* If the value is outside the min/max range, jump to default *)
1205+
let inrange = new_temp Mtype.T_bool in
1206+
let maximum = new_temp Mtype.T_int in
1207+
let minimum = new_temp Mtype.T_int in
1208+
let _1 = new_temp Mtype.T_bool in
1209+
let _2 = new_temp Mtype.T_bool in
1210+
1211+
(* Evaluate (x < max) && (x > min), which is the range where we can use jump table *)
1212+
Vec.push tac (AssignInt { rd = maximum; imm = mx });
1213+
Vec.push tac (AssignInt { rd = minimum; imm = mn });
1214+
Vec.push tac (Leq { rd = _1; rs1 = index; rs2 = maximum });
1215+
Vec.push tac (Geq { rd = _2; rs1 = index; rs2 = minimum });
1216+
Vec.push tac (And { rd = inrange; rs1 = _1; rs2 = _2 });
1217+
Vec.push tac (Branch { cond = inrange; ifso = jump; ifnot = default_lbl });
1218+
1219+
(* Load the address *)
1220+
Vec.push tac (Label jump);
1221+
1222+
let jtable = new_temp Mtype.T_bytes in
1223+
let ptr_sz = new_temp Mtype.T_int in
1224+
let off = new_temp Mtype.T_int in
1225+
let altered = new_temp Mtype.T_bytes in
1226+
let target = new_temp Mtype.T_bytes in
1227+
1228+
Vec.push tac (AssignLabel { rd = jtable; imm = table });
1229+
Vec.push tac (AssignInt { rd = ptr_sz; imm = pointer_size });
1230+
1231+
(* We must also minus the minimum, unlike switch_constr *)
1232+
let min_var = new_temp Mtype.T_int in
1233+
let ind_2 = new_temp Mtype.T_int in
1234+
1235+
Vec.push tac (AssignInt { rd = min_var; imm = mn });
1236+
Vec.push tac (Sub { rd = ind_2; rs1 = index; rs2 = min_var });
1237+
1238+
(* Now find which address to jump to *)
1239+
Vec.push tac (Mul { rd = off; rs1 = ind_2; rs2 = ptr_sz });
1240+
Vec.push tac (Add { rd = altered; rs1 = jtable; rs2 = off });
1241+
Vec.push tac (Load { rd = target; rs = altered; offset = 0; byte = pointer_size });
1242+
1243+
let visited = Vec.empty () in
1244+
let correspondence = Array.make (List.length cases) "_uninit" in
1245+
1246+
(* For each label, generate the code of it *)
1247+
let tac_cases = Vec.empty () in
1248+
1249+
List.iter2 (fun value (_, expr) ->
1250+
let lbl = List.nth jumps (value - mn) in
1251+
1252+
Vec.push tac_cases (Label lbl);
1253+
let ret = do_convert tac_cases expr in
1254+
Vec.push tac_cases (Assign { rd; rs = ret });
1255+
Vec.push tac_cases (Jump out);
1256+
Vec.push visited value;
1257+
correspondence.(value - mn) <- lbl
1258+
) values cases;
1259+
1260+
(* For each values in the (min, max) range, redirect them into default *)
1261+
let visited = visited |> Vec.to_list in
1262+
1263+
Vec.push tac_cases (Label default_lbl);
1264+
let ret = do_convert tac_cases default in
1265+
Vec.push tac_cases (Assign { rd; rs = ret });
1266+
Vec.push tac_cases (Jump out);
1267+
1268+
List.iter (fun i ->
1269+
if not (List.mem i visited) then (
1270+
correspondence.(i - mn) <- default_lbl
1271+
)
1272+
) (List.init (mx - mn) (fun i -> i + mn));
1273+
1274+
(* Store the correct order of jump table *)
1275+
Vec.push tac_cases (Label out);
1276+
Vec.push global_inst (ExtArray
1277+
{ label = table; values = Array.to_list correspondence; elem_size = 8 });
1278+
1279+
(* Deduplicate possibilities and jump there *)
1280+
let possibilities =
1281+
Array.to_list correspondence |> Stringset.of_list |> Stringset.to_seq |> List.of_seq
1282+
in
1283+
1284+
Vec.push tac (JumpIndirect { rs = target; possibilities });
1285+
Vec.append tac tac_cases;
1286+
1287+
)
11871288

11881289
| _ -> failwith "TODO: unsupported switch constant type");
11891290

@@ -1275,6 +1376,7 @@ let rec do_convert tac (expr: Mcore.expr) =
12751376
rd
12761377

12771378
| Cexpr_function _ ->
1379+
Printf.printf "unconverted: %s\n" (Mcore.sexp_of_expr expr |> S.to_string);
12781380
failwith "riscv_generate.ml: Cexpr_function should have been converted into letfn"
12791381

12801382
let generate_vtables () =
@@ -1455,6 +1557,10 @@ let analyze_closure (top: Mcore.top_item) =
14551557
iter_expr find_closures func.body;
14561558
Vec.iter process_closure worklist
14571559

1560+
| Ctop_expr { expr } ->
1561+
iter_expr find_closures expr;
1562+
Vec.iter process_closure worklist
1563+
14581564
| _ -> ()
14591565

14601566
let convert_toplevel _start (top: Mcore.top_item) =
@@ -1548,7 +1654,7 @@ let ssa_of_mcore (core: Mcore.t) =
15481654
(* Deal with main *)
15491655
let with_main = match core.main with
15501656
| Some (main_expr, _) ->
1551-
let lambda_removed = convert_lambda main_expr in
1657+
let lambda_removed = map_expr convert_lambda main_expr in
15521658

15531659
(* Find closures in main *)
15541660
let closures = Vec.empty () in

0 commit comments

Comments
 (0)