Commit Graph

31 Commits

Author SHA1 Message Date
Alex Crichton
be85242a3f Expose precise offset information in wasmtime::FrameInfo (#1495)
* Consolidate trap/frame information

This commit removes `TrapRegistry` in favor of consolidating this
information in the `FRAME_INFO` we already have in the `wasmtime` crate.
This allows us to keep information generally in one place and have one
canonical location for "map this PC to some original wasm stuff". The
intent for this is to next update with enough information to go from a
program counter to a position in the original wasm file.

* Expose module offset information in `FrameInfo`

This commit implements functionality for `FrameInfo`, the wasm stack
trace of a `Trap`, to return the module/function offset. This allows
knowing the precise wasm location of each stack frame, instead of only
the main trap itself. The intention here is to provide more visibility
into the wasm source when something traps, so you know precisely where
calls were and where traps were, in order to assist in debugging.
Eventually we might use this information for mapping back to native
source languages as well (given sufficient debug information).

This change makes a previously-optional artifact of compilation always
computed on the cranelift side of things. This `ModuleAddressMap` is
then propagated to the same store of information other frame information
is stored within. This also removes the need for passing a `SourceLoc`
with wasm traps or to wasm trap creation, since the backtrace's wasm
frames will be able to infer their own `SourceLoc` from the relevant
program counters.
2020-04-15 08:00:15 -05:00
iximeow
4cca510085 Windows FPRs preservation (#1216)
Preserve FPRs as required by the Windows fastcall calling convention.

This exposes an implementation limit due to Cranelift's approach to stack layout, which conflicts with expectations Windows makes in SEH layout - functions where the Cranelift user desires fastcall unwind information, that require preservation of an ABI-reserved FPR, that have a stack frame 240 bytes or larger, now produce an error when compiled. Several wasm spectests were disabled because they would trip this limit. This is a temporary constraint that should be fixed promptly.

Co-authored-by: bjorn3 <bjorn3@users.noreply.github.com>
2020-04-10 13:27:20 -07:00
Alex Crichton
c4e90f729c wasmtime: Pass around more contexts instead of fields (#1486)
* wasmtime: Pass around more contexts instead of fields

This commit refactors some wasmtime internals to pass around more
context-style structures rather than individual fields of each
structure. The intention here is to make the addition of fields to a
structure easier to plumb throughout the internals of wasmtime.
Currently you need to edit lots of functions to pass lots of parameters,
but ideally after this you'll only need to edit one or two struct fields
and then relevant locations have access to the information already.

Updates in this commit are:

* `debug_info` configuration is now folded into `Tunables`. Additionally
  a `wasmtime::Config` now holds a `Tunables` directly and is passed
  into an internal `Compiler`. Eventually this should allow for direct
  configuration of the `Tunables` attributes from the `wasmtime` API,
  but no new configuration is exposed at this time.

* `ModuleTranslation` is now passed around as a whole rather than
  passing individual components to allow access to all the fields,
  including `Tunables`.

This was motivated by investigating what it would take to optionally
allow loops and such to get interrupted, but that sort of codegen
setting was currently relatively difficult to plumb all the way through
and now it's hoped to be largely just an addition to `Tunables`.

* Fix lightbeam compile
2020-04-08 19:02:49 -05:00
Benjamin Bouvier
f4c4a84b84 cranelift codegen: pass source locations with external relocations; 2020-04-07 11:52:39 +02:00
Alex Crichton
3b7cb6ee64 Enable jitdump profiling support by default (#1310)
* Enable jitdump profiling support by default

This the result of some of the investigation I was doing for #1017. I've
done a number of refactorings here which culminated in a number of
changes that all amount to what I think should result in jitdump support being
enabled by default:

* Pass in a list of finished functions instead of just a range to
  ensure that we're emitting jit dump data for a specific module rather
  than a whole `CodeMemory` which may have other modules.
* Define `ProfilingStrategy` in the `wasmtime` crate to have everything
  locally-defined
* Add support to the C API to enable profiling
* Documentation added for profiling with jitdump to the book
* Split out supported/unsupported files in `jitdump.rs` to avoid having
  lots of `#[cfg]`.
* Make dependencies optional that are only used for `jitdump`.
* Move initialization up-front to `JitDumpAgent::new()` instead of
  deferring it to the first module.
* Pass around `Arc<dyn ProfilingAgent>` instead of
  `Option<Arc<Mutex<Box<dyn ProfilingAgent>>>>`

The `jitdump` Cargo feature is now enabled by default which means that
our published binaries, C API artifacts, and crates will support
profiling at runtime by default. The support I don't think is fully
fleshed out and working but I think it's probably in a good enough spot
we can get users playing around with it!
2020-03-20 11:44:51 -05:00
Alex Crichton
ba0dc40b2b Handle select relocations while generating trampolines (#1347)
* Handle select relocations while generating trampolines

Trampoline generation for all function signatures exposed a preexisting
bug in wasmtime where trampoline generation occasionally does have
relocations, but it's asserted that trampolines don't generate
relocations, causing a panic. The relocation is currently primarily the
probestack function which happens when functions might have a huge
number of parameters, but not so huge as to blow the wasmparser limit of
how many parameters are allowed.

This commit fixes the issue by handling relocations for trampolines in
the same manner as the rest of the code. Note that dynamically-generated
trampolines via the `Func` API still panic if they have too many
arguments and generate a relocation, but it seems like we can try to fix
that later if the need truly arises.

Closes #1322

* Log trampoline relocations
2020-03-17 16:30:21 -05:00
Andrew Brown
8598295bc4 Remove FPR32; fixes #1303
Until #1306 is resolved (some spilling/regalloc issue with larger FPR register banks), this removes FPR32 support. Only Wasm's `i64x2.mul` was using this register class and that instruction is predicated on AVX512 support; for the time being, that instruction will have to make do with the 16 FPR registers.
2020-03-17 12:46:41 -07:00
Alex Crichton
3e2be43502 Pre-generate trampoline functions (#957)
* Refactor wasmtime_runtime::Export

Instead of an enumeration with variants that have data fields have an
enumeration where each variant has a struct, and each struct has the
data fields. This allows us to store the structs in the `wasmtime` API
and avoid lots of `panic!` calls and various extraneous matches.

* Pre-generate trampoline functions

The `wasmtime` crate supports calling arbitrary function signatures in
wasm code, and to do this it generates "trampoline functions" which have
a known ABI that then internally convert to a particular signature's ABI
and call it. These trampoline functions are currently generated
on-the-fly and are cached in the global `Store` structure. This,
however, is suboptimal for a few reasons:

* Due to how code memory is managed each trampoline resides in its own
  64kb allocation of memory. This means if you have N trampolines you're
  using N * 64kb of memory, which is quite a lot of overhead!

* Trampolines are never free'd, even if the referencing module goes
  away. This is similar to #925.

* Trampolines are a source of shared state which prevents `Store` from
  being easily thread safe.

This commit refactors how trampolines are managed inside of the
`wasmtime` crate and jit/runtime internals. All trampolines are now
allocated in the same pass of `CodeMemory` that the main module is
allocated into. A trampoline is generated per-signature in a module as
well, instead of per-function. This cache of trampolines is stored
directly inside of an `Instance`. Trampolines are stored based on
`VMSharedSignatureIndex` so they can be looked up from the internals of
the `ExportFunction` value.

The `Func` API has been updated with various bits and pieces to ensure
the right trampolines are registered in the right places. Overall this
should ensure that all trampolines necessary are generated up-front
rather than lazily. This allows us to remove the trampoline cache from
the `Compiler` type, and move one step closer to making `Compiler`
threadsafe for usage across multiple threads.

Note that as one small caveat the `Func::wrap*` family of functions
don't need to generate a trampoline at runtime, they actually generate
the trampoline at compile time which gets passed in.

Also in addition to shuffling a lot of code around this fixes one minor
bug found in `code_memory.rs`, where `self.position` was loaded before
allocation, but the allocation may push a new chunk which would cause
`self.position` to be zero instead.

* Pass the `SignatureRegistry` as an argument to where it's needed.

This avoids the need for storing it in an `Arc`.

* Ignore tramoplines for functions with lots of arguments

Co-authored-by: Dan Gohman <sunfish@mozilla.com>
2020-03-12 16:17:48 -05:00
Yury Delendik
f76b36f737 Write .debug_frame information (#53)
* Write .debug_frame information

* mv map_reg
2020-03-11 10:22:51 -05:00
Andrew Brown
1d15054310 Remove the debug crate's hard-coded dependency on register ordering 2020-03-06 10:53:22 -08:00
Alex Crichton
c8ab1e293e Improve robustness of cache loading/storing (#974)
* Improve robustness of cache loading/storing

Today wasmtime incorrectly loads compiled compiled modules from the
global cache when toggling settings such as optimizations. For example
if you execute `wasmtime foo.wasm` that will cache globally an
unoptimized version of the wasm module. If you then execute `wasmtime -O
foo.wasm` it would then reload the unoptimized version from cache, not
realizing the compilation settings were different, and use that instead.
This can lead to very surprising behavior naturally!

This commit updates how the cache is managed in an attempt to make it
much more robust against these sorts of issues. This takes a leaf out of
rustc's playbook and models the cache with a function that looks like:

    fn load<T: Hash>(
        &self,
        data: T,
        compute: fn(T) -> CacheEntry,
    ) -> CacheEntry;

The goal here is that it guarantees that all the `data` necessary to
`compute` the result of the cache entry is hashable and stored into the
hash key entry. This was previously open-coded and manually managed
where items were hashed explicitly, but this construction guarantees
that everything reasonable `compute` could use to compile the module is
stored in `data`, which is itself hashable.

This refactoring then resulted in a few workarounds and a few fixes,
including the original issue:

* The `Module` type was split into `Module` and `ModuleLocal` where only
  the latter is hashed. The previous hash function for a `Module` left
  out items like the `start_func` and didn't hash items like the imports
  of the module. Omitting the `start_func` was fine since compilation
  didn't actually use it, but omitting imports seemed uncomfortable
  because while compilation didn't use the import values it did use the
  *number* of imports, which seems like it should then be put into the
  cache key. The `ModuleLocal` type now derives `Hash` to guarantee that
  all of its contents affect the hash key.

* The `ModuleTranslationState` from `cranelift-wasm` doesn't implement
  `Hash` which means that we have a manual wrapper to work around that.
  This will be fixed with an upstream implementation, since this state
  affects the generated wasm code. Currently this is just a map of
  signatures, which is present in `Module` anyway, so we should be good
  for the time being.

* Hashing `dyn TargetIsa` was also added, where previously it was not
  fully hashed. Previously only the target name was used as part of the
  cache key, but crucially the flags of compilation were omitted (for
  example the optimization flags). Unfortunately the trait object itself
  is not hashable so we still have to manually write a wrapper to hash
  it, but we likely want to add upstream some utilities to hash isa
  objects into cranelift itself. For now though we can continue to add
  hashed fields as necessary.

Overall the goal here was to use the compiler to expose what we're not
hashing, and then make sure we organize data and write the right code to
ensure everything is hashed, and nothing more.

* Update crates/environ/src/module.rs

Co-Authored-By: Peter Huene <peterhuene@protonmail.com>

* Fix lightbeam

* Fix compilation of tests

* Update the expected structure of the cache

* Revert "Update the expected structure of the cache"

This reverts commit 2b53fee426a4e411c313d8c1e424841ba304a9cd.

* Separate the cache dir a bit

* Add a test the cache is busted with opt levels

* rustfmt

Co-authored-by: Peter Huene <peterhuene@protonmail.com>
2020-02-26 16:18:02 -06:00
Johnnie Birch
9c6150b103 Adds perf jitdump support (#360)
Patch adds support for the perf jitdump file specification.
With this patch it should be possible to see profile data for code
generated and maped at runtime. Specifically the patch adds support
for the JIT_CODE_LOAD and the JIT_DEBUG_INFO record as described in
the specification. Dumping jitfiles is enabled with the --jitdump
flag. When the -g flag is also used there is an attempt to dump file
and line number information where this option would be most useful
when the WASM file already includes DWARF debug information.

The generation of the jitdump files has been tested on only a few wasm
files. This patch is expected to be useful/serviceable where currently
there is no means for jit profiling, but future patches may benefit
line mapping and add support for additional jitdump record types.

Usage Example:
Record
  sudo perf record -k 1 -e instructions:u target/debug/wasmtime -g
  --jitdump test.wasm
Combine
  sudo perf inject -v -j -i perf.data -o perf.jit.data
Report
  sudo perf report -i perf.jit.data -F+period,srcline
2020-02-21 08:30:21 -06:00
Alex Crichton
16affacafb Generate trampolines based on signatures (#947)
* Generate trampolines based on signatures

Instead of generating a trampoline-per-function generate a
trampoline-per-signature. This should hopefully greatly increase the
cache hit rate on trampolines within a module and avoid generating a
function-per-function.

* Update crates/runtime/src/traphandlers.rs

Co-Authored-By: Sergei Pepyakin <s.pepyakin@gmail.com>

Co-authored-by: Sergei Pepyakin <s.pepyakin@gmail.com>
2020-02-18 12:32:52 -06:00
Nick Fitzgerald
2af544de8b Update to cranelift 0.58.0 and enable (but ignore) reference types and bulk memory tests (#926)
* Update cranelift to 0.58.0

* Update `wasmprinter` dep to require 0.2.1

We already had it in the lock file, but this ensures we won't ever go back down.

* Ensure that our error messages match `assert_invalid`'s

The bulk of this work was done in
https://github.com/bytecodealliance/wasmparser/pull/186 but now we can test it
at the `wasmtime` level as well.

Fixes #492

* Stop feeling guilty about not matching `assert_malformed` messages

Remove the "TODO" and stop printing warning messages. These would just be busy
work to implement, and getting all the messages the exact same relies on using
the same structure as the spec interpreter's parser, which means that where you
have a helper function and they don't, then things go wrong, and vice versa. Not
worth it.

Fixes #492

* Enable (but ignore) the reference-types proposal tests

* Match test suite directly, instead of roundabout starts/endswith

* Enable (but ignore) bulk memory operations proposal test suite
2020-02-07 16:47:55 -06:00
Alex Crichton
f5b505de04 Remove the jit_function_registry global state (#915)
* Remove the `jit_function_registry` global state

This commit removes on the final pieces of global state in wasmtime
today, the `jit_function_registry` module. The purpose of this module is
to help translate a native backtrace with native program counters into a
wasm backtrace with module names, function names, and wasm module
indices. To that end this module retained a global map of function
ranges to this metadata information for each compiled function.

It turns out that we already had a `NAMES` global in the `wasmtime`
crate for symbolicating backtrace addresses, so this commit moves that
global into its own file and restructures the internals to account for
program counter ranges as well. The general set of changes here are:

* Remove `jit_function_registry`
* Remove `NAMES`
* Create a new `frame_info` module which has a singleton global
  registering compiled module's frame information.
* Update traps to use the `frame_info` module to symbolicate pcs,
  directly extracting a `FrameInfo` from the module.
* Register and unregister information on a module level instead of on a
  per-function level (at least in terms of locking granluarity).

This commit leaves the new `FRAME_INFO` global variable as the only
remaining "critical" global variable in `wasmtime`, which only exists
due to the API of `Trap` where it doesn't take in any extra context when
capturing a stack trace through which we could hang off frame
information. I'm thinking though that this is ok, and we can always
tweak the API of `Trap` in the future if necessary if we truly need to
accomodate this.

* Remove a lazy_static dep

* Add some comments and restructure
2020-02-07 07:33:21 -06:00
Alex Crichton
70345aff31 Remove all global state from the caching system (#863)
* Remove all global state from the caching system

This commit is a continuation of an effort to remove usages of
`lazy_static!` and similar global state macros which can otherwise be
accomodated with passing objects around. Previously there was a global
cache system initialized per-process, but it was initialized in a bit of
a roundabout way and wasn't actually reachable from the `wasmtime` crate
itself. The changes here remove all global state, refactor many of the
internals in the cache system, and makes configuration possible through
the `wasmtime` crate.

Specifically some changes here are:

* Usage of `lazy_static!` and many `static` items in the cache module
  have all been removed.
* Global `cache_config()`, `worker()`, and `init()` functions have all
  been removed. Instead a `CacheConfig` is a "root object" which
  internally owns its worker and passing around the `CacheConfig` is
  required for cache usage.
* The `wasmtime::Config` structure has grown options to load and parse
  cache files at runtime. Currently only loading files is supported,
  although we can likely eventually support programmatically configuring
  APIs as well.
* Usage of the `spin` crate has been removed and the dependency is removed.
* The internal `errors` field of `CacheConfig` is removed, instead
  changing all relevant methods to return a `Result<()>` instead of
  storing errors internally.
* Tests have all been updated with the new interfaces and APIs.

Functionally no real change is intended here. Usage of the `wasmtime`
CLI, for example, should still enable the cache by default.

* Fix lightbeam compilation
2020-02-06 13:11:06 -06:00
Alex Crichton
348c597a8e Remove global state for trap registration (#909)
* Remove global state for trap registration

There's a number of changes brought about in this commit, motivated by a
few things. One motivation was to remove an instance of using
`lazy_static!` in an effort to remove global state and encapsulate it
wherever possible. A second motivation came when investigating a
slowly-compiling wasm module (a bit too slowly) where a good chunk of
time was spent in managing trap registrations.

The specific change made here is that `TrapRegistry` is now stored
inside of a `Compiler` instead of inside a global. Additionally traps
are "bulk registered" for a module rather than one-by-one. This form of
bulk-registration allows optimizing the locks used here, where a lock is
only held for a module at-a-time instead of once-per-function.

With these changes the "unregister" logic has also been tweaked a bit
here and there to continue to work. As a nice side effect the `Compiler`
type now has one fewer field that requires actual mutability and has
been updated for multi-threaded compilation, nudging us closer to a
world where we can support multi-threaded compilation. Yay!

In terms of performance improvements, a local wasm test file that
previously took 3 seconds to compile is now 10% faster to compile,
taking ~2.7 seconds now.

* Perform trap resolution after unwinding

This avoids taking locks in signal handlers which feels a bit iffy...

* Remove `TrapRegistration::dummy()`

Avoid an case where you're trying to lookup trap information from a
dummy module for something that happened in a different module.

* Tweak some comments
2020-02-06 12:40:50 -06:00
Yury Delendik
4599234c6f Don't generate DWARF sections when no functions were compiled. (#894) 2020-02-03 14:41:29 -06:00
Alex Crichton
3db1074c15 Improve handling of strings for backtraces (#843)
* Improve handling of strings for backtraces

Largely avoid storing strings at all in the `wasmtime-*` internal
crates, and instead only store strings in a separate global cache
specific to the `wasmtime` crate itself. This global cache is inserted
and removed from dynamically as modules are created and deallocated, and
the global cache is consulted whenever a `Trap` is created to
symbolicate any wasm frames.

This also avoids the need to thread `module_name` through the jit crates
and back, and additionally removes the need for `ModuleSyncString`.

* Run rustfmt
2020-01-24 11:53:55 -06:00
Alex Crichton
e5af0ae3de Move the Store::signature_cache field (#847)
This commit removes the `signature_cache` field from the `Store` type
and performs a few internal changes which are aimed to be a bit forward
looking towards #777, making `Store` threadsafe.

The changes made here are:

* The `SignatureRegistry` internal type now contains the reverse map
  that `signature_cache` was serving to do. This is populated on calls
  to `register` automatically and is accompanied by a `lookup` method as
  well.

* The `register_wasmtime_signature` and `lookup_wasmtime_signature`
  methods were removed from `Store` and now instead work by using the
  `Compiler::signatures` field.

* The `SignatureRegistry` type was updated to have interior mutability.
  The global `Compiler` type is highly likely to get shared across many
  threads through `Store`, so it needs some form of lock somewhere for
  mutation of the registry of signatures and this commit opts to put it
  inside `SignatureRegistry` which will eventually allow for the removal
  of most `&mut self` method on `Compiler`.
2020-01-22 14:54:55 -06:00
Dan Gohman
9a88d3d894 Replace the global-exports mechanism with a caller-vmctx mechanism. (#789)
* Replace the global-exports mechanism with a caller-vmctx mechanism.

This eliminates the global exports mechanism, and instead adds a
caller-vmctx argument to wasm functions so that WASI can obtain the
memory and other things from the caller rather than looking them up in a
global registry.

This replaces #390.

* Fixup some merge conflicts

* Rustfmt

* Ensure VMContext is aligned to 16 bytes

With the removal of `global_exports` it "just so happens" that this
isn't happening naturally any more.

* Fixup some bugs with double vmctx in wasmtime crate

* Trampoline stub needed adjusting
* Use pointer type instead of always using I64 for caller vmctx
* Don't store `ir::Signature` in `Func` since we don't know the pointer
  size at creation time.
* Skip the first 2 arguments in IR signatures since that's the two vmctx
  parameters.

* Update cranelift to 0.56.0

* Handle more merge conflicts

* Rustfmt

Co-authored-by: Alex Crichton <alex@alexcrichton.com>
2020-01-21 14:50:59 -08:00
Yury Delendik
b2bfb98f1f Provide proper function index and name in the FrameInfo (#824)
* fix function index

* Add function name to JITFunctionTag

* Add ModuleSyncString.
2020-01-16 12:36:51 -06:00
Yury Delendik
2a50701f0a Backtrace WebAssembly function JIT frames (#759)
* Create backtrace

* Extend unwind information with FDE data.

* Expose backtrace via API/Trap

* wasmtime_call returns not-str

* Return Arc<JITFrameTag>

* rename frame -> function

* Fix windows crashes and unwrap UNWIND_HISTORY_TABLE

* mmaps -> entries

* pass a backtrace in ActionOutcome

* add test_trap_stack_overflow

* Update cranelift version.
2020-01-15 13:48:24 -06:00
XAMPPRocky
907e7aac01 Clippy fixes (#692) 2019-12-24 12:50:07 -08:00
Yury Delendik
cc6e8e1af2 Move cranelift dependencies to wasmtime-environ (#669)
Groups all CL data structures into single dependency to be used accross wasmtime project.
2019-12-05 16:07:34 -06:00
data-pup
d3f3aa04d7 misc. cleanup 2019-11-26 17:02:15 -05:00
data-pup
4f47a4f607 only collect functions if defined memories exist 2019-11-26 17:02:15 -05:00
data-pup
bbea2855be wip - fix #636, check memory before calculating offset 2019-11-26 17:02:15 -05:00
Alex Crichton
39e57e3e9a Migrate back to std:: stylistically (#554)
* Migrate back to `std::` stylistically

This commit moves away from idioms such as `alloc::` and `core::` as
imports of standard data structures and types. Instead it migrates all
crates to uniformly use `std::` for importing standard data structures
and types. This also removes the `std` and `core` features from all
crates to and removes any conditional checking for `feature = "std"`

All of this support was previously added in #407 in an effort to make
wasmtime/cranelift "`no_std` compatible". Unfortunately though this
change comes at a cost:

* The usage of `alloc` and `core` isn't idiomatic. Especially trying to
  dual between types like `HashMap` from `std` as well as from
  `hashbrown` causes imports to be surprising in some cases.
* Unfortunately there was no CI check that crates were `no_std`, so none
  of them actually were. Many crates still imported from `std` or
  depended on crates that used `std`.

It's important to note, however, that **this does not mean that wasmtime
will not run in embedded environments**. The style of the code today and
idioms aren't ready in Rust to support this degree of multiplexing and
makes it somewhat difficult to keep up with the style of `wasmtime`.
Instead it's intended that embedded runtime support will be added as
necessary. Currently only `std` is necessary to build `wasmtime`, and
platforms that natively need to execute `wasmtime` will need to use a
Rust target that supports `std`. Note though that not all of `std` needs
to be supported, but instead much of it could be configured off to
return errors, and `wasmtime` would be configured to gracefully handle
errors.

The goal of this PR is to move `wasmtime` back to idiomatic usage of
features/`std`/imports/etc and help development in the short-term.
Long-term when platform concerns arise (if any) they can be addressed by
moving back to `no_std` crates (but fixing the issues mentioned above)
or ensuring that the target in Rust has `std` available.

* Start filling out platform support doc
2019-11-18 22:04:06 -08:00
Andrew Brown
ea04aa5b98 Improve error messages received from Cranelift (#583)
As discussed in https://github.com/bytecodealliance/cranelift/pull/1226, the context of Cranelift errors is lost after exiting the scope containing the Cranelift function. `CodegenError` then only contains something like `inst2: arg 0 (v4) has type i16x8, expected i8x16`, which is rarely enough information for investigating a codegen failure. This change uses Cranelift's `pretty_error` function to improve the error messages wrapped in `CompileError`; `CompileError` has lost the reference to `CodegenError` due to `pretty_error` taking ownership but this seems preferable since no backtrace is attached and losing the pretty-printed context would be worse (if `CodegenError` gains a `Backtrace` or implements `Clone` we can revisit this).
2019-11-16 11:42:17 -08:00
Dan Gohman
22641de629 Initial reorg.
This is largely the same as #305, but updated for the current tree.
2019-11-08 06:35:40 -08:00