summaryrefslogtreecommitdiff
path: root/src
AgeCommit message (Collapse)Author
2018-11-30Remove constraint synonymsAlasdair Armstrong
They weren't needed for ASL parser like I thought they would be, and they increase the complexity of dealing with constraints throughout Sail, so just remove them. Also fix some compiler warnings
2018-11-30Parser tweaks and fixesAlasdair Armstrong
- Completely remove the nexp = nexp syntax in favour of nexp == nexp. All our existing specs have already switched over. As part of this fix every test that used the old syntax, and update the generated aarch64 specs - Remove the `type when constraint` syntax. It just makes changing the parser in any way really awkward. - Change the syntax for declaring new types with multiple type parameters from: type foo('a : Type) ('n : Int), constraint = ... to type foo('a: Type, 'n: Int), constraint = ... This makes type declarations mimic function declarations, and makes the syntax for declaring types match the syntax for using types, as foo is used as foo(type, nexp). None of our specifications use types with multiple type parameters so this change doesn't actually break anything, other than some tests. The brackets around the type parameters are now mandatory. - Experiment with splitting Type/Order type parameters from Int type parameters in the parser. Currently in a type bar(x, y, z) all of x, y, and z could be either numeric expressions, orders, or types. This means that in the parser we are severely restricted in what we can parse in numeric expressions because everything has to be parseable as a type (atyp) - it also means we can't introduce boolean type variables/expressions or other minisail features (like removing ticks from type variables!) because we are heavily constrained by what we can parse unambigiously due to how these different type parameters can be mixed and interleaved. There is now experimental syntax: vector::<'o, 'a>('n) <--> vector('n, 'o, 'a) which splits the type argument list into two between Type/Order-polymorphic arguments and Int-polymorphic arguments. The exact choice of delimiters isn't set in stone - ::< and > match generics in Rust. The obvious choices of < and > / [ and ] are ambigious in various ways. Using this syntax right now triggers a warning. - Fix undefined behaviour in C compilation when concatenating a 0-length vector with a 64-length vector.
2018-11-30Improvements for ASL parserAlasdair Armstrong
- Fix pretty printing nested constraints - Add flow typing for if condition then { throw exn }; ... blocks - Add optimisations for bitvector concatenation in C
2018-11-28Allow folding constant expressions into single register readsAlasdair
Essentially all we have to do to make this work is introduce a member of the Value type, V_attempted_read <reg>, which is returned whenever we try to read a register value with allow_registers disabled. This defers the failure from reading the register to the point where the register value is used (simply because nothing knows how to deal with V_attempted_read). However, if V_attempted_read is returned directly as the result of evaluating an expression, then we can replace the expression with a single direct register read. This optimises some indirection in the ARM specification.
2018-11-27Fix memory leak in string_of_bitsAlasdair Armstrong
Should hopefully fix memory leak in RISC-V. Also adds an optimization pass that removes copying structs and allows some structs to simply alias each other and avoid copying their contents. This requires knowing certain things about the lifetimes of the structs involved, as can't free the struct if another variable is referencing it - therefore we conservatively only apply this optimization for variables that are lifted outside function definitions, and should therefore never get freed until the model exits - however this may cause issues outside ARMv8, as there may be cases where a struct can exist within a variant type (which are not yet subject to this lifting optimisation), that would break these assumptions - therefore this optimisation is only enabled with the -Oexperimental flag.
2018-11-27Add an optimisation pass to combine variables if possibleAlasdair Armstrong
This optimisation re-uses variables if possible, rather than allocating new ones.
2018-11-26Use a temporary definition of List.init until 4.06 is more standard.Prashanth Mundkur
2018-11-26Add random generators for record typesBrian Campbell
2018-11-23Introduce intermediate bitvector representation in CAlasdair Armstrong
Bitvectors that aren't fixed size, but can still be shown to fit within 64-bits, now have a specialised representation. Still need to introduce more optimized functions, as right now we mostly have to convert them into large bitvectors to pass them into most functions. Nevertheless, this doubles the performance of the TLBLookup function in ARMv8.
2018-11-23C backend improvementsAlasdair Armstrong
- Propagate types more accurately to improve optimization on ANF representation. - Add a generic optimization pass to remove redundant variables that simply alias other variables. - Modify Sail interactive mode, so it can compile a specification with the :compile command, view generated intermediate representation via the :ir <function> command, and step-through the IR with :exec <exp> (although this is very incomplete) - Introduce a third bitvector representation, between fast fixed-precision bitvectors, and variable length large bitvectors. The bitvector types are now from most efficient to least * CT_fbits for fixed precision, 64-bit or less bitvectors * CT_sbits for 64-bit or less, variable length bitvectors * CT_lbits for arbitrary variable length bitvectors - Support for generating C code using CT_sbits is currently incomplete, it just exists in the intermediate representation right now. - Include ctyp in AV_C_fragment, so we don't have to recompute it
2018-11-21Coq: only generate equality functions for records where we need itBrian Campbell
because >100 field records slow everything down
2018-11-21Coq: add equality for records and polymorphic vectorsBrian Campbell
2018-11-21Escape string literals in coq backend. Note that ↵Robert Norton
71020c2f460e6031776df17cf8f2f71df5bb9730 introduced assert error messages containing " revealing unescaped string literals in generated lem and prompting review of other backends.
2018-11-21Escape strings literals in lem pretty printer.Robert Norton
2018-11-20Add messages for assert failures without user defined messagesAlasdair Armstrong
Also fix some C optimisations
2018-11-19Fix Lem untupling to correctly identify when multiple arguments are usedBrian Campbell
Fixes CHERI Lem build
2018-11-19Don't re-check AST repeatedly in exp_lift_assign re-writeAlasdair Armstrong
This was _really_ slow - about 50secs for ARM. If this changes causes breakages we should fix them in some other way. Also using Reporting.err_unreachable in ANF translation, and fix slice optimization when creating slices larger than 64-bits in C translation
2018-11-19Ensure sizeof re-writing occurs for configuration registersAlasdair Armstrong
2018-11-19Merge branch 'latex' into sail2Robert Norton
2018-11-16Canonicalise functions types in val specsAlasdair Armstrong
This brings Sail closer to MiniSail, and means that type my_range 'n 'm = {'o, 'n <= 'o <= 'm. int('o)} will work on the left hand side of a function type in the same way as a regular built-in range type. This means that in principle neither range nor int need be built-in types, as both can be implemented in terms of int('n) (atom internally). It also means we can easily identify type variables that need to be made into implict arguments, with the criterion for that being simply any type variable that doesn't appear in a base type on the LHS of the function, or only appears on the RHS.
2018-11-16Various bugfixes and a simple profiling feature for rewritesAlasdair Armstrong
2018-11-15When outputing latex do not expand type synonyms in val specs during type check.Robert Norton
2018-11-15Add simple valspec printing in latex that drops effects and other extraneous ↵Robert Norton
details (TODO make this optional).
2018-11-15ast_utils: simplify numeric constraints in inequalities.Robert Norton
2018-11-14Use code style For [id] refs in doc comments.Robert Norton
2018-11-14latex: use callback macro saildocxxx (one per top-level category) to give ↵Robert Norton
usere more flexibility about formatting generated latex.
2018-11-13Make pretty printer stricter with brace placementAlasdair Armstrong
Also add a special case for shift-left when we are shifting 8 by a two bit opcode, or 32 by a one bit opcode.
2018-11-12Infer tuple l-expressions types if all components are inferrableAlasdair Armstrong
This fixes another case we often have to patch manually in translated ASL code where a function returns a (result, Constraint)-pair. Also (slightly) improve the error message for when we fail to infer a l-expression, as we are going to hit this case more often now.
2018-11-12Make type checker smarter at inferring l-expressionsAlasdair Armstrong
Previously the following would fail: ``` default Order dec $include <prelude.sail> register V : vector(1, dec, vector(32, dec, bit)) val zeros : forall 'n, 'n >= 0. unit -> vector('n, dec, bit) function main() : unit -> unit = { V[0] = zeros() } ``` Since the type-checker wouldn't see that zeros() must have type `vector(32, dec, bit)` from the type of `V[0]`. It now tries both to infer the expression, and use that to check the assignment, and if that fails we infer the lexp to check the assignment. This pattern occurs a lot in ASL, and we often had to patch zeros() to zeros(32) or similar there.
2018-11-12Add referencing commands to generated latexAlasdair Armstrong
2018-11-12Fix numbers in constructor argumentsAlasdair Armstrong
Also ensure no collisions for function clause constructor categories
2018-11-12Improve latex naming scheme and avoid collisionsAlasdair Armstrong
2018-11-09Improvements to latex generationAlasdair Armstrong
The main changes so far are: * Allow markdown formatting in doc comments. We parse the markdown using Omd, which is a OCaml library for parsing markdown. The nice thing about this library is it's pure OCaml and has no dependencies other the the stdlib. Incidentally it was also developed at OCaml labs. Using markdown keeps our doc-comments from becoming latex specfic, and having an actual parser is _much_ nicer than trying to hackily process latex in doc-comments using OCamls somewhat sub-par regex support. * More sane conversion latex identifiers the main approach is to convert Sail identifiers to lowerCamelCase, replacing numbers with words, and then add a 'category' code based on the type of identifier, so for a function we'd have fnlowerCamelCase and for type synonym typelowerCamelCase etc. Because this transformation is non-injective we keep track of identifiers we've generated so we end up with identifierA, identifierB, identifierC when there are collisions. * Because we parse markdown in doc comments doc comments can use Sail identifiers directly in hyperlinks, without having to care about how they are name-mangled down into TeX compatible things. * Allow directives to be passed through the compiler to backends. There are various $latex directives that modify the latex output. Most usefully there's a $latex newcommand name markdown directive that uses the markdown parser to generate latex commands. An example of why this is useful is bellow. We can also use $latex noref id To suppress automatically inserting links to an identifier * Refactor the latex generator to make the overall generation process cleaner * Work around the fact that some operating systems consider case-sensitive file names to be a good thing * Fix a bug where latex generation wouldn't occur unless the directory specified by -o didn't exist This isn't quite all the requested features for good CHERI documentation, but new features should be much easier to add now.
2018-11-07Move inline forall in function definitionsAlasdair Armstrong
* Previously we allowed the following bizarre syntax for a forall quantifier on a function: val foo(arg1: int('n), arg2: typ2) -> forall 'n, 'n >= 0. unit this commit changes this to the more sane: val foo forall 'n, 'n >= 2. (arg1: int('n), arg2: typ2) -> unit Having talked about it today, we could consider adding the syntax val foo where 'n >= 2. (arg1: int('n), arg2: typ2) -> unit which would avoid the forall (by implicitly quantifying variables in the constraint), and be slightly more friendly especially for documentation purposes. Only RISC-V used this syntax, so all uses of it there have been switched to the new style. * Second, there is a new (somewhat experimental) syntax for existentials, that is hopefully more readable and closer to minisail: val foo(x: int, y: int) -> int('m) with 'm >= 2 "type('n) with constraint" is equivalent to minisail: {'n: type | constraint} the type variables in typ are implicitly quantified, so this is equivalent to {'n, constraint. typ('n)} In order to make this syntax non-ambiguous we have to use == in constraints rather than =, but this is a good thing anyway because the previous situation where = was type level equality and == term level equality was confusing. Now all the type type-level and term-level operators can be consistent. However, to avoid breaking anything = is still allowed in non-with constraints, and produces a deprecated warning when parsed.
2018-11-07Move inline forall in function definitionsAlasdair Armstrong
* Previously we allowed the following bizarre syntax for a forall quantifier on a function: val foo(arg1: int('n), arg2: typ2) -> forall 'n, 'n >= 0. unit this commit changes this to the more sane: val foo forall 'n, 'n >= 2. (arg1: int('n), arg2: typ2) -> unit Having talked about it today, we could consider adding the syntax val foo where 'n >= 2. (arg1: int('n), arg2: typ2) -> unit which would avoid the forall (by implicitly quantifying variables in the constraint), and be slightly more friendly especially for documentation purposes. Only RISC-V used this syntax, so all uses of it there have been switched to the new style. * Second, there is a new (somewhat experimental) syntax for existentials, that is hopefully more readable and closer to minisail: val foo(x: int, y: int) -> int('m) with 'm >= 2 "type('n) with constraint" is equivalent to minisail: {'n: type | constraint} the type variables in typ are implicitly quantified, so this is equivalent to {'n, constraint. typ('n)} In order to make this syntax non-ambiguous we have to use == in constraints rather than =, but this is a good thing anyway because the previous situation where = was type level equality and == term level equality was confusing. Now all the type type-level and term-level operators can be consistent. However, to avoid breaking anything = is still allowed in non-with constraints, and produces a deprecated warning when parsed.
2018-11-06Fix bug with loop indices not being mapped to int64 in CAlasdair Armstrong
This should fix the issue in cheri128 Also introduce a feature to more easily debug the C backend: sail -dfunction Name will pretty-print the ANF and IR representation of just the Name function. I want to make this work for the type-checker as well, but it's a bit hard to get that to not fire during re-writing passes right now.
2018-11-05Ensure function quantifier is in scope when generating C return typeAlasdair Armstrong
This goes partway to resolving issue #23, as it now generates C code, but it seems like there is still an issue with the generated C.
2018-11-05Ensure type-synonyms are handled correctly in register dependenciesAlasdair Armstrong
We need to ensure that we expand type-synonyms when calculating which types a register depends on during topological sorting in order to place the undefined_type function in the correct place, even when type is indirected through a function.
2018-11-05Make sure undefined_type functions are generated before registersAlasdair Armstrong
When topologically sorting the top-level definitions, we add the undefined_X functions for any type X to a registers dependencies if it uses the type X, this ensures that any such functions are generated before the register declaration. In theory this is only needed for OCaml, but adding these edges in the definition graph shouldn't cause any issues.
2018-11-02Add code to analyse function return typesAlasdair Armstrong
For ASL parser, we have code that can add additional constraints to a function if they are required by functions it calls, but for more general range analysis we need to restrict the return types of various ASL functions that return int. To do this we can write some code that walks over the type-checked AST for a function body and tries to infer a more restrictive return type at each function exit point. Then we try to union those types together if possible to infer a more restricted return type. For example, for the highest_set_bit function val highest_set_bit : forall ('n : Int), 'n >= 0. bits('n) -> int function highest_set_bit x = { foreach (i from ('n - 1) to 0 by 1 in dec) { print_int("idx = ", i); if [x[i]] == 0b1 then return(i) else () }; return(negate(1)) } Which is annotated as returning any int, we can synthesise a return type of {'m, ('m = -1 | (0 <= 'm & 'm <= ('n - 1))). int('m)} Currently I have this code in Sail as it's likely also useful as a optimisation/lint but it could also live in the asl_parser repository.
2018-11-02Coq: add more autocasts for different but equal kidsBrian Campbell
(only affects Reduce on Aarch64)
2018-11-01Changes to enable analysing type errors in ASL parserAlasdair Armstrong
Also some pretty printer improvements Make all the tests use the same colours for green/red/yellow
2018-10-31Add rewriting pass for not-patternsAlasdair Armstrong
Doesn't work with nested not-patterns, but I think we should probably just disallow these as they seem very hard to remove in any kind of sensible way.
2018-10-31Remove Parse_ast.Int, add unique locationsAlasdair Armstrong
Remove Parse_ast.Int (for internal locations) as this was unused. Add a Parse_ast.Unique constructor to create unique locations. Change locate_X functions to take a function modifying locations, rather than just replacing them and add a function unique : l -> l that makes locations unique, such that `locate unique X` will make a locations in X unique.
2018-10-31Rename Reporting_basic to ReportingAlasdair Armstrong
There is no Reporting_complex, so it's not clear what the basic is intended to signify anyway. Add a GitHub issue link to any err_unreachable errors (as they are all bugs)
2018-10-31Improve error messages for unsolved function quantifiersAlasdair Armstrong
For example, for a function like ``` val aget_X : forall 'n, 0 <= 'n <= 31. int('n) -> bits(64) function test(n : int) -> unit = { let y = aget_X(n); () } ``` we get the message > Could not resolve quantifiers for aget_X (0 <= 'ex7# & 'ex7# <= 31) > > Try adding named type variables for n : atom('ex7#) > > The property (0 <= n & n <= 31) must hold which suggests adding a name for the type variable 'ex7#, and gives the property in terms of the variable n. If we give n a type variable name: ``` val test : int -> unit function test(n as 'N) = { let y = aget_X(n); () } ``` It will suggest a constraint involving the type variable name > Could not resolve quantifiers for aget_X (0 <= 'ex6# & 'ex6# <= 31) > > Try adding the constraint (0 <= 'N & 'N <= 31)
2018-10-29Pretty printer tweaks for ASL parserAlasdair Armstrong
No longer remove braces around singleton expressions, as this can produce unreadably long lines in ASL parser output when assignments are converted to lets. Add brackets around as-patterns for type-variables
2018-10-24Add constraint synonymsAlasdair Armstrong
Currently not enabled by default, the flag -Xconstraint_synonyms enables them For generating constraints in ASL parser, we want to be able to give names to the constraints that we attach to certain variables. It's slightly awkward right now when constraints get long complicated because the entire constraint always has to be typed out in full whenever it appears, and there's no way to abstract away from that. This adds constraint synonyms, which work much like type synonyms except for constraints, e.g. constraint Size('n) = 'n in {1, 2, 4, 8} | 128 <= 'n <= 256 these constraints can then be used instead of the full constraint, e.g. val f : forall 'n, where Size('n). int('n) -> unit Unfortunatly we need to have a keyword to 'call' the constraint synonym otherwise the grammer stops being LR(1). This could be resolved by parsing all constraints into Parse_ast.atyp and then de-sugaring them into constraints, which is what happens for n-expressions already, but that would require quite a bit of work on the parser. To avoid this forcing changes to any other parts of Sail, the intended invariant is that all constraints appearing anywhere in a type-checked AST have no constraint synonyms, so they don't have to worry about matching on NC_app, or calling Env.expand_typquant_synonyms (which isn't even exported for this reason).
2018-10-22Coq: use function type more carefully in untuplingBrian Campbell
And update the RISC-V patch accordingly.
2018-10-22Coq: work around constructors with tupled argumentsBrian Campbell