| Age | Commit message (Collapse) | Author |
|
Some functions are partial, e.g. converting a bitvector to an integer, which
might fail for the bit list representation due to undefined bits. Undefined
cases can be handled in different ways:
- call Lem's failwith, which maps to undefined/ARB in Isabelle and HOL (the
default so far),
- return an option type,
- raise a failure in the monad, or
- use a bitstream oracle to resolve undefined bits.
This patch adds different versions of partial functions corresponding to those
options. The desired behaviour can be selected by choosing a binding in the
Sail prelude. The naming scheme is that the failwith version is the default,
while the other versions have the suffixes _maybe, _fail, and _oracle,
respectively.
|
|
For example, generates an auxiliary function execute_ADD (rs, rt, rd) for the
clause execute (ADD (rs,rt,rd)) = ...
Without this rewriting, the execute function easily becomes too large to be
handled by Isabelle (e.g., for CHERI-MIPS; for MIPS alone, it seems to be just
about small enough).
This used to be implemented in the pretty-printer, but that code was commented
out recently in order to support a recursive execute function for RISC-V
compressed instructions.
|
|
Effectful expressions are monadic in Lem, causing type errors when binding them
to global immutable variables.
|
|
The state monad currently assumes that tags are written to and read from
properly aligned addresses (since it does not know the capability size used in
the Sail model). This change allows the Sail model to pass in the aligned
address(es) even if data is written to an unaligned address. There might be
better ways to model tag writing, but this approach seems rather general.
|
|
This simplifies reasoning in Isabelle.
|
|
|
|
Fixed an issue whereby an option constructor that was never
constructed, but only matched on, would cause compilation to
fail. Temporarily fixed an issue where union types that can be
entirely stack-allocated were not being treated as such, by simply
heap-allocating all unions. Need to adapt the code generator to handle
this case properly. Fixed a further small issue whereby multiple union
types would confuse the type specialisation pass.
Added a test case for compiling option types.
RISCV now generates C code, but there are still some bugs that need to
be squashed before it compile and work.
|
|
|
|
|
|
|
|
Add a flag to Sail that allows for an image of an elf file to be
dumped in a simple format using linksem, used as
sail -elf test.elf -o test.bin
This image file can then be used by a compiled C version of a sail
spec as with ocaml simply by
./a.out test.bin
|
|
|
|
Also work on making C backend compile RISC-V
|
|
|
|
Previously union types could have no-argument constructors, for
example the option type was previously:
union option ('a : Type) = {
Some : 'a,
None
}
Now every union constructor must have a type, so option becomes:
union option ('a : Type) = {
Some : 'a,
None : unit
}
The reason for this is because previously these two different types of
constructors where very different in the AST, constructors with
arguments were used the E_app AST node, and no-argument constructors
used the E_id node. This was particularly awkward, because it meant
that E_id nodes could have polymorphic types, i.e. every E_id node
that was also a union constructor had to be annotated with a type
quantifier, in constrast with all other identifiers that have
unquantified types. This became an issue when monomorphising types,
because the machinery for figuring out function instantiations can't
be applied to identifier nodes. The same story occurs in patterns,
where previously unions were split across P_id and P_app nodes - now
the P_app node alone is used solely for unions.
This is a breaking change because it changes the syntax for union
constructors - where as previously option was matched as:
function is_none opt = match opt {
Some(_) => false,
None => true
}
it is now matched as
function is_none opt = match opt {
Some(_) => false,
None() => true
}
note that constructor() is syntactic sugar for constructor(()), i.e. a
one argument constructor with unit as it's value. This is exactly the
same as for functions where a unit-function can be called as f() and
not as f(()). (This commit also makes exit() work consistently in the
same way) An attempt to pattern match a variable with the same name as
a union-constructor now gives an error as a way to guard against
mistakes made because of this change.
There is probably an argument for supporting the old syntax via some
syntactic sugar, as it is slightly prettier that way, but for now I
have chosen to keep the implementation as simple as possible.
The RISCV spec, ARM spec, and tests have been updated to account for
this change. Furthermore the option type can now be included from
$SAIL_DIR/lib/ using
$include <option.sail>
|
|
|
|
Can now handle when an instantiation introduces more polymorphism. We
can now deal with the case where, for example, a type variable gets
specialised in two two steps, e.g. 'a => list('a) => list(int). Also
handle the case where a Type-kinded type variable gets substituted
with an Int-polymorphic type, e.g. 'a => atom('n).
This also fixes an issue where specialisation would loop due to
generated type variable names. This was fixed by ensuring that when we
convert an instantiation to a string to name the newly specialised
definition, we ensure that any alpha-equivalent instantiations map to
the same name.
|
|
Currently ignored in the state monad
|
|
Add an Undefined outcome to the prompt monad that asks the environment for a
Boolean value. For the state monad, add fields for a random generator and a
seed (currently of type nat) to the state.
|
|
Rather than just using strings to represent literals, now use value
types from sail_lib.lem to represent them. This allows for expressions
to be evaluated at compile time, which will be useful for future
optimisations involving constant folding and propagation, and allows
the intermediate bytecode to be interpreted using the same lem
builtins that the shallow embedding uses.
To get this to work I had to tweak the build process slightly to allow
ml files to import lem files from gen_lib/. Hopefully this doesn't
break anything!
|
|
The rewriter ignored loops that were not contained within some let-binding,
which later caused the Lem pretty-printer to fail (see #8).
|
|
Fix for loop in interactive interpreter
Fixes #8
|
|
|
|
intialising and dumping CHERI state. Somewhat working cheri sail2 model.
|
|
One caveat still: Won't work if the polymorphic definition consists of
multiple function clauses, but this seems unlikely - and I added an
error message if this is the case.
Also fix a small flow typing bug
Fixes #7
|
|
Previously this did not result in an error, but would cause issues
with generated code.
Fixes #5
|
|
Fixes #6
|
|
Fix some issues where some early returns in functions would cause
memory leaks, and optimize struct updates so the struct is not copied
uneccesarily.
Also make C print_bits match ocaml version output, and update tests.
|
|
|
|
|
|
|
|
With these optimisations on, now get about 10x performance over OCaml.
|
|
entry_point overflows an ocaml int.
|
|
Fixes #4
|
|
The suffix _lemmas is more descriptive than _extras.
|
|
Architecture-specific lemmas about concrete registers and types are generated
and written to a file <prefix>_lemmas.thy, generic lemmas are in the
theories *_extras.thy in lib/isabelle. In particular, State_extras contains
simplification lemmas about the lifting from prompt to state monad.
|
|
Fixed an issue with pattern matching on enums
Fixed an issue whereby fix_early_returns would cause memory leaks
Added optimizations for some of the builtins used in the decode
function. Optimizations are turned on with the -O flag.
|
|
|
|
|
|
to_get_slice_int in less confusing way. Add arithmetic shift right.
|
|
Add support for short-ciruiting and/or. I forgot about this in the
original ANF specification and not having it causes problems for the
ARM spec.
|
|
(plus some adjustments for the test case)
|
|
|
|
|
|
|
|
|
|
Now compiles to C and builds a working executable. Just need to
correctly implement all the library builtins (some are still stubs),
and it should work.
|
|
|
|
const progagation.
Needed to avoid negative bitvector sizes on aarch64
Also propagate values found from "if var = const ...", which is needed in
aarch64
|
|
|