Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Single-pass native code generation for x86-64 using dynasm. #276

Merged
merged 112 commits into from
Mar 21, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
112 commits
Select commit Hold shift + click to select a range
9649219
Initial work on WebAssembly parser for Dynasm backend.
losfair Feb 8, 2019
f735471
Merge remote-tracking branch 'private/master' into feature/dynasm-bac…
losfair Feb 11, 2019
af19f5c
Update dependencies.
losfair Feb 11, 2019
bbb27be
Code generation framework.
losfair Feb 11, 2019
ffc1bde
Cleanup & add imports.
losfair Feb 11, 2019
2fbb5e3
Codegen backend for x64.
losfair Feb 11, 2019
4ebb22f
Calling conventions, value stack, and runtime stack layout.
losfair Feb 12, 2019
a69c5b4
stack: Helper functions and unified return types
losfair Feb 13, 2019
43df3dd
Use System V calling convention and implement a few opcodes.
losfair Feb 13, 2019
7df7204
codegen: More opcodes
losfair Feb 13, 2019
8d8db4a
Starting integration.
losfair Feb 13, 2019
1526d35
Emit a Return opcode if the last one is not return.
losfair Feb 14, 2019
bb52a4e
Now we can run `add`!
losfair Feb 14, 2019
5583e96
Mitigate a bug that causes incorrect code generation.
losfair Feb 19, 2019
93d2713
Operators.
losfair Feb 19, 2019
61c8350
Control frames, jumps & stack unwinding.
losfair Feb 20, 2019
aaabbf1
Operator::Br and control stack fixes
losfair Feb 20, 2019
6f97ebd
Remove a hack in parser.
losfair Feb 21, 2019
63b3f41
Handle unreachable and fix return.
losfair Feb 21, 2019
7c43993
Block and conditional branch.
losfair Feb 21, 2019
08a2ec8
Unary operators, comparison opcodes, loops, etc.
losfair Feb 22, 2019
693c9fd
Single-pass backend tests.
losfair Feb 22, 2019
e9c0325
Update dependencies
losfair Feb 23, 2019
09cbd4a
Changed to using custom calling conventions; Implemented direct calls.
losfair Feb 23, 2019
b2f5f77
Add direct call test
losfair Feb 23, 2019
dbebdf9
Code generation for br_table.
losfair Feb 24, 2019
2432a6c
Fix function calls.
losfair Feb 25, 2019
da1a3fa
Add test for br_table.
losfair Feb 25, 2019
80812e3
Implement native call & fix stack alignment.
losfair Feb 25, 2019
78fd995
Fix argument passing at entry.
losfair Feb 25, 2019
b18595f
Pass command-line arguments to wasm as i32.
losfair Feb 25, 2019
5302949
Allow more registers to be used.
losfair Feb 25, 2019
9d8c5a5
Add a note on incorrect code generation.
losfair Feb 25, 2019
3c3c5db
Native trampolines.
losfair Feb 26, 2019
d50f1cc
If/Else.
losfair Feb 27, 2019
ec9a8f0
Add test for if/else.
losfair Feb 27, 2019
b7ca5e4
Add Select opcode.
losfair Feb 28, 2019
adb309f
Add select test.
losfair Feb 28, 2019
64142c4
Reserve R15.
losfair Feb 28, 2019
e026adf
Initial work on linear memory.
losfair Feb 28, 2019
aa75994
Add memory opcodes and test.
losfair Mar 1, 2019
2962fe2
Add unwinding test.
losfair Mar 1, 2019
fa61b66
Strongly type scratch registers and fixed an unwinding issue.
losfair Mar 4, 2019
bd7698e
64-bit operators.
losfair Mar 4, 2019
5a97a25
Add basic test for i64.
losfair Mar 4, 2019
27b2061
Implemented missing integer operators and fixed division.
losfair Mar 5, 2019
8d2e877
tee_local and div tests
losfair Mar 5, 2019
12c2137
Hack around calling imports. Not yet working.
losfair Mar 7, 2019
258dea6
Fix calling imports.
losfair Mar 8, 2019
4c4743e
Globals.
losfair Mar 8, 2019
3efccbe
Support imported globals.
losfair Mar 8, 2019
25034ec
Almost finished indirect calls.
losfair Mar 8, 2019
c6dfbcd
Add tests.
losfair Mar 8, 2019
c5ef0a9
Update vm::Ctx.
losfair Mar 8, 2019
683cb20
Fix call_indirect.
losfair Mar 12, 2019
c3b0bd7
Validate return values in indirect call test.
losfair Mar 12, 2019
1fc7b31
Add missing trait items to DynasmCompiler so that cargo build --all w…
bjfish Mar 13, 2019
557be77
Merge branch 'master' into feature/dynasm-backend
bjfish Mar 13, 2019
a5bab8c
Updates to compile dynasm after merge from master
bjfish Mar 13, 2019
68181ac
Add dynasm to spectests
bjfish Mar 13, 2019
d4ded2c
Fix bugs found when running spectests.
losfair Mar 13, 2019
179bbf9
Fix integer division.
losfair Mar 14, 2019
e5d67c9
Add dynasm feature to emscripten tests
bjfish Mar 14, 2019
d80ea47
FIx bugs found with spectests.
losfair Mar 14, 2019
c76887d
Merge remote-tracking branch 'private/feature/dynasm-backend' into fe…
losfair Mar 14, 2019
592c3fb
Fixes and some floating point operations.
losfair Mar 14, 2019
4d2b6a0
Add Copy + Clone for IfElseState
losfair Mar 14, 2019
1104073
Implemented more floating point operations.
losfair Mar 14, 2019
1b5ea9b
Passes all `assert_return(_*)` tests.
losfair Mar 14, 2019
53a8fca
Make wasmer executable work with dynasm
syrusakbary Mar 16, 2019
81af8cf
Fixed several bugs in the single-pass backend and implemented a runti…
losfair Mar 16, 2019
1f8c644
Merge remote-tracking branch 'private/feature/dynasm-backend' into fe…
losfair Mar 16, 2019
f8fe999
Implemented protected call and floating point traps; passing all spec…
losfair Mar 17, 2019
d8d39c3
Fix warnings.
losfair Mar 17, 2019
7394df2
FIx floating point trunc's.
losfair Mar 17, 2019
08f4526
Merge remote-tracking branch 'origin/master' into feature/dynasm-backend
losfair Mar 17, 2019
fcfde73
Use R15 as temporary register.
losfair Mar 17, 2019
337b2eb
Add dynasm tests to the Makefile
bjfish Mar 17, 2019
99faa79
Run cargo fmt.
losfair Mar 17, 2019
6c40ea1
Cargo fmt more files.
losfair Mar 17, 2019
e2a3887
Merge remote-tracking branch 'private/feature/dynasm-backend' into fe…
losfair Mar 17, 2019
4ca27b6
Manually fix lint errors.
losfair Mar 17, 2019
e48ff02
Remove commented out code.
losfair Mar 17, 2019
c5694ec
Fix lint errors.
losfair Mar 17, 2019
662a649
Only run dynasm tests on nightly.
losfair Mar 17, 2019
e1cb4fc
Removed submodule cranlift
bjfish Mar 17, 2019
caa239a
Make wasmer-dynasm-backend optional.
losfair Mar 18, 2019
75678b5
Merge remote-tracking branch 'origin/feature/dynasm-backend' into fea…
losfair Mar 18, 2019
b94c046
Remove println.
losfair Mar 18, 2019
af8f307
Fix dependencies.
losfair Mar 18, 2019
cd5c145
Fix default compiler.
losfair Mar 18, 2019
b06a49e
Move wasmer-dynasm-backend out of default-compiler.
losfair Mar 18, 2019
eb606a6
Disable clippy temporarily.
losfair Mar 18, 2019
af24cfc
Exclude dynasm backend in cargo test.
losfair Mar 18, 2019
2ab2205
Allow cross-module indirect calls.
losfair Mar 19, 2019
ebaf2dc
Make DynFunc::func_index private.
losfair Mar 19, 2019
61abe70
cargo fmt
losfair Mar 19, 2019
a006a36
Cleanup.
losfair Mar 19, 2019
14da8ab
Run-time memory bound checking.
losfair Mar 19, 2019
4256ccb
Cleanup & fix need_check condition.
losfair Mar 19, 2019
7ee364a
Cargo fmt.
losfair Mar 19, 2019
fd60631
Remove '+nightly' in Makefile.
losfair Mar 19, 2019
f0e8f22
Merge remote-tracking branch 'origin/master' into feature/dynasm-backend
losfair Mar 19, 2019
82b2034
Run clippy on nightly rust.
losfair Mar 19, 2019
8b85099
Unset global git redirection.
losfair Mar 19, 2019
295efbf
Fix clippy errors.
losfair Mar 19, 2019
01f18b2
Merge remote-tracking branch 'origin/master' into feature/dynasm-backend
losfair Mar 19, 2019
395161a
Merge remote-tracking branch 'origin/master' into feature/dynasm-backend
losfair Mar 20, 2019
cb3846f
Add `InternalCtx`.
losfair Mar 21, 2019
a4ee873
Merge remote-tracking branch 'origin/master' into feature/dynasm-backend
losfair Mar 21, 2019
26e4278
Make the `internal` field private from outside.
losfair Mar 21, 2019
08ba696
Fix vmctx offset tests.
losfair Mar 21, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 23 additions & 15 deletions lib/dynasm-backend/src/codegen_x64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,12 @@ impl ProtectedCaller for X64ExecutionContext {
msg: "only one linear memory is supported".into(),
});
}
unsafe { ((**(*_vmctx).memories).base, (**(*_vmctx).memories).bound) }
unsafe {
(
(**(*_vmctx).internal.memories).base,
(**(*_vmctx).internal.memories).bound,
)
}
} else if _module.info.imported_memories.len() > 0 {
if _module.info.memories.len() != 0 || _module.info.imported_memories.len() != 1 {
return Err(RuntimeError::Trap {
Expand All @@ -414,8 +419,8 @@ impl ProtectedCaller for X64ExecutionContext {
}
unsafe {
(
(**(*_vmctx).imported_memories).base,
(**(*_vmctx).imported_memories).bound,
(**(*_vmctx).internal.imported_memories).base,
(**(*_vmctx).internal.imported_memories).bound,
)
}
} else {
Expand Down Expand Up @@ -1394,7 +1399,7 @@ impl X64FunctionCode {
}
dynasm!(
assembler
; mov r15, r14 => vm::Ctx.memories
; mov r15, r14 => vm::InternalCtx.memories
);
} else if info.imported_memories.len() > 0 {
if info.memories.len() != 0 || info.imported_memories.len() != 1 {
Expand All @@ -1404,7 +1409,7 @@ impl X64FunctionCode {
}
dynasm!(
assembler
; mov r15, r14 => vm::Ctx.imported_memories
; mov r15, r14 => vm::InternalCtx.imported_memories
);
} else {
return Ok(());
Expand Down Expand Up @@ -1477,7 +1482,7 @@ impl X64FunctionCode {
}
dynasm!(
assembler
; mov rcx, r9 => vm::Ctx.memories
; mov rcx, r9 => vm::InternalCtx.memories
);
true
} else if info.imported_memories.len() > 0 {
Expand All @@ -1488,7 +1493,7 @@ impl X64FunctionCode {
}
dynasm!(
assembler
; mov rcx, r9 => vm::Ctx.imported_memories
; mov rcx, r9 => vm::InternalCtx.imported_memories
);
true
} else {
Expand Down Expand Up @@ -2101,7 +2106,7 @@ impl FunctionCodeGenerator for X64FunctionCode {
if global_index < module_info.imported_globals.len() {
dynasm!(
assembler
; mov rax, r14 => vm::Ctx.imported_globals
; mov rax, r14 => vm::InternalCtx.imported_globals
);
} else {
global_index -= module_info.imported_globals.len();
Expand All @@ -2112,7 +2117,7 @@ impl FunctionCodeGenerator for X64FunctionCode {
}
dynasm!(
assembler
; mov rax, r14 => vm::Ctx.globals
; mov rax, r14 => vm::InternalCtx.globals
);
}

Expand All @@ -2139,7 +2144,7 @@ impl FunctionCodeGenerator for X64FunctionCode {
dynasm!(
assembler
; push rbx
; mov rbx, r14 => vm::Ctx.imported_globals
; mov rbx, r14 => vm::InternalCtx.imported_globals
);
} else {
global_index -= module_info.imported_globals.len();
Expand All @@ -2151,7 +2156,7 @@ impl FunctionCodeGenerator for X64FunctionCode {
dynasm!(
assembler
; push rbx
; mov rbx, r14 => vm::Ctx.globals
; mov rbx, r14 => vm::InternalCtx.globals
);
}

Expand Down Expand Up @@ -5129,7 +5134,7 @@ unsafe extern "C" fn invoke_import(
_memory_base: *mut u8,
) -> u64 {
let vmctx: &mut vm::Ctx = &mut *vmctx;
let import = (*vmctx.imported_funcs.offset(import_id as isize)).func;
let import = (*vmctx.internal.imported_funcs.offset(import_id as isize)).func;

CONSTRUCT_STACK_AND_CALL_NATIVE(stack_top, stack_base, vmctx, import)
}
Expand All @@ -5155,15 +5160,18 @@ unsafe extern "C" fn call_indirect(
assert!(stack_top as usize <= stack_base as usize);

let table: &LocalTable = match local_or_import {
CallIndirectLocalOrImport::Local => &*(*(*vmctx).tables),
CallIndirectLocalOrImport::Import => &*(*(*vmctx).imported_tables),
CallIndirectLocalOrImport::Local => &*(*(*vmctx).internal.tables),
CallIndirectLocalOrImport::Import => &*(*(*vmctx).internal.imported_tables),
};
if elem_index >= table.count as usize {
eprintln!("element index out of bounds");
protect_unix::trigger_trap();
}
let anyfunc = &*(table.base as *mut vm::Anyfunc).offset(elem_index as isize);
let dynamic_sigindex = *(*vmctx).dynamic_sigindices.offset(sig_index as isize);
let dynamic_sigindex = *(*vmctx)
.internal
.dynamic_sigindices
.offset(sig_index as isize);

if anyfunc.func.is_null() {
eprintln!("null anyfunc");
Expand Down
64 changes: 39 additions & 25 deletions lib/runtime-core/src/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,25 @@ use std::{ffi::c_void, mem, ptr};
#[derive(Debug)]
#[repr(C)]
pub struct Ctx {
// `internal` must be the first field of `Ctx`.
pub internal: InternalCtx,
losfair marked this conversation as resolved.
Show resolved Hide resolved

pub(crate) local_functions: *const *const Func,

local_backing: *mut LocalBacking,
import_backing: *mut ImportBacking,
module: *const ModuleInner,

pub data: *mut c_void,
pub data_finalizer: Option<extern "C" fn(data: *mut c_void)>,
}

/// The internal context of the currently running WebAssembly instance.
///
///
#[derive(Debug)]
#[repr(C)]
pub struct InternalCtx {
losfair marked this conversation as resolved.
Show resolved Hide resolved
/// A pointer to an array of locally-defined memories, indexed by `MemoryIndex`.
pub memories: *mut *mut LocalMemory,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it necessary for these to be public outside of the crate?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These fields need to be public to be accessed from the codegen backend. Otherwise we have to access these fields by offsets which is not clean.

Copy link
Contributor

@lachlansneff lachlansneff Mar 19, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ctx has been designed to be usable without falling back on rust. Can you use either offsets or implement it in assembly so that it doesn't need to call rust to do call_indirect?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dynasm provides a quite good feature that computes offset of a struct field automatically by name. Even only for this reason, it's good to keep these fields public.

Also, I prefer to implement cold or large code paths in Rust to improve cleanness and make it less error-prone. Currently the only two functions implemented in assembly are CONSTRUCT_STACK_AND_CALL_NATIVE and CALL_WASM which both does some low-level stuff that converts calling conventions.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Context is exposed to the user of the runtime, so it's not ideal for these internal fields to be public. I'd be okay with making an InternalVmCtx struct that has these fields public, and then is part of the Vmctx struct.


Expand All @@ -39,15 +58,6 @@ pub struct Ctx {
/// signature id. This is used to allow call-indirect to other
/// modules safely.
pub dynamic_sigindices: *const SigId,

pub(crate) local_functions: *const *const Func,

local_backing: *mut LocalBacking,
import_backing: *mut ImportBacking,
module: *const ModuleInner,

pub data: *mut c_void,
pub data_finalizer: Option<extern "C" fn(data: *mut c_void)>,
}

impl Ctx {
Expand All @@ -58,16 +68,18 @@ impl Ctx {
module: &ModuleInner,
) -> Self {
Self {
memories: local_backing.vm_memories.as_mut_ptr(),
tables: local_backing.vm_tables.as_mut_ptr(),
globals: local_backing.vm_globals.as_mut_ptr(),
internal: InternalCtx {
memories: local_backing.vm_memories.as_mut_ptr(),
tables: local_backing.vm_tables.as_mut_ptr(),
globals: local_backing.vm_globals.as_mut_ptr(),

imported_memories: import_backing.vm_memories.as_mut_ptr(),
imported_tables: import_backing.vm_tables.as_mut_ptr(),
imported_globals: import_backing.vm_globals.as_mut_ptr(),
imported_funcs: import_backing.vm_functions.as_mut_ptr(),
imported_memories: import_backing.vm_memories.as_mut_ptr(),
imported_tables: import_backing.vm_tables.as_mut_ptr(),
imported_globals: import_backing.vm_globals.as_mut_ptr(),
imported_funcs: import_backing.vm_functions.as_mut_ptr(),

dynamic_sigindices: local_backing.dynamic_sigindices.as_ptr(),
dynamic_sigindices: local_backing.dynamic_sigindices.as_ptr(),
},
local_functions: local_backing.local_functions.as_ptr(),

local_backing,
Expand All @@ -88,16 +100,18 @@ impl Ctx {
data_finalizer: extern "C" fn(*mut c_void),
) -> Self {
Self {
memories: local_backing.vm_memories.as_mut_ptr(),
tables: local_backing.vm_tables.as_mut_ptr(),
globals: local_backing.vm_globals.as_mut_ptr(),
internal: InternalCtx {
memories: local_backing.vm_memories.as_mut_ptr(),
tables: local_backing.vm_tables.as_mut_ptr(),
globals: local_backing.vm_globals.as_mut_ptr(),

imported_memories: import_backing.vm_memories.as_mut_ptr(),
imported_tables: import_backing.vm_tables.as_mut_ptr(),
imported_globals: import_backing.vm_globals.as_mut_ptr(),
imported_funcs: import_backing.vm_functions.as_mut_ptr(),
imported_memories: import_backing.vm_memories.as_mut_ptr(),
imported_tables: import_backing.vm_tables.as_mut_ptr(),
imported_globals: import_backing.vm_globals.as_mut_ptr(),
imported_funcs: import_backing.vm_functions.as_mut_ptr(),

dynamic_sigindices: local_backing.dynamic_sigindices.as_ptr(),
dynamic_sigindices: local_backing.dynamic_sigindices.as_ptr(),
},
local_functions: local_backing.local_functions.as_ptr(),

local_backing,
Expand Down
22 changes: 14 additions & 8 deletions lib/runtime-core/src/vmcalls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ pub unsafe extern "C" fn local_static_memory_grow(
memory_index: LocalMemoryIndex,
delta: Pages,
) -> i32 {
let local_memory = *ctx.memories.add(memory_index.index());
let local_memory = *ctx.internal.memories.add(memory_index.index());
let memory = (*local_memory).memory as *mut StaticMemory;

match (*memory).grow(delta, &mut *local_memory) {
Expand All @@ -30,7 +30,7 @@ pub unsafe extern "C" fn local_static_memory_size(
ctx: &vm::Ctx,
memory_index: LocalMemoryIndex,
) -> Pages {
let local_memory = *ctx.memories.add(memory_index.index());
let local_memory = *ctx.internal.memories.add(memory_index.index());
let memory = (*local_memory).memory as *mut StaticMemory;

(*memory).size()
Expand All @@ -41,7 +41,7 @@ pub unsafe extern "C" fn local_dynamic_memory_grow(
memory_index: LocalMemoryIndex,
delta: Pages,
) -> i32 {
let local_memory = *ctx.memories.add(memory_index.index());
let local_memory = *ctx.internal.memories.add(memory_index.index());
let memory = (*local_memory).memory as *mut DynamicMemory;

match (*memory).grow(delta, &mut *local_memory) {
Expand All @@ -54,7 +54,7 @@ pub unsafe extern "C" fn local_dynamic_memory_size(
ctx: &vm::Ctx,
memory_index: LocalMemoryIndex,
) -> Pages {
let local_memory = *ctx.memories.add(memory_index.index());
let local_memory = *ctx.internal.memories.add(memory_index.index());
let memory = (*local_memory).memory as *mut DynamicMemory;

(*memory).size()
Expand All @@ -69,7 +69,10 @@ pub unsafe extern "C" fn imported_static_memory_grow(
import_memory_index: ImportedMemoryIndex,
delta: Pages,
) -> i32 {
let local_memory = *ctx.imported_memories.add(import_memory_index.index());
let local_memory = *ctx
.internal
.imported_memories
.add(import_memory_index.index());
let memory = (*local_memory).memory as *mut StaticMemory;

match (*memory).grow(delta, &mut *local_memory) {
Expand All @@ -82,7 +85,10 @@ pub unsafe extern "C" fn imported_static_memory_size(
ctx: &vm::Ctx,
import_memory_index: ImportedMemoryIndex,
) -> Pages {
let local_memory = *ctx.imported_memories.add(import_memory_index.index());
let local_memory = *ctx
.internal
.imported_memories
.add(import_memory_index.index());
let memory = (*local_memory).memory as *mut StaticMemory;

(*memory).size()
Expand All @@ -93,7 +99,7 @@ pub unsafe extern "C" fn imported_dynamic_memory_grow(
memory_index: ImportedMemoryIndex,
delta: Pages,
) -> i32 {
let local_memory = *ctx.imported_memories.add(memory_index.index());
let local_memory = *ctx.internal.imported_memories.add(memory_index.index());
let memory = (*local_memory).memory as *mut DynamicMemory;

match (*memory).grow(delta, &mut *local_memory) {
Expand All @@ -106,7 +112,7 @@ pub unsafe extern "C" fn imported_dynamic_memory_size(
ctx: &vm::Ctx,
memory_index: ImportedMemoryIndex,
) -> Pages {
let local_memory = *ctx.imported_memories.add(memory_index.index());
let local_memory = *ctx.internal.imported_memories.add(memory_index.index());
let memory = (*local_memory).memory as *mut DynamicMemory;

(*memory).size()
Expand Down