Skip to content

Commit 75dce8c

Browse files
committed
[CN-Test-Gen] Sized generators
1 parent 11df0c9 commit 75dce8c

File tree

23 files changed

+857
-87
lines changed

23 files changed

+857
-87
lines changed

backend/cn/bin/main.ml

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,7 @@ let run_tests
445445
until_timeout
446446
exit_fast
447447
max_stack_depth
448+
max_generator_size
448449
=
449450
(* flags *)
450451
Cerb_debug.debug_level := debug_level;
@@ -507,7 +508,8 @@ let run_tests
507508
interactive;
508509
until_timeout;
509510
exit_fast;
510-
max_stack_depth
511+
max_stack_depth;
512+
max_generator_size
511513
}
512514
in
513515
TestGeneration.run
@@ -959,6 +961,14 @@ module Testing_flags = struct
959961
value
960962
& opt (some int) TestGeneration.default_cfg.max_stack_depth
961963
& info [ "max-stack-depth" ] ~doc)
964+
965+
966+
let test_max_generator_size =
967+
let doc = "Maximum size for generated values" in
968+
Arg.(
969+
value
970+
& opt (some int) TestGeneration.default_cfg.max_generator_size
971+
& info [ "max-generator-size" ] ~doc)
962972
end
963973

964974
let testing_cmd =
@@ -990,6 +1000,7 @@ let testing_cmd =
9901000
$ Testing_flags.test_until_timeout
9911001
$ Testing_flags.test_exit_fast
9921002
$ Testing_flags.test_max_stack_depth
1003+
$ Testing_flags.test_max_generator_size
9931004
in
9941005
let doc =
9951006
"Generates RapidCheck tests for all functions in [FILE] with CN specifications.\n\

backend/cn/lib/testGeneration/genAnalysis.ml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ module LC = LogicalConstraints
66
module RP = ResourcePredicates
77
module LAT = LogicalArgumentTypes
88
module GT = GenTerms
9+
module GD = GenDefinitions
910
module SymSet = Set.Make (Sym)
1011
module SymMap = Map.Make (Sym)
1112

@@ -209,3 +210,36 @@ let get_recursive_preds (preds : (Sym.t * RP.definition) list) : SymSet.t =
209210
|> List.map fst
210211
|> List.filter (fun fsym -> G.mem_edge closure fsym fsym)
211212
|> SymSet.of_list
213+
214+
215+
module SymGraph = Graph.Persistent.Digraph.Concrete (Sym)
216+
217+
open struct
218+
let get_calls (gd : GD.t) : SymSet.t =
219+
let rec aux (gt : GT.t) : SymSet.t =
220+
let (GT (gt_, _, _)) = gt in
221+
match gt_ with
222+
| Arbitrary | Uniform _ | Alloc _ | Return _ -> SymSet.empty
223+
| Pick wgts ->
224+
wgts |> List.map snd |> List.map aux |> List.fold_left SymSet.union SymSet.empty
225+
| Call (fsym, _) -> SymSet.singleton fsym
226+
| Asgn (_, _, gt') | Assert (_, gt') | Map (_, gt') -> aux gt'
227+
| Let (_, (_, gt1), gt2) | ITE (_, gt1, gt2) -> SymSet.union (aux gt1) (aux gt2)
228+
in
229+
aux (Option.get gd.body)
230+
231+
232+
module SymGraph = Graph.Persistent.Digraph.Concrete (Sym)
233+
module Oper = Graph.Oper.P (SymGraph)
234+
end
235+
236+
let get_call_graph (ctx : GD.context) : SymGraph.t =
237+
ctx
238+
|> List.map_snd (List.map snd)
239+
|> List.map_snd (fun gds -> match gds with [ gd ] -> gd | _ -> failwith __LOC__)
240+
|> List.map_snd get_calls
241+
|> List.fold_left
242+
(fun cg (fsym, calls) ->
243+
SymSet.fold (fun fsym' cg' -> SymGraph.add_edge cg' fsym fsym') calls cg)
244+
SymGraph.empty
245+
|> Oper.transitive_closure

backend/cn/lib/testGeneration/genCodeGen.ml

Lines changed: 82 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ let compile_lc (sigma : CF.GenTypes.genTypeCategory A.sigma) (lc : LC.t) =
4747

4848
let rec compile_term
4949
(sigma : CF.GenTypes.genTypeCategory A.sigma)
50+
(ctx : GR.context)
5051
(name : Sym.t)
5152
(tm : GR.term)
5253
: A.bindings
@@ -55,25 +56,22 @@ let rec compile_term
5556
=
5657
let loc = Locations.other __LOC__ in
5758
match tm with
58-
| Uniform { bt; sz } ->
59+
| Uniform { bt; sz = _ } ->
5960
( [],
6061
[],
6162
A.(
6263
mk_expr
6364
(AilEcall
6465
( mk_expr (AilEident (Sym.fresh_named "CN_GEN_UNIFORM")),
65-
List.map
66-
mk_expr
67-
[ AilEident (Sym.fresh_named (name_of_bt name bt));
68-
AilEconst (ConstantInteger (IConstant (Z.of_int sz, Decimal, None)))
69-
] ))) )
66+
List.map mk_expr [ AilEident (Sym.fresh_named (name_of_bt name bt)) ] )))
67+
)
7068
| Pick { bt; choice_var; choices; last_var } ->
7169
let var = Sym.fresh () in
7270
let bs, ss =
7371
List.split
7472
(List.mapi
7573
(fun i (_, gr) ->
76-
let bs, ss, e = compile_term sigma name gr in
74+
let bs, ss, e = compile_term sigma ctx name gr in
7775
( bs,
7876
A.(
7977
[ AilSexpr
@@ -131,13 +129,48 @@ let rec compile_term
131129
[ mk_expr (AilEident choice_var) ] )))
132130
],
133131
A.(mk_expr (AilEident var)) )
134-
| Alloc { bytes = it } ->
135-
let alloc_sym = Sym.fresh_named "cn_gen_alloc" in
132+
| Alloc { bytes = it; sized } ->
133+
let alloc_sym =
134+
Sym.fresh_named (if sized then "CN_GEN_ALLOC_SIZED" else "CN_GEN_ALLOC")
135+
in
136136
let b, s, e = compile_it sigma name it in
137-
(b, s, mk_expr (AilEcall (mk_expr (AilEident alloc_sym), [ e ])))
138-
| Call { fsym; iargs; oarg_bt; path_vars } ->
137+
let es =
138+
if sized then
139+
[ e; mk_expr (AilEident (Sym.fresh_named "cn_gen_rec_size")) ]
140+
else
141+
[ e ]
142+
in
143+
(b, s, mk_expr (AilEcall (mk_expr (AilEident alloc_sym), es)))
144+
| Call { fsym; iargs; oarg_bt; path_vars; sized } ->
139145
let sym = GenUtils.get_mangled_name (fsym :: List.map fst iargs) in
140-
let es = iargs |> List.map snd |> List.map (fun x -> A.(mk_expr (AilEident x))) in
146+
let es = iargs |> List.map snd |> List.map (fun x -> A.(AilEident x)) in
147+
let es =
148+
List.map
149+
mk_expr
150+
(es
151+
@ A.(
152+
match sized with
153+
| Some 1 ->
154+
[ AilEbinary
155+
( mk_expr (AilEident (Sym.fresh_named "cn_gen_rec_size")),
156+
Arithmetic Sub,
157+
mk_expr
158+
(AilEconst (ConstantInteger (IConstant (Z.one, Decimal, None)))) )
159+
]
160+
| Some n ->
161+
[ AilEbinary
162+
( mk_expr (AilEident (Sym.fresh_named "cn_gen_rec_size")),
163+
Arithmetic Div,
164+
mk_expr
165+
(AilEconst
166+
(ConstantInteger (IConstant (Z.of_int n, Decimal, None)))) )
167+
]
168+
| None
169+
when (not (GenBuiltins.is_builtin fsym))
170+
&& (ctx |> List.assoc Sym.equal fsym |> List.hd |> snd).sized ->
171+
[ AilEcall (mk_expr (AilEident (Sym.fresh_named "cn_gen_get_size")), []) ]
172+
| None -> []))
173+
in
141174
let x = Sym.fresh () in
142175
let b = Utils.create_binding x (bt_to_ctype fsym oarg_bt) in
143176
let wrap_to_string (sym : Sym.t) =
@@ -232,7 +265,7 @@ let rec compile_term
232265
@ [ mk_expr (AilEconst ConstantNull) ] )))
233266
]
234267
in
235-
let b4, s4, e4 = compile_term sigma name rest in
268+
let b4, s4, e4 = compile_term sigma ctx name rest in
236269
(b1 @ b2 @ b3 @ b4, s1 @ s2 @ s3 @ s4, e4)
237270
| Let { backtracks; x; x_bt; value; last_var; rest } ->
238271
let s1 =
@@ -250,7 +283,7 @@ let rec compile_term
250283
] )))
251284
]
252285
in
253-
let b2, s2, e2 = compile_term sigma name value in
286+
let b2, s2, e2 = compile_term sigma ctx name value in
254287
let s3 =
255288
A.(
256289
[ AilSexpr
@@ -265,7 +298,13 @@ let rec compile_term
265298
(Option.value
266299
~default:name
267300
(match value with
268-
| Call { fsym; iargs; oarg_bt = _; path_vars = _ } ->
301+
| Call
302+
{ fsym;
303+
iargs;
304+
oarg_bt = _;
305+
path_vars = _;
306+
sized = _
307+
} ->
269308
Some
270309
(GenUtils.get_mangled_name
271310
(fsym :: List.map fst iargs))
@@ -302,7 +341,7 @@ let rec compile_term
302341
@ [ mk_expr (AilEconst ConstantNull) ] )))
303342
])
304343
in
305-
let b4, s4, e4 = compile_term sigma name rest in
344+
let b4, s4, e4 = compile_term sigma ctx name rest in
306345
(b2 @ [ Utils.create_binding x (bt_to_ctype name x_bt) ] @ b4, s1 @ s2 @ s3 @ s4, e4)
307346
| Return { value } ->
308347
let b, s, e = compile_it sigma name value in
@@ -332,12 +371,12 @@ let rec compile_term
332371
@ [ mk_expr (AilEconst ConstantNull) ] )))
333372
]
334373
in
335-
let b2, s2, e2 = compile_term sigma name rest in
374+
let b2, s2, e2 = compile_term sigma ctx name rest in
336375
(b1 @ b2, s1 @ s_assert @ s2, e2)
337376
| ITE { bt; cond; t; f } ->
338377
let b_if, s_if, e_if = compile_it sigma name cond in
339-
let b_then, s_then, e_then = compile_term sigma name t in
340-
let b_else, s_else, e_else = compile_term sigma name f in
378+
let b_then, s_then, e_then = compile_term sigma ctx name t in
379+
let b_else, s_else, e_else = compile_term sigma ctx name f in
341380
let res_sym = Sym.fresh () in
342381
let res_expr = mk_expr (AilEident res_sym) in
343382
let res_binding = Utils.create_binding res_sym (bt_to_ctype name bt) in
@@ -406,7 +445,7 @@ let rec compile_term
406445
(mk_expr (AilEident (Sym.fresh_named "CN_GEN_MAP_BODY")), [ e_perm ])))
407446
])
408447
in
409-
let b_val, s_val, e_val = compile_term sigma name inner in
448+
let b_val, s_val, e_val = compile_term sigma ctx name inner in
410449
let s_end =
411450
A.(
412451
s_val
@@ -424,6 +463,7 @@ let rec compile_term
424463

425464
let compile_gen_def
426465
(sigma : CF.GenTypes.genTypeCategory A.sigma)
466+
(ctx : GR.context)
427467
((name, gr) : Sym.t * GR.definition)
428468
: A.sigma_tag_definition * (A.sigma_declaration * 'a A.sigma_function_definition)
429469
=
@@ -437,7 +477,12 @@ let compile_gen_def
437477
A.Decl_function
438478
( false,
439479
(C.no_qualifiers, ct_ret),
440-
List.map (fun (_, bt) -> (C.no_qualifiers, bt_to_ctype name bt, false)) gr.iargs,
480+
(List.map (fun (_, bt) -> (C.no_qualifiers, bt_to_ctype name bt, false)) gr.iargs
481+
@
482+
if gr.sized then
483+
[ (C.no_qualifiers, C.mk_ctype_integer Size_t, false) ]
484+
else
485+
[]),
441486
false,
442487
false,
443488
false )
@@ -446,15 +491,26 @@ let compile_gen_def
446491
let s1 =
447492
A.(
448493
AilSexpr
449-
(mk_expr (AilEcall (mk_expr (AilEident (Sym.fresh_named "CN_GEN_INIT")), []))))
494+
(mk_expr
495+
(if gr.sized then
496+
AilEcall
497+
( mk_expr (AilEident (Sym.fresh_named "CN_GEN_INIT_SIZED")),
498+
[ mk_expr (AilEident (Sym.fresh_named "cn_gen_rec_size")) ] )
499+
else
500+
AilEcall (mk_expr (AilEident (Sym.fresh_named "CN_GEN_INIT")), []))))
450501
in
451-
let b2, s2, e2 = compile_term sigma name gr.body in
502+
let b2, s2, e2 = compile_term sigma ctx name gr.body in
452503
let sigma_def : CF.GenTypes.genTypeCategory A.sigma_function_definition =
453504
( name,
454505
( loc,
455506
0,
456507
CF.Annot.Attrs [],
457-
List.map fst gr.iargs,
508+
(List.map fst gr.iargs
509+
@
510+
if gr.sized then
511+
[ Sym.fresh_named "cn_gen_rec_size" ]
512+
else
513+
[]),
458514
mk_stmt
459515
(A.AilSblock
460516
( b2,
@@ -467,9 +523,7 @@ let compile_gen_def
467523
(mk_expr
468524
(AilEcall
469525
( mk_expr
470-
(AilEident
471-
(Sym.fresh_named
472-
"cn_gen_backtrack_decrement_depth")),
526+
(AilEident (Sym.fresh_named "cn_gen_decrement_depth")),
473527
[] )))
474528
]
475529
@ A.
@@ -504,7 +558,7 @@ let compile (sigma : CF.GenTypes.genTypeCategory A.sigma) (ctx : GR.context) : P
504558
BT.Record (List.map (fun (x, bt) -> (Id.id (Sym.pp_string x), bt)) def.oargs)
505559
in
506560
CtA.augment_record_map ~cn_sym:name bt);
507-
let tag_definitions, funcs = List.split (List.map (compile_gen_def sigma) defs) in
561+
let tag_definitions, funcs = List.split (List.map (compile_gen_def sigma ctx) defs) in
508562
let declarations, function_definitions = List.split funcs in
509563
let sigma : 'a A.sigma =
510564
{ A.empty_sigma with tag_definitions; declarations; function_definitions }

backend/cn/lib/testGeneration/genInline.ml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,16 @@ let unfold (ctx : GD.context) : GD.context =
2929
else
3030
loop (Option.map (fun x -> x - 1) fuel) { gd with body = Some gt' })
3131
in
32-
List.map_snd (List.map_snd (loop (TestGenConfig.get_max_unfolds ()))) ctx
32+
let unfolds = TestGenConfig.get_max_unfolds () in
33+
ctx
34+
|> List.map_snd (List.map_snd (loop unfolds))
35+
|> List.filter_map (fun (x, gds) ->
36+
if Option.is_some unfolds then
37+
Some (x, gds)
38+
else (
39+
match List.filter (fun ((_, gd) : _ * GD.t) -> gd.spec || gd.recursive) gds with
40+
| [] -> None
41+
| gds' -> Some (x, gds')))
3342

3443

3544
let inline (ctx : GD.context) : GD.context = unfold ctx

0 commit comments

Comments
 (0)