forked from ocaml/ocaml
-
Notifications
You must be signed in to change notification settings - Fork 0
/
dataflow.mli
90 lines (76 loc) · 4.39 KB
/
dataflow.mli
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
(**************************************************************************)
(* *)
(* OCaml *)
(* *)
(* Xavier Leroy, projet Cambium, INRIA Paris *)
(* *)
(* Copyright 2021 Institut National de Recherche en Informatique et *)
(* en Automatique. *)
(* *)
(* All rights reserved. This file is distributed under the terms of *)
(* the GNU Lesser General Public License version 2.1, with the *)
(* special exception on linking described in the file LICENSE. *)
(* *)
(**************************************************************************)
(* An abstract domain for dataflow analysis. Defines a type [t]
of abstractions, with lattice operations. *)
module type DOMAIN = sig
type t
val bot: t
val join: t -> t -> t
val lessequal: t -> t -> bool
end
(* Build a backward dataflow analysis engine for the given domain. *)
module Backward(D: DOMAIN) : sig
val analyze: ?exnhandler: (D.t -> D.t) ->
?exnescape: D.t ->
transfer: (Mach.instruction -> next: D.t -> exn: D.t -> D.t) ->
Mach.instruction ->
D.t * (int -> D.t)
(* [analyze ~exnhandler ~transfer instr] performs a backward dataflow
analysis on the Mach instruction [instr], typically a function body.
It returns a pair of
- the abstract state at the function entry point;
- a mapping from catch handler label to the abstract state at the
beginning of the handler with this label.
The [transfer] function is called as [transfer i ~next ~exn].
- [i] is a sub-instruction of [instr].
- [next] is the abstract state "after" the instruction for
normal control flow, falling through the successor(s) of [i].
- [exn] is the abstract state "after" the instruction for
exceptional control flow, branching to the nearest exception handler
or exiting the function with an unhandled exception.
The [transfer] function, then, returns the abstract state "before"
the instruction. The dataflow analysis will, then, propagate this
state "before" as the state "after" the predecessor instructions.
For compound instructions like [Iifthenelse], the [next] abstract
value that is passed to [transfer] is not the abstract state at
the end of the compound instruction (e.g. after the "then" and "else"
branches have joined), but the join of the abstract states at
the beginning of the sub-instructions. More precisely:
- for [Iifthenelse(tst, ifso, ifnot)], it's the join of the
abstract states at the beginning of the [ifso] and [ifnot]
branches;
- for [Iswitch(tbl, cases)], it's the join of the abstract states
at the beginning of the [cases] branches;
- for [Icatch(recflag, body, handlers)] and [Itrywith(body, handler)],
it's the abstract state at the beginning of [body].
The [transfer] function is called for every sub-instruction of [instr],
as many times as needed to reach a fixpoint. Hence, it can record
the results of the analysis at each sub-instruction in a mutable
data structure. For instance, the transfer function for liveness
analysis updates the [live] fields of instructions as a side
effect.
The optional [exnhandler] argument deals with exception handlers.
This is a function that transforms the abstract state at the
beginning of an exception handler into the exceptional abstract
state for the instructions within the body of the handler.
Typically, for liveness analysis, it takes the registers live at
the beginning of the handler and removes the register
[Proc.loc_exn_bucket] that carries the exception value. If not
specified, [exnhandler] defaults to the identity function.
The optional [exnescape] argument deals with unhandled exceptions.
It is the abstract state corresponding to exiting the function on an
unhandled exception. It defaults to [D.bot].
*)
end