Skip to content

Commit 80c0dcc

Browse files
committed
Stack alloc: option to print in JSON format
The command line option is -json-stack-alloc filename
1 parent ef263df commit 80c0dcc

File tree

5 files changed

+138
-4
lines changed

5 files changed

+138
-4
lines changed

CHANGELOG.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,11 @@
5151
`SMULTT`, `SMLABB`, `SMLABT`, `SMLATB`, `SMLATT`, `SMULWB`, and `SMULWT`
5252
([PR #644](https://github.com/jasmin-lang/jasmin/pull/644)).
5353

54+
- The results of the stack allocation oracle can now be printed in JSON.
55+
The command line option is `-json-stack-alloc filename`.
56+
This adds package yojson as a dependency of the compiler.
57+
([PR #656](https://github.com/jasmin-lang/jasmin/pull/656)).
58+
5459
## Bug fixes
5560

5661
- Type-checking rejects wrongly casted primitive operators
@@ -65,7 +70,7 @@
6570
([PR #541](https://github.com/jasmin-lang/jasmin/pull/541);
6671
fixes [#540](https://github.com/jasmin-lang/jasmin/issues/540)).
6772

68-
- More precise detection of speculative safe loads in the SCT checker
73+
- More precise detection of speculative safe loads in the SCT checker
6974
([PR #556](https://github.com/jasmin-lang/jasmin/pull/556)).
7075

7176
- Fix printing to EasyCrypt of ARMv7 instruction `bic`

compiler/src/CLI_errors.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,4 +57,4 @@ let check_options () =
5757
if !latexfile <> ""
5858
then warning Deprecated Location.i_dummy
5959
"the [-latex] option has been deprecated since March 2023; use [jazz2tex] instead";
60-
List.iter chk_out_file [ outfile; latexfile; ecfile ]
60+
List.iter chk_out_file [ outfile; latexfile; ecfile; json_stack_alloc_file ]

compiler/src/dune

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
(public_name jasmin.jasmin)
1313
(flags -rectypes)
1414
(modules :standard \ arch main_compiler x86_safety uint63_63 uint63_31)
15-
(libraries batteries.unthreaded zarith menhirLib))
15+
(libraries batteries.unthreaded zarith menhirLib yojson))
1616

1717
(library
1818
(name jasminc)

compiler/src/glob_options.ml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ let lea = ref false
3232
let set0 = ref false
3333
let model = ref Normal
3434
let print_stack_alloc = ref false
35+
let json_stack_alloc_file = ref ""
3536
let introduce_array_copy = ref true
3637
let print_dependencies = ref false
3738
let lazy_regalloc = ref false
@@ -223,6 +224,7 @@ let options = [
223224
"-color", Arg.Symbol (["auto"; "always"; "never"], set_color), ": print messages with color";
224225
"-help-intrinsics", Arg.Set help_intrinsics, "List the set of intrinsic operators";
225226
"-print-stack-alloc", Arg.Set print_stack_alloc, ": print the results of the stack allocation OCaml oracle";
227+
"-json-stack-alloc", Arg.Set_string json_stack_alloc_file, "[filename]: print the results of the stack allocation OCaml oracle as JSON in file [filename]";
226228
"-lazy-regalloc", Arg.Set lazy_regalloc, "\tAllocate variables to registers in program order";
227229
"-pall" , Arg.Unit set_all_print, "print program after each compilation steps";
228230
"-print-dependencies", Arg.Set print_dependencies, ": print dependencies and exit";

compiler/src/stackAlloc.ml

Lines changed: 128 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ let pp_return fmt n =
5757

5858
let pp_sao fmt sao =
5959
let open Stack_alloc in
60-
Format.fprintf fmt "alignment = %s; size = %a; ioff = %a; extra size = %a; max size = %a@;max call depth = %a@;params =@;<2 2>@[<v>%a@]@;return = @[<hov>%a@]@;slots =@;<2 2>@[<v>%a@]@;alloc= @;<2 2>@[<v>%a@]@;saved register = @[<hov>%a@]@;saved stack = %a@;return address = %a"
60+
Format.fprintf fmt "alignment = %s; size = %a; ioff = %a; extra size = %a; max size = %a@;max call depth = %a@;params =@;<2 2>@[<v>%a@]@;return = @[<hov>%a@]@;slots =@;<2 2>@[<v>%a@]@;alloc = @;<2 2>@[<v>%a@]@;saved register = @[<hov>%a@]@;saved stack = %a@;return address = %a"
6161
(string_of_ws sao.sao_align)
6262
Z.pp_print (Conv.z_of_cz sao.sao_size)
6363
Z.pp_print (Conv.z_of_cz sao.sao_ioff)
@@ -88,6 +88,127 @@ let pp_oracle up fmt saos =
8888
(pp_list "@;" pp_slot) ao_global_alloc
8989
(pp_list "@;" pp_stack_alloc) fs
9090

91+
let json_of_param_info pi =
92+
let open Stack_alloc in
93+
match pi with
94+
| None -> `Null
95+
| Some pi ->
96+
`Assoc [
97+
"writable", `Bool pi.pp_writable;
98+
"var", `String (Format.asprintf "%a" pp_var_ty (Conv.var_of_cvar pi.pp_ptr));
99+
"alignment", `String (string_of_ws pi.pp_align)
100+
]
101+
102+
let json_of_return n =
103+
match n with
104+
| None -> `Null
105+
| Some n -> `Int (Conv.int_of_nat n)
106+
107+
let json_of_slot ((x, ws), ofs) =
108+
`Assoc [
109+
"offset", `Int (Z.to_int (Conv.z_of_cz ofs));
110+
"var", `String (Format.asprintf "%a" pp_var_ty (Conv.var_of_cvar x));
111+
"alignment", `String (string_of_ws ws);
112+
]
113+
114+
let json_of_alloc (x, pki) =
115+
let json_of_pki pki =
116+
let open Stack_alloc in
117+
match pki with
118+
| PIdirect (v, z, sc) ->
119+
"direct",
120+
`Assoc [
121+
"scope", `String (if sc = Sglob then "global" else "stack");
122+
"var", `String (Format.asprintf "%a" pp_var (Conv.var_of_cvar v));
123+
"zone", `String (Format.asprintf "%a" pp_zone z);
124+
]
125+
| PIregptr v ->
126+
"reg ptr",
127+
`Assoc [
128+
"var", `String (Format.asprintf "%a" pp_var (Conv.var_of_cvar v))
129+
]
130+
| PIstkptr (v, z, x) ->
131+
"stack ptr",
132+
`Assoc [
133+
"var", `String (Format.asprintf "%a" pp_var_ty (Conv.var_of_cvar v));
134+
"zone", `String (Format.asprintf "%a" pp_zone z);
135+
"pseudo-reg", `String (Format.asprintf "%a" pp_var_ty (Conv.var_of_cvar x))
136+
]
137+
in
138+
`Assoc [
139+
"var", `String (Format.asprintf "%a" pp_var (Conv.var_of_cvar x));
140+
json_of_pki pki
141+
]
142+
143+
let json_of_to_save (x, ofs) =
144+
`Assoc [
145+
"var", `String (Format.asprintf "%a" pp_var (Conv.var_of_cvar x));
146+
"offset", `Int (Z.to_int (Conv.z_of_cz ofs));
147+
]
148+
149+
let json_of_saved_stack ss =
150+
let open Expr in
151+
match ss with
152+
| SavedStackNone -> `Null
153+
| SavedStackReg x ->
154+
`Assoc ["reg", `String (Format.asprintf "%a" pp_var (Conv.var_of_cvar x))]
155+
| SavedStackStk z ->
156+
`Assoc ["stack", `Int (Z.to_int (Conv.z_of_cz z))]
157+
158+
let json_of_return_address ra =
159+
let open Expr in
160+
match ra with
161+
| RAnone -> `Null
162+
| RAreg x ->
163+
`Assoc ["reg", `String (Format.asprintf "%a" pp_var (Conv.var_of_cvar x))]
164+
| RAstack (x, z) ->
165+
`Assoc ["stack",
166+
`Assoc [
167+
"var",
168+
begin match x with
169+
| None -> `Null
170+
| Some x -> `String (Format.asprintf "%a" pp_var (Conv.var_of_cvar x))
171+
end;
172+
"offset", `Int (Z.to_int (Conv.z_of_cz z))
173+
]
174+
]
175+
176+
let json_of_sao fn sao : Yojson.Basic.t =
177+
let open Stack_alloc in
178+
`Assoc [
179+
"function name", `String fn.fn_name;
180+
"alignment", `String (string_of_ws sao.sao_align);
181+
"size", `Int (Z.to_int (Conv.z_of_cz sao.sao_size));
182+
"ioff", `Int (Z.to_int (Conv.z_of_cz sao.sao_ioff));
183+
"extra size", `Int (Z.to_int (Conv.z_of_cz sao.sao_extra_size));
184+
"max size", `Int (Z.to_int (Conv.z_of_cz sao.sao_max_size));
185+
"max call depth", `Int (Z.to_int (Conv.z_of_cz sao.sao_max_call_depth));
186+
"params", `List (List.map json_of_param_info sao.sao_params);
187+
"return", `List (List.map json_of_return sao.sao_return);
188+
"slots", `List (List.map json_of_slot sao.sao_slots);
189+
"alloc", `List (List.map json_of_alloc sao.sao_alloc);
190+
"saved register", `List (List.map json_of_to_save sao.sao_to_save);
191+
"saved stack", json_of_saved_stack sao.sao_rsp;
192+
"return address", json_of_return_address sao.sao_return_address;
193+
]
194+
195+
let json_of_oracle up saos =
196+
let Compiler.{ ao_globals; ao_global_alloc; ao_stack_alloc } = saos in
197+
let json_of_globals global =
198+
`Int (Z.to_int (Conv.z_of_word U8 global))
199+
in
200+
let json_of_stack_alloc f =
201+
let fn = f.f_name in
202+
json_of_sao fn (ao_stack_alloc fn)
203+
in
204+
let _, fs = Conv.prog_of_cuprog up in
205+
`Assoc [
206+
("global data", `List (List.map json_of_globals ao_globals));
207+
("global slots", `List (List.map json_of_slot ao_global_alloc));
208+
("stack alloc", `List (List.map json_of_stack_alloc fs));
209+
]
210+
211+
91212
module StackAlloc (Arch: Arch_full.Arch) = struct
92213

93214
module Regalloc = Regalloc (Arch)
@@ -316,6 +437,12 @@ let memory_analysis pp_err ~debug up =
316437
Format.eprintf "(* Final results of the stack allocation oracle *)@.@.";
317438
Format.eprintf "%a@.@.@." (pp_oracle up) saos
318439
end;
440+
let outfile = !Glob_options.json_stack_alloc_file in
441+
if outfile <> "" then begin
442+
BatFile.with_file_out outfile (fun out ->
443+
let fmt = BatFormat.formatter_of_out_channel out in
444+
Format.fprintf fmt "%a@." Yojson.Basic.pretty_print (json_of_oracle up saos));
445+
end;
319446

320447
saos
321448

0 commit comments

Comments
 (0)