Commit Graph

886 Commits

Author SHA1 Message Date
Dan Gohman
5e99a4fb6a Simplify a pattern-match. 2017-08-30 14:53:39 -07:00
Dan Gohman
0cc8bd06cd Remove unnecessary () values. 2017-08-30 14:53:34 -07:00
Dan Gohman
8647b10135 Loop over references to containers instead of using explicit iteration methods.
https://github.com/rust-lang-nursery/rust-clippy/wiki#explicit_iter_loop
2017-08-30 14:52:17 -07:00
Dan Gohman
03698f6bc8 Use slices rather than Vec borrows.
https://github.com/rust-lang-nursery/rust-clippy/wiki#ptr_arg
2017-08-30 14:48:17 -07:00
Dan Gohman
01744d6f65 Avoid unneeded return keywords. 2017-08-30 14:46:48 -07:00
Dan Gohman
3532c3533a Teach simple_gvn that iconst.i32 is not congruent to iconst.i64. 2017-08-30 14:33:54 -07:00
Dan Gohman
dcb65b59c1 Remove an unnecessary mut, fixing a compiler warning. 2017-08-30 09:10:08 -07:00
Dan Gohman
b2fcb1ad17 Change translate_module to use a slice rather than a borrowed Vec.
This makes it more convenient to call from a cargo-fuzz fuzzer.
2017-08-30 09:10:08 -07:00
Dan Gohman
5303e7708b Handle wasmparser errors gracefully. 2017-08-30 09:10:08 -07:00
Jakob Stoklund Olesen
0deaa616a3 Record identity assignments in regalloc constraint solver.
Fixes #147.

The Solver::reassign_in() method would previously not record fixed
register assignments for values that are already in the correct
register. The register would simply be marked as unavailable for the
solver.

This did have the effect of tripping up the sanity checks in
Solver::add_var() when that method was called with such a "reassigned"
value. The function can be called for a value that already has a fixed
assignment, but the sanity checks want to make sure the variable
constraints are compatible with the existing fixed assignment. When no
such assignment could be found, the method panicked.

To fix this, make sure that even identity reassignments are recorded
in the assignments vector. Instead, filter the identity assignments out
before scheduling a move sequence for the assignments.

Also add some debug tracing to the regalloc solver.
2017-08-29 10:45:33 -07:00
Dan Gohman
c380df1d04 Eliminate a heap allocation. 2017-08-29 05:44:40 -07:00
Dan Gohman
4afa5df3b6 Remove the last_inst_return field.
It's not necessary to explicitly track whether the last instruction is a
return; if the builder for the last block isn't filled by the time we reach
the end, it needs a return to fill it.
2017-08-29 05:09:25 -07:00
Dan Gohman
ea1d053831 Simplify the "am I in unreachable code" predicate.
The phantom unreachable stack is only used when the real unreachable stack is
active, so it's sufficient to check whether the real unreachable stack is empty.
2017-08-29 03:36:38 -07:00
Dan Gohman
c71d4fc01b Remove a stale comment. 2017-08-29 03:30:22 -07:00
Dan Gohman
f905dc914b Enable missing_docs errors in the wasm crate.
This adds `#![deny(missing_docs)]` to the wasm crate, and adds documentation
to several struct and enum fields, as needed.
2017-08-28 17:07:28 -07:00
Denis Merigoux
ee9989c4b9 Dumped code from the wasm2cretonne repo.
Integrated wasm test suite translation as cretonne test

Fixes #146.
Fixes #143.
2017-08-28 15:57:43 -07:00
Jakob Stoklund Olesen
2201e6249e Add Intel encodings for brz.b1 and brnz.b1.
Use these encodings to test trapz.b1 and trapnz.b1.

When a b1 value is stored in a register, only the low 8 bits are valid.
This is so we can use the various setCC instructions to generate the b1
registers.
2017-08-28 14:56:11 -07:00
Jakob Stoklund Olesen
217434b474 Add custom legalization for conditional traps.
The expansion of these instructions requires the CFG to be modified,
something the Python XForms can't yet do.
2017-08-28 11:19:42 -07:00
Jakob Stoklund Olesen
6d9198d55f Recompute the dominator tree on demand.
The legalizer can invalidate the dominator tree, but we don't actually
need a dominator tree during legalization, so defer the construction of
the domtree.

- Add an "invalid" state to the dominator tree along with clear() and
  is_valid() methods to test it.
- Invalidate the dominator tree as part of legalization.
- Ensure that a valid dominator tree exists before the passes that need
  it.

Together these features add up to a manual invalidation mechanism for
the dominator tree.
2017-08-28 11:16:29 -07:00
Jakob Stoklund Olesen
fecbcbb7b4 Drop the domtree argument to legalize_function().
Future legalization patterns will have the ability to mutate the
flowgraph, so the domtree's list of RPO blocks is not a good guide for
iteration. Use the layout order instead. This will pick up any new EBBs
inserted.
2017-08-25 10:36:25 -07:00
Jakob Stoklund Olesen
aae946128b Add heap_addr custom legalization.
The expansion of a heap_addr instruction depends on the type of heap and
its configuration, so this is handled by custom code.

Add a couple examples of heap access code to the language reference
manual.
2017-08-24 14:44:47 -07:00
Jakob Stoklund Olesen
3b71a27632 Add heaps to the Cretonne IL.
Add preamble syntax for declaring static and dynamic heaps, and update
the langref section on heaps. Add IR support for heap references.

Remove the heap_load and heap_store as discussed in #144. We will use
heap_addr along with native load and store instructions in their place.

Add the heap_addr instruction and document its bounds checking
semantics.
2017-08-23 14:15:59 -07:00
Jakob Stoklund Olesen
a9238eda7a Clean up the documentation for the entity module. 2017-08-18 17:14:31 -07:00
Jakob Stoklund Olesen
9cb0529be4 Move EntityList and SparseMap into the entity module.
These data structures are dependent on EntityRef and EntityMap, so it
makes sense to keep them in the same module.
2017-08-18 16:14:06 -07:00
Jakob Stoklund Olesen
7e08b14cf6 Split EntityMap into entity::PrimaryMap and entity::EntityMap.
The new PrimaryMap replaces the primary EntityMap and the PrimaryEntityData
marker trait which was causing some confusion. We now have a clear
division between the two types of maps:

- PrimaryMap is used to assign entity numbers to the primary data for an
  entity.
- EntityMap is a secondary mapping adding additional info.

The split also means that the secondary EntityMap can now behave as if
all keys have a default value. This means that we can get rid of the
annoying ensure() and get_or_default() methods ther were used everywhere
instead of indexing. Just use normal indexing now; non-existent keys
will return the default value.
2017-08-18 16:04:43 -07:00
Jakob Stoklund Olesen
8599372098 Rename the entity_ref module to 'entity'.
This is in preparation for moving a number of data structures into
sub-modules of the 'entity' module:

- EntityList
- EntityMap
- SparseMap
2017-08-18 15:07:21 -07:00
Jakob Stoklund Olesen
c7b9bc1abf Prefer to use qualified type names in generated code.
Emit type names like ir::Foo instead of just Foo to avoid very long
manual use declarations in files including generated code.
2017-08-18 14:14:23 -07:00
Jakob Stoklund Olesen
6bcb24b3a6 Add a uimm32 operand kind.
We already have a uoffset32 operand kind, but that prints as an offset
with a permanent sign.
2017-08-18 13:07:44 -07:00
Jakob Stoklund Olesen
f2ebabaf5f Custom legalization for global_addr.
The code to compute the address of a global variable depends on the kind
of variable, so custom legalization is required.

- Add a legalizer::globalvar module which exposes an
  expand_global_addr() function. This module is likely to grow as we add
  more types of global variables.
- Add a ArgumentPurpose::VMContext enumerator. This is used to represent
  special 'vmctx' arguments that are used as base pointers for vmctx
  globals.
2017-08-18 10:08:06 -07:00
Jakob Stoklund Olesen
5dba00b761 Add support for custom legalization actions.
The custom_legalize() method on XFormGroup can be used to call a
custom function to legalize specific opcodes.

This will be used shortly to expand global_addr which has an expansion
that depends on the details of the global variable being referenced.
2017-08-17 18:33:53 -07:00
Jakob Stoklund Olesen
4b94ea21ed Switch to a FuncCursor in the top-level legalizer loop.
Stop passing Cursor references to legalizer functions. Give them the
whole &mut Function instead. Given the whole Function reference, these
functions can create their own cursors.

This lets legalizer actions access other Function data structures like
the global variables.
2017-08-17 16:13:15 -07:00
Jakob Stoklund Olesen
5566c99dba Check for global variable deref cycles in the verifier. 2017-08-17 15:11:58 -07:00
Jakob Stoklund Olesen
bf4ae3bb2e Add global variables to Cretonne IL.
See #144 for discussion.

- Add a new GlobalVar entity type both in Python and Rust.
- Define a UnaryGlobalVar instruction format containing a GlobalVar
  reference.
- Add a globalvar.rs module defining the GlobalVarData with support for
  'vmctx' and 'deref' global variable kinds.

Langref:
    Add a section about global variables and the global_addr
    instruction.

Parser:
    Add support for the UnaryGlobalVar instruction format as well as
    global variable declarations in the preamble.
2017-08-17 14:41:27 -07:00
Jakob Stoklund Olesen
7e402a6104 Document memory operation flags.
Also move the extending loads and truncating stores into the bulkier
"Operations" section to improve the flow of the "Memory" section in the
language reference.
2017-08-17 10:42:43 -07:00
d1m0
66da171050 Fix for #141 (#142)
* Add Atom and Literal base classes to CDSL Ast. Change substitution() and copy() on Def/Apply/Rtl to support substituting Var->Union[Var, Literal]. Check in Apply() constructor kinds of passed in Literals respect instruction signature

* Change verify_semantics to check all possible instantiations of enumerated immediates (needed to descrive icmp). Add all bitvector comparison primitives and bvite; Change set_semantics to optionally accept XForms; Add semantics for icmp; Fix typing errors in semantics/{smtlib, elaborate, __init__}.py after the change of VarMap->VarAtomMap

* Forgot macros.py

* Nit obscured by testing with mypy enabled present.

* Typo
2017-08-14 20:19:47 -07:00
Dan Gohman
79d8aa366d Don't perform gvn on instructions with other_side_effects(). 2017-08-14 15:20:19 -07:00
Denis Merigoux
8546cabc8f Verifier now checks it branch target ebbs are inserted in the layout 2017-08-14 08:42:53 -07:00
Jakob Stoklund Olesen
ffae39377c Switch branch relaxation to a FuncCursor. 2017-08-04 16:00:48 -07:00
Jakob Stoklund Olesen
92c3d8f87b Add a FuncCursor type to the cursor library.
A FuncCursor works a like a layout cursor, but it holds a reference to
the entire function and lets you re-borrow the function reference.

Rewrite the dominator tree unit tests with a FuncCursor instead of a
layout cursor to demonstrate the difference. It avoids the constrained
lifetimes of the layout cursor in the tests.
2017-08-04 15:31:08 -07:00
Jakob Stoklund Olesen
e904bff420 Use EncCursor for reload.rs.
Same deal as for spilling. Place an EncCursor in the context and use
that to reference into the IR function when necessary.
2017-08-04 15:02:46 -07:00
Jakob Stoklund Olesen
f15abe7154 Use EncCursor in regalloc/spilling.rs
Use an EncCursor instead of a layout cursor to keep track of the
current position in the function. Since the EncCursor holds a reference
to the whole IR function insteadof just the layout, we can rework how IR
borrowing works.

The Context data structure that's live during the spilling pass now owns
an EncCursor which in turn holds references to the function and ISA.
This means that we no longer need to pass around references to parts of
the ir::Function. We can no longer borrow any part of the IR function
across a context method call, but that turns out to be not necessary.
2017-08-04 14:13:56 -07:00
Jakob Stoklund Olesen
87cee86acb Cursor library.
Add a new cursor module and define an EncCursor data type in it. An
EncCursor is a cursor that inserts instructions with a valid encoding
for the ISA. This is useful for passes generating code after
legalization.

Implement a builder interface via the new InstInserterBase trait such
that the EncCursor builders support with_result().

Use EncCursor in coalescing.rs instead of the layout cursor as a proof
of concept.
2017-08-04 14:05:14 -07:00
Jakob Stoklund Olesen
621abb5026 Reorganize the instruction builder traits.
Leave the primary InstBuilderBase trait alone, but add an alternative
InstInserterBase trait that can be implemented instead by builders that
always allocate new instructions with dfg.make_inst().

Any implementation of InstInserterBase can be used as an instruction
builder by wrapping it in an InsertBuilder. The InsertBuilder type adds
additional functionality via the with_results() method which makes it
possible to override the result values on the instruction that is built.

The motivation for this shuffle is that the with_result() functionality
can now be reused by different kinds of instruction builders, as long as
they insert new instructions. So ReplaceBuilder doesn't get
with_results().
2017-08-04 11:56:03 -07:00
Jakob Stoklund Olesen
aa0c37235a Add CursorBase builder methods.
The CursorBase::at_* are convenience methods for building a cursor that
points to a specific instruction.
2017-08-04 09:08:24 -07:00
Jakob Stoklund Olesen
dba0df787c Move most Cursor methods into a CursorBase trait.
The Cursor navigation methods all just depend on the cursor's position
and layout reference. Make a CursorBase trait that provides access to
this information with methods and implement the navigation methods on
top of that.

This makes it possible to have multiple types implement the cursor
interface.
2017-08-04 09:08:24 -07:00
Jakob Stoklund Olesen
f175882030 Avoid evaluating dbg!() arguments in a closure.
The dbg!() macro should behave like a function call in how it evaluates
its arguments, and captures by Rust closures are not fully compatible
with path-specific borrowing. Specifically:

    let borrow = &mut obj.foo;
    dbg!("{}", obj.bar);

would fail because the closure inside dbg!() would borrow all of obj
instead of just obj.foo.

Fix this by using the format_args!() macro to evaluate the dbg!()
arguments and produce an fmt::Arguments object which can be safely
passed to the thread-local closure for printing.

The arguments are still evaluated inside an if { .. } which
constant-folds away in release builds.
2017-08-04 08:54:00 -07:00
Denis Merigoux
05ba8dcab6 Added partial recompute of dominator tree in case of Ebb splitting (#135)
* Partial recompute for dominator tree in case of ebb splitting
Implemented via striding in RPO numbers
2017-08-03 18:26:41 -07:00
Jakob Stoklund Olesen
92392c6041 Add a prologue_epilogue() hook to TargetIsa.
This will compute the stack frame layout as appropriate for the
function's calling convention and insert prologue and epilogue code.

The default implementation is not useful, each target ISA will need to
override this function.
2017-08-03 13:48:30 -07:00
Jakob Stoklund Olesen
39cc7efc2d Move the stack layout computation into its own module.
This is trying to keep algorithms out if the ir module which deals with
the intermediate representation.

Also give the layout_stack() function a Result return value so it can
report a soft error when the stack frame is too large instead of
asserting. Since local variables can be arbitrarily large, it is easy
enough to overflow the stack with even a small function.
2017-08-03 13:31:58 -07:00
Jakob Stoklund Olesen
c96d4daa20 Add a calling convention to all function signatures.
A CallConv enum on every function signature makes it possible to
generate calls to functions with different calling conventions within
the same ISA / within a single function.

The calling conventions also serve as a way of customizing Cretonne's
behavior when embedded inside a VM. As an example, the SpiderWASM
calling convention is used to compile WebAssembly functions that run
inside the SpiderMonkey virtual machine.

All function signatures must have a calling convention at the end, so
this changes the textual IL syntax.

Before:

    sig1 = signature(i32, f64) -> f64

After

    sig1 = (i32, f64) -> f64 native
    sig2 = (i32) spiderwasm

When printing functions, the signature goes after the return types:

    function %r1() -> i32, f32 spiderwasm {
    ebb1:
        ...
    }

In the parser, this calling convention is optional and defaults to
"native". This is mostly to avoid updating all the existing test cases
under filetests/. When printing a function, the calling convention is
always included, including for "native" functions.
2017-08-03 11:40:24 -07:00