1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
type 'a t =
| Assign of Dba.LValue.t * Dba.Expr.t
| SJump of 'a Dba.jump_target * Dba.tag option
| DJump of Dba.Expr.t * Dba.tag option
| Assert of Dba.Expr.t
| If of Dba.Expr.t * 'a Dba.jump_target
| Undef of Dba.LValue.t
| Nondet of Dba.LValue.t
| Stop of Dba.state
let assign lval e =
Dba_logger.debug ~level:5 "@[<hov 0>Assigning %a (%d) with %a (%d)@]"
Dba_printer.Ascii.pp_lhs lval (Dba.LValue.size_of lval)
Dba_printer.Ascii.pp_bl_term e (Dba.Expr.size_of e);
assert (Dba.LValue.size_of lval = Dba.Expr.size_of e);
Assign (lval, e)
let ( <<- ) = assign
let static_jump ?tag jt = SJump (jt, tag)
let dynamic_jump ?tag e = DJump (e, tag)
let dynamic_assert e = Assert e
let conditional_jump c jt = If (c, jt)
let undefined lval = Undef lval
let non_deterministic lval = Nondet lval
let stop s = Stop s
let needs_termination = function
| Dba.Instr.DJump _ | Dba.Instr.SJump (Dba.JOuter _, _) | Dba.Instr.Stop _ ->
false
| Dba.Instr.Assume _ | Dba.Instr.Assert _ | Dba.Instr.Assign _
| Dba.Instr.Undef _ | Dba.Instr.If _ | Dba.Instr.Nondet _ | Dba.Instr.SJump _
->
true
let to_dba_instruction next_id = function
| Assert cond -> Dba.Instr._assert cond next_id
| If (cond, thn) -> Dba.Instr.ite cond thn next_id
| Assign (lhs, expr) -> Dba.Instr.assign lhs expr next_id
| Undef lhs -> Dba.Instr.undefined lhs next_id
| Nondet lhs -> Dba.Instr.non_deterministic lhs next_id
| SJump (dst, tag) -> Dba.Instr.static_jump dst ?tag
| DJump (dst, tag) -> Dba.Instr.dynamic_jump dst ?tag
| Stop st -> Dba.Instr.stop (Some st)
let blockify next_addr instructions =
let end_jump = Dba.Instr.static_jump (Dba.JOuter next_addr) in
let rec aux n acc = function
| [] -> (
match acc with
| [] -> [ end_jump ]
| instr :: _ -> if needs_termination instr then end_jump :: acc else acc
)
| instr :: instructions ->
let id = n + 1 in
let dba_instr = to_dba_instruction id instr in
aux id (dba_instr :: acc) instructions
in
aux 0 [] instructions |> List.rev |> Dhunk.of_list