Summary:
This diff changes the analysis exploration algorithm from considering
only sequential executions to considering executions of the
interleaving semantics. As part of this, symbolic states are changed
so that each thread has its own registers, while all memory is shared
between them.
Currently only a simple threads interface is supported: they can be
created with `thread_create(&thread_routine)`, they can exit by
returning from `thread_routine`, and they can be joined with
`thread_join`. Current simplifications include that newly created
threads are already runnable, thread routines accept no arguments and
return no result, and no failures are possible.
The concurrent exploration algorithm gives preference to executions
which have fewer context switches, thereby performing an incremental
form of context-bounded analysis.
A form of partial-order reduction is performed, where the symbolic
states are joined across (prefixes of) executions with the same number
of context switches which reach a point where the instruction pointers
and call stacks of all threads are the same. This has the effect of
"dagifying" the concurrent execution tree by merging points after
e.g. threads perform actions that commute with each other. This is
unlike traditional partial-order reduction in that it relies on the
symbolic join to combine the results of commuting operations in a way
that the following symbolic execution can take advantage of, rather
than performing some up-front analysis to identify commuting
operations and quotienting the space of executions. The current state
of the symbolic join and execution is significantly suboptimal in this
regard.
Differential Revision: D29441149
fbshipit-source-id: cf801a6b1
Summary:
This diff reworks the analysis scheduler to explicitly use a notion of
"abstract machine state" which makes the distinction with the state of
the analysis exploration algorithm more clear. The instruction
pointer, call stack, symbolic state, and retreating edge depths were,
prior to this change, passed individually to the various `exec_*`
functions. After this change, all this information is combined into an
abstract machine state value.
Additionally, this change explicitly factors out the commonality
between abstract machine states, on which symbolic execution operates,
and the elements of the frontier of exploration, that the analysis
scheduler maintaines. In short, an element of the frontier is simply
an abstract machine state with a control-flow edge instead of an
instruction pointer.
This change is almost entirely a non-functional refactoring. While
this serves as an improvement in code clarity, the main motivation is
that it establishes a code structure which minimizes the structural
changes needed when adding the concurrency analysis.
Differential Revision: D29441152
fbshipit-source-id: 01be87d4e
Summary:
In the sequential analysis there is no control-flow within a basic
block. This changes in the concurrent analyis as context switches can
occur within basic blocks. To support this, this diff adds a notion of
"instruction pointer" to Llair and adjusts Control to use it to
iterate blocks.
Differential Revision: D29441164
fbshipit-source-id: b9c977545
Summary:
The width of joins in the concurrency analysis is much wider, making
it worthwhile to use an n-ary version of join in order to avoid
repeated formula simplifiaction.
Differential Revision: D29441154
fbshipit-source-id: ae17de37b
Summary:
Memoize the translation from program registers to logical
variables. Currently this is not significant, but is semantically
necessary for the concurrency analysis.
Differential Revision: D29441162
fbshipit-source-id: ff674c4c3
Summary:
The output generated for `pp_raw` was incorrectly less raw for
disjuncts than for their parent formulas.
Differential Revision: D29441156
fbshipit-source-id: 3e4b42fe3
Summary:
The initializers of globals are constant expressions, and therefore
contain no registers. This change adds an assertion to make this
existing invariant explicit.
Differential Revision: D29441160
fbshipit-source-id: 4da4e74d1
Summary:
It is possible for normalization to change a term from an
uninterpreted application to e.g. an interpreted atom. For instance,
the conversion `(u1)-1` evaluates to `1`. Context.canon_extend was not
taking this into account, and as a result could violate the
representation invariant of Context.t.
Reviewed By: ngorogiannis
Differential Revision: D28907806
fbshipit-source-id: 9b5171e15
Summary:
Allow joining relations with distinct entry states, since the
destinations will be the same, there is no loss of context
sensitivity. As a result, check that the call stack of the
destinations of edges are equal before joining, as it is no longer
implicitly ensured by the equal entry state check.
This change leads to joining a state with itself often, as the entry
states are often idential, so this diff also adds an optimization of
join with a fast path for joining identical states.
Reviewed By: ngorogiannis
Differential Revision: D28907809
fbshipit-source-id: 2c66223ff
Summary:
The control scheduler treats functions as if they were syntactically
inlined, by including a call stack in each control flow edge,
implicitly copying each function's control-flow graph for each calling
context. A "depth" is maintained for each retreating edge,
representing the number of times the edge has been crossed. The depths
are used to explore executions with fewer loop iterations before those
with more iterations.
The current implementation is incorrect in some situations involving
mutually recursive functions where the cycle detection algorithm
determines that calls to one of the mutually recursive functions need
not be considered retreating. Currently return frames of recursive
calls are filtered out of call stacks for the purposes of tracking
edge depths. This is insufficient in such mutual recursive
situations. This diff fixes this by explicity ignoring the entire
stack of recursive call edges.
Reviewed By: ngorogiannis
Differential Revision: D28907813
fbshipit-source-id: e04849ca8
Summary:
The formatting of sugared list syntax regressed with
https://github.com/ocaml-ppx/ocamlformat/pull/1567.
Reviewed By: ngorogiannis
Differential Revision: D28907812
fbshipit-source-id: 16ad68218
Summary:
Add a mode which executes randomly-chosen paths depth-first, without
duplicating the work of executing shared prefixes. This mode is to be
used when hoping to get lucky and quickly choose a path that exhibits
a bug, but is slower to achieve coverage than the default.
Differential Revision: D27996963
fbshipit-source-id: 20a7a32c5
Summary:
The configuration options for the analysis are used only/principally
in Control, they do not belong in the interface of domains. Also, the
definition of the used_globals type for the results of the used
globals pre-analysis belongs to the Domain_used_globals module.
Reviewed By: jvillard
Differential Revision: D27828752
fbshipit-source-id: e42de74e0
Summary:
Just reorder definitions to clarify that as_inlined_location is not
used in the rest of Stack.
Reviewed By: jvillard
Differential Revision: D27828755
fbshipit-source-id: 1436f1e6d
Summary: Preparation for allowing a choice among several scheduler strategies.
Reviewed By: jvillard
Differential Revision: D27828759
fbshipit-source-id: 63d6ec203
Summary:
The priority queue does not crucially depend on the type of
elements. This diff makes it parametric.
Reviewed By: jvillard
Differential Revision: D27828756
fbshipit-source-id: a7bfc4ee5
Summary:
When domain join operations are total, the control scheduler does not
need to handle the case where joining states is undefined. This leads
to some simplification, and in particular removed the need to expose a
remove operation for the scheduling queue.
Reviewed By: jvillard
Differential Revision: D27828761
fbshipit-source-id: b8cdd2eb6
Summary:
The only domain with a partial join is the lifting of a predicate
domain to a relation one, where the entry states are required to be
equal. This situation now indicates a programming error in the
analysis, rather than something that the domain should be responsible
for. Therefore this diff changes that check to an assertion and
simplifies the remaining join operations which are all total.
Reviewed By: jvillard
Differential Revision: D27828763
fbshipit-source-id: ec52ff741
Summary:
Mainly code cleanup. The only potential functional change is to
eliminate the test that a function returning with an empty stack is an
entry point, which should always hold anyhow.
Reviewed By: jvillard
Differential Revision: D27828749
fbshipit-source-id: 25124a568
Summary:
Mainly code simplification. The only functional change is to move the
test that a candidate entry-point function has no formals earlier,
with the result of avoiding failure if a function with an entry-point
name but with formals is encountered before an entry-point function
with no formals.
Reviewed By: jvillard
Differential Revision: D27828751
fbshipit-source-id: d5a832952
Summary:
There used to be a bug where recursive calls were not correctly
bounded. This is no longer needed, and this diff removes the
workaround that was added in D15577134 (881a4d10af) / 4cd3b62.
Reviewed By: jvillard
Differential Revision: D27828764
fbshipit-source-id: 80265a588
Summary:
Specifying that sledge should stop execution when the first report is
made via e.g. `sledge l a -t Stop` currently only works when debug
tracing is enabled. This diff fixes this so that `-t Stop` also works
for the release build.
Reviewed By: jvillard
Differential Revision: D27828753
fbshipit-source-id: dd7511ff1
Summary:
Currently all alarms are reported as "Invalid memory access", which is
not accurate for `abort` and hence assertion violations. This diff
adds an explicit type for alarms which distinguishes these two
cases. Further refinement is left for later.
Reviewed By: jvillard
Differential Revision: D27828754
fbshipit-source-id: 9c33f3c86
Summary:
The computation of common prefixes and suffixes was wrong. In
particular, the computation of the common suffix did not correctly
consider the common prefix. This manifested in case one entire
sequence is a suffix of the other.
Reviewed By: ngorogiannis
Differential Revision: D27564874
fbshipit-source-id: 267a75102
Summary:
Switch to a stronger but more expensive operation to check if a
symbolic heap is unsatisfiable.
Reviewed By: ngorogiannis
Differential Revision: D27564872
fbshipit-source-id: c8e306408
Summary:
`Typ.equivalent` relates types that denote the same sets of values in
the semantic model, such as pointers and integers of the appropriate
size. This diff strengthens the treatment of casts between such types
in the first-order solver by translating `(s)(t)e` to `e` for
equivalent types `s` and `t`.
These casts are usually simplified out of the bitcode produced by
clang. However, code using `_Atomic(...)` leads to `load atomic` llvm
instructions that, for some reason, cast pointers to i64 and back.
Reviewed By: ngorogiannis
Differential Revision: D27564881
fbshipit-source-id: 6138eb4f1
Summary:
When solving equations such as `α[o,l) = β`, the memory theory solver
computes a term to represent the length of α. This fails if α is a
variable (which might itself be equal to a sized term elsewhere in the
formula). This diff fixes such failures by generating a fresh variable
for the length in such situations.
Reviewed By: ngorogiannis
Differential Revision: D27564871
fbshipit-source-id: e5e066b77
Summary:
There are not too many cases where the function name is not enough to
disambiguate a trace message, but it is still perhaps more
approachable to include the module names as well.
Reviewed By: jvillard
Differential Revision: D27396914
fbshipit-source-id: ea4c8b44f
Summary:
Llair.Func.mk makes two passes over the CFG to resolve block parents,
jump destinations, and eliminate jumps to jumps. This is not
economical, but more importantly the current code mistakenly uses the
`retreating` metadata before it is set correctly. This diff combines
these passes into a single one, which also incorporates setting the
retreating field from Llair.Program.mk.
This avoids nontermination on code that contains immediate self-jumps
such as `L: goto L;` that LLVM 11 can now generate.
Reviewed By: jvillard
Differential Revision: D27262512
fbshipit-source-id: 0543ba669
Summary:
This warning (68) triggers when a function argument pattern depends on
mutable state, which prevents the remaining arguments from being
uncurried, causing additional closure allocations.
Reviewed By: jvillard
Differential Revision: D27188311
fbshipit-source-id: a43354e15
Summary:
It is possible for the filename of a source location to be the empty
string. Fpath.v asserts when passed an empty string.
Reviewed By: jvillard
Differential Revision: D27188304
fbshipit-source-id: a7d73444b
Summary:
The only difference between `program` and `identified` variables is
terminology, technically they are redundant.
Reviewed By: jvillard
Differential Revision: D26451308
fbshipit-source-id: eb4e7be43
Summary:
Negating the ids of program variables leads to inverting the order on
them. This is logically fine, the order is still a valid total order.
But it can lead to choosing younger variables as equality class
representatives over older variables, and thereby lead to more churn
as adding an equality is more likely to cause a change of
representative, and hence additional normalizing rewrites.
Reviewed By: jvillard
Differential Revision: D26451304
fbshipit-source-id: eb20d1901
Summary:
Theory.solved is a list of pairs of terms representing solved
equalities. The order of the pairs is very important, which is not
apparent from the type. This diff introduces an oriented_equality type
to make this more clear.
Reviewed By: jvillard
Differential Revision: D26451303
fbshipit-source-id: 56a49e601
Summary:
Generalize the existing find_or_add and find_and_remove operations to
find_update. Slightly simplify the interfaces of change, update,
find_or_add, and find_and_remove, reducing the gap to the natural
underlying functionality.
Reviewed By: jvillard
Differential Revision: D26451305
fbshipit-source-id: 89f67c84d
Summary:
The normalization and then extension of the carrier can be combined
into one pass. This weakens the property that this normalization needs
to achieve, which yields a small simplification, and combining the
passes is a minor optimization.
Reviewed By: jvillard
Differential Revision: D26400406
fbshipit-source-id: 8a3cbb2de