summaryrefslogtreecommitdiff
path: root/lisc/tools
diff options
context:
space:
mode:
Diffstat (limited to 'lisc/tools')
-rw-r--r--lisc/tools/abi.ml247
1 files changed, 145 insertions, 102 deletions
diff --git a/lisc/tools/abi.ml b/lisc/tools/abi.ml
index a5ad250..814bc79 100644
--- a/lisc/tools/abi.ml
+++ b/lisc/tools/abi.ml
@@ -19,7 +19,8 @@ type _ aty =
type anyb = AB: _ bty -> anyb (* kinda boring... *)
type anys = AS: _ sty -> anys
type anya = AA: _ aty -> anya
-type test = T: 'a aty * 'a -> test
+type testb = TB: 'a bty * 'a -> testb
+type testa = TA: 'a aty * 'a -> testa
let btysize: type a. a bty -> int = function
@@ -36,6 +37,14 @@ let styempty: type a. a sty -> bool = function
| Field _ -> false
| Empty -> true
+let rec stysize: type a. a sty -> int = function
+ | Field (b, s) -> (btyalign b) + (stysize s)
+ | Empty -> 0
+
+let rec styalign: type a. a sty -> int = function
+ | Field (b, s) -> max (btyalign b) (styalign s)
+ | Empty -> 1
+
(* Generate types and test vectors. *)
module Gen = struct
@@ -111,7 +120,7 @@ module Gen = struct
let test () =
let AA ty = a () in
let t = testv ty in
- T (ty, t)
+ TA (ty, t)
let tests () =
let rec f n =
@@ -124,8 +133,8 @@ end
module type OUT = sig
val extension: string
val comment: out_channel -> string -> unit
- val caller: out_channel -> test -> test list -> unit
- val callee: out_channel -> test -> test list -> unit
+ val caller: out_channel -> testa -> testa list -> unit
+ val callee: out_channel -> testa -> testa list -> unit
end
(* Code generation for C *)
@@ -170,7 +179,7 @@ module OutC = struct
| Float, f -> fprintf oc "%ff" f
| Double, f -> fprintf oc "%f" f
- let init oc name (T (ty, t)) =
+ let init oc name (TA (ty, t)) =
let inits s =
let rec f: type a. a sty * a -> unit = function
| Field (b, s), (tb, ts) ->
@@ -208,7 +217,7 @@ module OutC = struct
]
let typedef oc name = function
- | T (Struct ts, _) ->
+ | TA (Struct ts, _) ->
ctypelong oc name (Struct ts);
fprintf oc ";\n";
| _ -> ()
@@ -220,8 +229,8 @@ module OutC = struct
base oc t;
fprintf oc ")\n\t\tfail(%S);\n" name; in
function
- | T (Base b, tb) -> chkbase name (b, tb)
- | T (Struct s, ts) ->
+ | TA (Base b, tb) -> chkbase name (b, tb)
+ | TA (Struct s, ts) ->
let rec f: type a. int -> a sty * a -> unit =
fun i -> function
| Field (b, s), (tb, ts) ->
@@ -232,11 +241,11 @@ module OutC = struct
let argname i = "arg" ^ string_of_int (i+1)
- let proto oc (T (tret, _)) args =
+ let proto oc (TA (tret, _)) args =
ctype oc "ret" tret;
fprintf oc " f(";
let narg = List.length args in
- List.iteri (fun i (T (targ, _)) ->
+ List.iteri (fun i (TA (targ, _)) ->
ctype oc (argname i) targ;
fprintf oc " %s" (argname i);
if i <> narg-1 then
@@ -259,7 +268,7 @@ module OutC = struct
init oc (argname i) arg;
) args;
fprintf oc "\t";
- let T (tret, _) = ret in
+ let TA (tret, _) = ret in
ctype oc "ret" tret;
fprintf oc " ret;\n\n";
fprintf oc "\tret = f(";
@@ -296,96 +305,21 @@ end
module OutIL = struct
open Printf
- let ctypelong oc name =
- let cb: type a. a bty -> unit = function
- | Char -> fprintf oc "char"
- | Short -> fprintf oc "short"
- | Int -> fprintf oc "int"
- | Long -> fprintf oc "long"
- | Float -> fprintf oc "float"
- | Double -> fprintf oc "double" in
- let rec cs: type a. int -> a sty -> unit =
- fun i -> function
- | Field (b, s) ->
- cb b;
- fprintf oc " f%d; " i;
- cs (i+1) s;
- | Empty -> () in
- function
- | Base b ->
- cb b;
- | Struct s ->
- fprintf oc "struct %s { " name;
- cs 1 s;
- fprintf oc "}";
- ()
-
- let ctype: type a. out_channel -> string -> a aty -> unit =
- fun oc name -> function
- | Struct _ -> fprintf oc "struct %s" name
- | t -> ctypelong oc "" t
-
- let init oc name (T (ty, t)) =
- let inits s =
- let rec f: type a. a sty * a -> unit = function
- | Field (b, s), (tb, ts) ->
- base oc (b, tb);
- fprintf oc ", ";
- f (s, ts)
- | Empty, () -> () in
- fprintf oc "{ ";
- f s;
- fprintf oc "}"; in
- ctype oc name ty;
- fprintf oc " %s = " name;
- begin match (ty, t) with
- | Base b, tb -> base oc (b, tb)
- | Struct s, ts -> inits (s, ts)
- end;
- fprintf oc ";\n";
- ()
-
-
let comment oc s =
fprintf oc "# %s\n" s
- let check oc name =
- let chkbase: type a. string -> a bty * a -> unit =
- fun name t ->
- fprintf oc "\tif (%s != " name;
- base oc t;
- fprintf oc ")\n\t\tfail(%S);\n" name; in
- function
- | T (Base b, tb) -> chkbase name (b, tb)
- | T (Struct s, ts) ->
- let rec f: type a. int -> a sty * a -> unit =
- fun i -> function
- | Field (b, s), (tb, ts) ->
- chkbase (Printf.sprintf "%s.f%d" name i) (b, tb);
- f (i+1) (s, ts);
- | Empty, () -> () in
- f 1 (s, ts)
-
- let tmp =
+ let tmp, lbl =
let next = ref 0 in
- fun () ->
- incr next;
- "%t" ^ (string_of_int !next)
-
- (* NEW NEW NEW *)
-
- let base: type a. out_channel -> a bty * a -> unit =
- fun oc -> function
- | Char, i -> fprintf oc "%d" i
- | Short, i -> fprintf oc "%d" i
- | Int, i -> fprintf oc "%d" i
- | Long, i -> fprintf oc "%d" i
- | Float, f -> fprintf oc "s_%f" f
- | Double, f -> fprintf oc "d_%f" f
-
- let extension = ".ssa"
+ (fun () -> incr next; "%t" ^ (string_of_int !next)),
+ (fun () -> incr next; "@l" ^ (string_of_int !next))
- let argname i = "arg" ^ string_of_int (i+1)
+ let bvalue: type a. a bty * a -> string = function
+ | Char, i -> sprintf "%d" i
+ | Short, i -> sprintf "%d" i
+ | Int, i -> sprintf "%d" i
+ | Long, i -> sprintf "%d" i
+ | Float, f -> sprintf "s_%f" f
+ | Double, f -> sprintf "d_%f" f
let btype: type a. a bty -> string = function
| Char -> "w"
@@ -395,9 +329,71 @@ module OutIL = struct
| Float -> "s"
| Double -> "d"
+ let extension = ".ssa"
+
+ let argname i = "arg" ^ string_of_int (i+1)
+
+ let siter oc base s g =
+ let rec f: type a. int -> int -> a sty * a -> unit =
+ fun id off -> function
+ | Field (b, s), (tb, ts) ->
+ let al = btyalign b in
+ let off =
+ let x = off mod al in
+ if x <> 0 then off + al - x else off in
+ let addr = tmp () in
+ fprintf oc "\t%s =l add %d, %s\n" addr off base;
+ g id addr (TB (b, tb));
+ f (id + 1) (off + btysize b) (s, ts);
+ | Empty, () -> () in
+ f 0 0 s
+
+ let init oc = function
+ | TA (Base b, tb) -> bvalue (b, tb)
+ | TA (Struct s, ts) ->
+ let base = tmp () in
+ fprintf oc "\t%s =l alloc%d %d\n"
+ base (styalign s) (stysize s);
+ siter oc base (s, ts)
+ begin fun _ addr (TB (b, tb)) ->
+ fprintf oc "\tstore%s %s, %s\n"
+ (btype b) (bvalue (b, tb)) addr;
+ end;
+ base
+
+ let check oc id name =
+ let bcheck = fun id name (b, tb) ->
+ let tcmp = tmp () in
+ let nxtl = lbl () in
+ fprintf oc "\t%s =w ceq%s %s, %s\n"
+ tcmp (btype b) name (bvalue (b, tb));
+ fprintf oc "\tstorew %d, %%failcode\n" id;
+ fprintf oc "\tjnz %s, %s, @fail\n" tcmp nxtl;
+ fprintf oc "%s\n" nxtl; in
+ function
+ | TA (Base Char, i) ->
+ let tval = tmp () in
+ fprintf oc "\t%s =w extsb %s\n" tval name;
+ bcheck id tval (Int, i)
+ | TA (Base Short, i) ->
+ let tval = tmp () in
+ fprintf oc "\t%s =w extsh %s\n" tval name;
+ bcheck id tval (Int, i)
+ | TA (Base b, tb) ->
+ bcheck id name (b, tb)
+ | TA (Struct s, ts) ->
+ siter oc name (s, ts)
+ begin fun id' addr (TB (b, tb)) ->
+ let tval = tmp () in
+ fprintf oc "\t%s =%s load %s\n"
+ tval (btype b) addr;
+ bcheck (100*id + id'+1) tval (b, tb);
+ end;
+ ()
+
let ttype name = function
- | T (Base b, _) -> btype b
- | T (Struct _, _) -> ":" ^ name
+ | TA (Base b, _) -> btype b
+ | TA (Struct _, _) -> ":" ^ name
let typedef oc name =
let rec f: type a. a sty -> unit = function
@@ -408,12 +404,51 @@ module OutIL = struct
f s;
| Empty -> () in
function
- | T (Struct ts, _) ->
+ | TA (Struct ts, _) ->
fprintf oc "type :%s = { " name;
f ts;
fprintf oc " }\n";
| _ -> ()
+ let postlude oc = List.iter (fprintf oc "%s\n")
+ [ "@fail"
+ ; "# failure code"
+ ; "\t%fcode =w loadw %failcode"
+ ; "\t%f0 =w call $printf(l $failstr, w %fcode)"
+ ; "\t%f1 =w call $abort()"
+ ; "\tret 0"
+ ; "}"
+ ; ""
+ ; "data $failstr = { b \"fail on check %d\\n\", b 0 }"
+ ]
+
+ let caller oc ret args =
+ let narg = List.length args in
+ List.iteri (fun i arg ->
+ typedef oc (argname i) arg;
+ ) args;
+ typedef oc "ret" ret;
+ fprintf oc "\nfunction w $main() {\n";
+ fprintf oc "@start\n";
+ fprintf oc "\t%%failcode =l alloc4 4\n";
+ let targs = List.mapi (fun i arg ->
+ comment oc ("define argument " ^ (string_of_int (i+1)));
+ (ttype (argname i) arg, init oc arg)
+ ) args in
+ comment oc "call test function";
+ fprintf oc "\t%%ret =%s call $f(" (ttype "ret" ret);
+ List.iteri (fun i (ty, tmp) ->
+ fprintf oc "%s %s" ty tmp;
+ if i <> narg-1 then
+ fprintf oc ", ";
+ ) targs;
+ fprintf oc ")\n";
+ comment oc "check the return value";
+ check oc 0 "%ret" ret;
+ fprintf oc "\tret 0\n";
+ postlude oc;
+ ()
+
let callee oc ret args =
let narg = List.length args in
List.iteri (fun i arg ->
@@ -428,8 +463,16 @@ module OutIL = struct
fprintf oc ", ";
) args;
fprintf oc ") {\n";
-
- fprintf oc "}\n";
+ fprintf oc "@start\n";
+ fprintf oc "\t%%failcode =l alloc4 4\n";
+ List.iteri (fun i arg ->
+ comment oc ("checking argument " ^ (string_of_int (i+1)));
+ check oc (i+1) ("%" ^ argname i) arg;
+ ) args;
+ comment oc "define the return value";
+ let rettmp = init oc ret in
+ fprintf oc "\tret %s\n" rettmp;
+ postlude oc;
()
end
@@ -441,6 +484,6 @@ let _ =
let targs = Gen.tests () in
let oc = stdout in
O.comment oc (Printf.sprintf "seed %d" seed);
- (* O.caller oc tret targs; *)
+ O.caller oc tret targs;
O.callee oc tret targs;
()