Frama-C API - Partition
A partition is a collection of states, each identified by a unique key. The keys define the states partition: states with identical keys are joined together, while states with different keys are maintained separate. A key contains the reason for which a state must be kept separate from others, or joined with similar states.
Partitioning actions allow updating the keys or splitting some states to define or change the partition. Actions are applied to flows, in which states with the same key are *not* automatically joined. This allows applying multiple actions before recomputing the partitions. Flows can then be converted into partitions, thus merging states with identical keys.
Flows are used to transfer states from one partition to another. Transfer functions can be applied to flows; keys are maintained through transfer functions, until partitioning actions update them.
Keys and partitions.
type branch = | Branch of int(*Junction branch id in the control flow
*)| Builtin_result of Frama_c_kernel.Kernel_function.t * Frama_c_kernel.Cil_datatype.Kinstr.t * int(*Case of a builtin
*)| Spec_behavior of Frama_c_kernel.Kernel_function.t * Frama_c_kernel.Cil_datatype.Kinstr.t * int(*Behavior of a spec
*)| Disjunction_case of Frama_c_kernel.Cil_datatype.Stmt.t * int(*Case of a disjunction in an ACSL annotation
*)
module Key : sig ... endval empty : 'a partitionval is_empty : 'a partition -> boolval size : 'a partition -> intPartitioning actions.
Rationing are used to keep separate the n first states propagated at a point, by creating unique stamp until the limit is reached. Implementation of the option -eva-slevel.
val new_rationing : limit:int -> merge:bool -> rationingCreates a new rationing, that can be used successively on several flows.
type unroll_limit = | ExpLimit of Frama_c_kernel.Cil_types.exp(*Value of the expression for each incoming state. The expression must evaluate to a singleton integer in each state.
*)| IntLimit of int(*Integer limit.
*)| AutoUnroll of Eva_automata.loop * int * int(*
*)AutoUnroll(loop, min, max)requests to find a "good" unrolling limit betweenminandmaxfor the looploop.
The unroll limit of a loop.
Splits on an expression can be static or dynamic:
- static splits are processed once: the expression is only evaluated at the split point, and the key is then kept unchanged until a merge.
- dynamic splits are regularly redone: the expression is re-evaluated, and states are then split or merged accordingly.
val new_monitor : limit:int -> kind:split_kind -> term:Eva_annotations.split_term -> split_monitorCreates a new monitor that allows to split up to limit states according to term evaluation.
type action = | Enter_loop of unroll_limit * Eva_automata.loop(*Enters a loop in which the n first iterations will be kept separate: creates an iteration counter at 0 for each states in the flow; states at different iterations will be kept separate, until reaching the
*)unroll_limit. Counters are incremented by theIncr_loopaction.| Leave_loop(*Leaves the current loop: removes its iteration counter. States that were kept separate only by this iteration counter will be joined together.
*)| Incr_loop(*Increments the iteration counter of the current loop for all states in the flow. States with different iteration counter are kept separate.
*)| Add_branch of int * int(*Identifies all the states in the flow as coming from the branch identified by the first integer. They will be kept separated from states coming from other branches. The second integer is the maximum number of successive branches kept in the keys: this action also removes the oldest branches from the keys to meet this constraint.
*)| Ration of rationing(*Ensures that the first states encountered are kept separate, by creating a unique ration stamp for each new state until the
*)limitis reached. The same rationing can be used on multiple flows. Applying a new rationing replaces the previous one. If the rationing has been created withmerge:true, all the states from each flow receive the same stamp, but states from different flows receive different stamps, untillimitstates have been tagged.| Restrict of Eva_ast.exp * Frama_c_kernel.Z.t list(*
*)Restrict (exp, list)restricts the rationing according to the evaluation of the expressionexp: – for each integeriinlist, states in whichexpevaluates exactly to the singletonireceive the same unique stamp, and will thus be joined together but kept separate from other states; – all other states are joined together. Previous rationing is erased and replaced by this new stamping. Implementation of the option -eva-split-return.| Split of split_monitor(*If
*)monitorhas been built asnew_monitor ~limit ~kind ~termthenSplit monitortries to separate states such as thetermevaluates to a singleton value in each state in the flow. If necessary and possible, splits states into multiple states. States in which thetermevaluates to different values will be kept separate. Gives up the split iftermevaluates to more thanlimitvalues. A same monitor can be used for successive splits on different flows.| Merge of Eva_annotations.split_term(*Forgets the split of an expression: states that were kept separate only by the split of this expression will be joined together.
*)| Update_dynamic_splits(*Updates dynamic splits by evaluating the expression and splitting the states accordingly.
*)
These actions redefine the partitioning by updating keys or splitting states. They are applied to all the pair (key, state) in a flow.
Flows.
module MakeFlow (Abstract : Engine_abstractions_sig.S) : sig ... endFlows are used to transfer states from one partition to another, by applying transfer functions and partitioning actions. They do not enforce the unicity of keys.
