| Age | Commit message (Collapse) | Author |
|
|
|
Shouldn't affect anything as this is done by the typechecker now.
Also remove some unfinished tracing code from c_backend.ml
|
|
Main change is splitting apart the Sail->IR compilation stage and the
C code generation and optimization phase. Rather than variously
calling the intermediate language either bytecode (when it's not
really) or simply IR, we give it a name: Jib (a type of Sail). Most of
the types are still prefixed by c/C, and I don't think it's worth
changing this.
The various parts of the C backend are now in the src/jib/ subdirectory
src/jib/anf.ml - Sail->ANF translation
src/jib/jib_util.ml - various Jib AST processing and helper functions (formerly bytecode_util)
src/jib/jib_compile.ml - Sail->Jib translation (using Sail->ANF)
src/jib/c_backend.ml - Jib->C code generator and optimizations
Further, bytecode.ott is now jib.ott and generates jib.ml (which still
lives in src/ for now)
The optimizations in c_backend.ml should eventually be moved in a
separate jib_optimization file.
The Sail->Jib compilation can be parameterised by two functions - one
is a custom ANF->ANF optimization pass that can be specified on a per
Jib backend basis, and the other is the rule for translating Sail
types in Jib types. This can be more or less precise depending on how
precise we want to be about bit-widths etc, i.e. we only care about <64
and >64 for C, but for SMT generation we would want to be as precise
as possible.
Additional improvements:
The Jib IR is now agnostic about whether arguments are allocated on
the heap vs the stack and this is handled by the C code generator.
jib.ott now has some more comments explaining various parts of the Jib
AST.
A Set module and comparison function for ctyps is defined, and some
functions now return ctyp sets rather than lists to avoid repeated
work.
|
|
|
|
|
|
|
|
|
|
Previously instrs_graph would return the control-flow graph, as well
as some data-flow by including reads and writes to variables
represented as a node type in the graph (G_id). However, this was not
particularly useful, and since the graph isn't in SSA form (so
identifiers are non-unique) potentially inaccurate too. This
simplifies the code so instrs_graph just returns control flow
dependencies, which in turn simplifies the instr_reads and
instr_writes functions.
|
|
(e.g., for the dual 32/64 bit RISC-V model)
Apply this rewrite in Coq backend.
|
|
|
|
This shouldn't change any functionality.
|
|
|
|
|
|
Make instruction dependency graph use graph.ml
Expose incremental graph building functions for performance in graph.mli
|
|
|
|
Add some comments in constant_fold.ml
|
|
|
|
|
|
|
|
|
|
Rename rewrite_split_fun_constr_pats to rewrite_split_fun_ctor_pats as
constr is commonly used as an abbreviation for constraint rather than
constructor, and add a more descriptive comment.
|
|
Previously any constraints on constructors were just outright dropped
when splitting the execute function in Lem generation. Now we get the
constraints and type signature for each execute clause from the type
given by Env.get_union_constructor, rather than by inferring the type
of the pattern in each function clause.
Currently this can still fail in the case where we have
union U('x: Int), C1('x) = { ctor: {'y. C2('x, 'y), T('x, 'y)} }
and
val execute : forall 'z, C3('z). U('z) -> unit
when C3 implies C1, and the body of an excute clause relies on the
fact that C3 is stronger than C1, as each split function execute_ctor
is only guaranteed to be constrained by some subset of C1. This seems
unlikely to happen in practice though.
Also fix a bug when binding P as int('T) against int('T) and similar
cases, where the new type variable would cause the old type variable
to become shadowed, but the constraint that the bound type variable
and the old type variable are equal would not take this into account.
|
|
|
|
|
|
|
|
Fixes some bugs found by doing this
|
|
|
|
Also make unifying int against int('n) work as expected for
constructor applications.
|
|
|
|
Issues came up with Christophers translation of hand-written ARM into
Sail2 where we were being overly pedantic about the exact position of
existential quantifiers in constructors with multiple arguments. This
commit generalises unify_typ and type_coercion_unify to be more
flexible and support this. Should think at some point if unify_typ can
be generalised further.
This fix should fix the decode side of things, but may be some issues
with the executes that still need looking into when existentials and
multiple argument constructors are mixed.
|
|
|
|
|
|
Also drop unused implication function
|
|
|
|
Now generates something vaguely sensible for RISC-V, although the solver
needs a little work.
Adds type annotations around effectful, rich and/or expressions.
|
|
Make internal_plet produce annotations (with code to replace unusable
type variables)
Add mappings for bool kids at bindings
Add version of and_bool that proves a property
|
|
|
|
|
|
|
|
Also make pretty printing more keen on line breaking
|
|
This introduces some simplification of informative booleans, but tries
too hard to eliminate all of the existentials resulting in difficulties
in and/or trees.
|
|
For example:
sail -c_extra_params "CPUMIPSState *env" -c_extra_args env
would pass a QEMU MIPS cpu state to every non-builtin function call.
Also add documentation for each C compilation option in C_backend.mli
|
|
|
|
Can now set a prefix for generated C functions with -c_prefix so
-c_prefix sail_ would give sail_execute_CGetPerm over
zexecute_CGetPerm. We still have to use our standard name-mangling
scheme to avoid possible collisions within the name.
Can build C that doesn't expect the standard runtime, which leaves
operations like read_memory, write_memory etc to be stubbed in by
another C program including the generated Sail. Things like
letbindings are still an issue because we rely on a very small runtime
to initialize global letbindings and similar.
-c_separate_execute splits the execute function apart in the generated C
|
|
|
|
The old check used the wrong part of the AST. It would stop when it
reached the actual effect, anyway, but this should improve performance.
|
|
Add a flag in C backend ctx that allows us to generate arbitrary
precision signed integer types, rather than just int64
|
|
|
|
|
|
If we want to use our low-level intermediate representation to generate
SMT, then we want to be more precise than just splitting integers into
64-bits and larger. This commit changes CT_int and CT_int64 into CT_lint
for large integers and CT_fint n for (signed) fixed precision integers
that fit within n bits. This follows the convention for bitvectors where
we have CT_fbits for fixed-length bitvectors and CT_lbits for large
arbitrary precision bitvectors.
|