Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
alexcrichton committed Dec 1, 2023
1 parent 03a14ac commit 3670f02
Show file tree
Hide file tree
Showing 52 changed files with 823 additions and 446 deletions.
6 changes: 3 additions & 3 deletions crates/asm-macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,12 @@ cfg_if::cfg_if! {
std::arch::global_asm!(
concat!(
".p2align 4\n",
".hidden ", $name, "\n",
//".hidden ", $name, "\n",
".global ", $name, "\n",
$crate::elf_func_type_header!($name),
//$crate::elf_func_type_header!($name),
$name, ":\n",
$body,
".size ", $name, ",.-", $name,
//".size ", $name, ",.-", $name,
)
$(, $($args)*)?
);
Expand Down
1 change: 1 addition & 0 deletions crates/jit/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,4 @@ ittapi = { version = "0.4.0", optional = true }
[features]
profiling = ['dep:wasmtime-jit-debug', 'dep:ittapi']
demangle = ['dep:rustc-demangle', 'dep:cpp_demangle']
debug-builtins = []
4 changes: 1 addition & 3 deletions crates/jit/src/code_memory.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
//! Memory management for executable code.
use crate::subslice_range;
use crate::unwind::UnwindRegistration;
use anyhow::{anyhow, bail, Context, Result};
use object::read::{File, Object, ObjectSection};
use object::ObjectSymbol;
use std::mem::ManuallyDrop;
use std::ops::Range;
use wasmtime_environ::obj;
use wasmtime_jit_icache_coherence as icache_coherence;
use wasmtime_runtime::libcalls;
use wasmtime_runtime::MmapVec;
use wasmtime_runtime::{libcalls, MmapVec, UnwindRegistration};

/// Management of executable memory within a `MmapVec`
///
Expand Down
19 changes: 11 additions & 8 deletions crates/jit/src/instantiate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
//! steps.
use crate::code_memory::CodeMemory;
use crate::debug::create_gdbjit_image;
use crate::profiling::ProfilingAgent;
use anyhow::{bail, Context, Error, Result};
use object::write::{Object, SectionId, StandardSegment, WritableBuffer};
Expand All @@ -19,9 +18,7 @@ use wasmtime_environ::{
DefinedFuncIndex, FuncIndex, FunctionLoc, MemoryInitialization, Module, ModuleTranslation,
PrimaryMap, SignatureIndex, StackMapInformation, Tunables, WasmFunctionInfo,
};
use wasmtime_runtime::{
CompiledModuleId, CompiledModuleIdAllocator, GdbJitImageRegistration, MmapVec,
};
use wasmtime_runtime::{CompiledModuleId, CompiledModuleIdAllocator, MmapVec};

/// Secondary in-memory results of function compilation.
#[derive(Serialize, Deserialize)]
Expand Down Expand Up @@ -426,7 +423,8 @@ pub struct CompiledModule {
wasm_to_native_trampolines: Vec<(SignatureIndex, FunctionLoc)>,
meta: Metadata,
code_memory: Arc<CodeMemory>,
dbg_jit_registration: Option<GdbJitImageRegistration>,
#[cfg(feature = "debug-builtins")]
dbg_jit_registration: Option<wasmtime_runtime::GdbJitImageRegistration>,
/// A unique ID used to register this module with the engine.
unique_id: CompiledModuleId,
func_names: Vec<FunctionName>,
Expand Down Expand Up @@ -459,6 +457,7 @@ impl CompiledModule {
module: Arc::new(info.module),
funcs: info.funcs,
wasm_to_native_trampolines: info.wasm_to_native_trampolines,
#[cfg(feature = "debug-builtins")]
dbg_jit_registration: None,
code_memory,
meta: info.meta,
Expand All @@ -471,11 +470,15 @@ impl CompiledModule {
}

fn register_debug_and_profiling(&mut self, profiler: &dyn ProfilingAgent) -> Result<()> {
#[cfg(feature = "debug-builtins")]
if self.meta.native_debug_info_present {
let text = self.text();
let bytes = create_gdbjit_image(self.mmap().to_vec(), (text.as_ptr(), text.len()))
.context("failed to create jit image for gdb")?;
let reg = GdbJitImageRegistration::register(bytes);
let bytes = crate::debug::create_gdbjit_image(
self.mmap().to_vec(),
(text.as_ptr(), text.len()),
)
.context("failed to create jit image for gdb")?;
let reg = wasmtime_runtime::GdbJitImageRegistration::register(bytes);
self.dbg_jit_registration = Some(reg);
}
profiler.register_module(&self.code_memory, &|addr| {
Expand Down
2 changes: 1 addition & 1 deletion crates/jit/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
#![deny(missing_docs)]

mod code_memory;
#[cfg(feature = "debug-builtins")]
mod debug;
mod demangling;
mod instantiate;
pub mod profiling;
mod unwind;

pub use crate::code_memory::CodeMemory;
#[cfg(feature = "addr2line")]
Expand Down
10 changes: 6 additions & 4 deletions crates/runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,22 @@ wasmtime-wmemcheck = { workspace = true }
wasmtime-asm-macros = { workspace = true }
wasmtime-environ = { workspace = true }
wasmtime-fiber = { workspace = true, optional = true }
wasmtime-jit-debug = { workspace = true, features = ["gdb_jit_int"] }
wasmtime-jit-debug = { workspace = true, features = ["gdb_jit_int"], optional = true }
wasmtime-versioned-export-macros = { workspace = true }
libc = { version = "0.2.112", default-features = false }
log = { workspace = true }
memoffset = "0.9.0"
indexmap = { workspace = true }
cfg-if = { workspace = true }
rand = { version = "0.8.3", features = ['small_rng'] }
anyhow = { workspace = true }
memfd = "0.6.2"
paste = "1.0.3"
encoding_rs = { version = "0.8.31", optional = true }
sptr = "0.3.2"
wasm-encoder = { workspace = true }

[target.'cfg(target_os = "linux")'.dependencies]
memfd = "0.6.2"

[target.'cfg(target_os = "macos")'.dependencies]
mach = "0.3.2"

Expand All @@ -54,6 +55,7 @@ features = [
[dev-dependencies]
once_cell = { workspace = true }
proptest = "1.0.0"
rand = { version = "0.8.3", features = ['small_rng'] }

[build-dependencies]
cc = "1.0"
Expand All @@ -64,4 +66,4 @@ async = ["wasmtime-fiber"]
pooling-allocator = []
component-model = ["wasmtime-environ/component-model", "dep:encoding_rs"]
wmemcheck = []
debug-builtins = []
debug-builtins = ['wasmtime-jit-debug']
11 changes: 10 additions & 1 deletion crates/runtime/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@ use std::env;
use wasmtime_versioned_export_macros::versioned_suffix;

fn main() {
println!("cargo:rerun-if-changed=build.rs");

// If this platform is neither unix nor windows then there's no default need
// for a C helper library since `helpers.c` is tailored for just these
// platforms currently.
if env::var("CARGO_CFG_UNIX").is_err() && env::var("CARGO_CFG_WINDOWS").is_err() {
return;
}

let mut build = cc::Build::new();
build.warnings(true);
let arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
Expand All @@ -11,7 +20,7 @@ fn main() {
build.define("VERSIONED_SUFFIX", Some(versioned_suffix!()));
if arch == "s390x" {
println!("cargo:rerun-if-changed=src/trampolines/s390x.S");
build.file("src/trampolines/s390x.S");
build.file("src/arch/s390x.S");
}
println!("cargo:rerun-if-changed=src/helpers.c");
build.file("src/helpers.c");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,47 @@ pub fn assert_fp_is_aligned(_fp: usize) {
//
// [0]: https://github.com/ARM-software/abi-aa/blob/2022Q1/aapcs64/aapcs64.rst#the-frame-pointer
}

#[rustfmt::skip]
macro_rules! wasm_to_libcall_trampoline {
($libcall:ident ; $libcall_impl:ident) => {
wasmtime_asm_macros::asm_func!(
wasmtime_versioned_export_macros::versioned_stringify_ident!($libcall),
"
.cfi_startproc
bti c
// Load the pointer to `VMRuntimeLimits` in `x9`.
ldur x9, [x0, #8]
// Store the last Wasm FP into the `last_wasm_exit_fp` in the limits.
stur fp, [x9, #24]
// Store the last Wasm PC into the `last_wasm_exit_pc` in the limits.
stur lr, [x9, #32]
// Tail call to the actual implementation of this libcall.
b {}
.cfi_endproc
",
sym $libcall_impl
);
};
}
pub(crate) use wasm_to_libcall_trampoline;

#[cfg(test)]
mod wasm_to_libcall_trampoline_offsets_tests {
use wasmtime_environ::{Module, PtrSize, VMOffsets};

#[test]
fn test() {
let module = Module::new();
let offsets = VMOffsets::new(std::mem::size_of::<*mut u8>() as u8, &module);

assert_eq!(8, offsets.vmctx_runtime_limits());
assert_eq!(24, offsets.ptr.vmruntime_limits_last_wasm_exit_fp());
assert_eq!(32, offsets.ptr.vmruntime_limits_last_wasm_exit_pc());
}
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
//! Wasm-to-libcall trampolines.
cfg_if::cfg_if! {
if #[cfg(target_arch = "x86_64")] {
#[macro_use]
mod x86_64;
pub use x86_64::*;
} else if #[cfg(target_arch = "aarch64")] {
#[macro_use]
mod aarch64;
pub use aarch64::*;
} else if #[cfg(target_arch = "s390x")] {
#[macro_use]
mod s390x;
}else if #[cfg(target_arch = "riscv64")] {
#[macro_use]
pub use s390x::*;
} else if #[cfg(target_arch = "riscv64")] {
mod riscv64;
pub use riscv64::*;
} else {
compile_error!("unsupported architecture");
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,22 @@
pub unsafe fn get_next_older_pc_from_fp(fp: usize) -> usize {
*(fp as *mut usize).offset(1)
}

// And the current frame pointer points to the next older frame pointer.
pub const NEXT_OLDER_FP_FROM_FP_OFFSET: usize = 0;

pub fn reached_entry_sp(fp: usize, entry_sp: usize) -> bool {
fp >= entry_sp
}

pub fn assert_entry_sp_is_aligned(sp: usize) {
assert_eq!(sp % 16, 0, "stack should always be aligned to 16");
}

pub fn assert_fp_is_aligned(fp: usize) {
assert_eq!(fp % 16, 0, "stack should always be aligned to 16");
}

#[rustfmt::skip]
macro_rules! wasm_to_libcall_trampoline {
($libcall:ident ; $libcall_impl:ident) => {
Expand Down Expand Up @@ -28,6 +47,7 @@ macro_rules! wasm_to_libcall_trampoline {
);
};
}
pub(crate) use wasm_to_libcall_trampoline;

#[cfg(test)]
mod wasm_to_libcall_trampoline_offsets_tests {
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,3 +1,26 @@
pub unsafe fn get_next_older_pc_from_fp(fp: usize) -> usize {
// The next older PC can be found in register %r14 at function entry, which
// was saved into slot 14 of the register save area pointed to by "FP" (the
// backchain pointer).
*(fp as *mut usize).offset(14)
}

// The next older "FP" (backchain pointer) was saved in the slot pointed to
// by the current "FP".
pub const NEXT_OLDER_FP_FROM_FP_OFFSET: usize = 0;

pub fn reached_entry_sp(fp: usize, entry_sp: usize) -> bool {
fp > entry_sp
}

pub fn assert_entry_sp_is_aligned(sp: usize) {
assert_eq!(sp % 8, 0, "stack should always be aligned to 8");
}

pub fn assert_fp_is_aligned(fp: usize) {
assert_eq!(fp % 8, 0, "stack should always be aligned to 8");
}

// The implementation for libcall trampolines is in the s390x.S
// file. We provide this dummy definition of wasm_to_libcall_trampoline
// here to make libcalls.rs compile on s390x. Note that this means we
Expand All @@ -6,6 +29,7 @@
macro_rules! wasm_to_libcall_trampoline {
($libcall:ident ; $libcall_impl:ident) => {};
}
pub(crate) use wasm_to_libcall_trampoline;

// The wasm_to_host_trampoline implementation is in the s390x.S
// file, but we still want to have this unit test here.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,45 @@
pub unsafe fn get_next_older_pc_from_fp(fp: usize) -> usize {
// The calling convention always pushes the return pointer (aka the PC of
// the next older frame) just before this frame.
*(fp as *mut usize).offset(1)
}

// And the current frame pointer points to the next older frame pointer.
pub const NEXT_OLDER_FP_FROM_FP_OFFSET: usize = 0;

pub fn reached_entry_sp(fp: usize, entry_sp: usize) -> bool {
fp >= entry_sp
}

pub fn assert_entry_sp_is_aligned(sp: usize) {
assert_eq!(sp % 16, 0, "stack should always be aligned to 16");
}

pub fn assert_fp_is_aligned(fp: usize) {
assert_eq!(fp % 16, 0, "stack should always be aligned to 16");
}

// Helper macros for getting the first and second arguments according to the
// system calling convention, as well as some callee-saved scratch registers we
// can safely use in the trampolines.
cfg_if::cfg_if! {
if #[cfg(windows)] {
macro_rules! callee_vmctx { () => ("rcx") }
#[allow(unused)] macro_rules! caller_vmctx { () => ("rdx") }
macro_rules! scratch0 { () => ("r10") }
macro_rules! scratch1 { () => ("r11") }
} else if #[cfg(unix)] {
} else if #[cfg(any(unix, wasmtime_custom_platform))] {
macro_rules! callee_vmctx { () => ("rdi") }
#[allow(unused)] macro_rules! caller_vmctx { () => ("rsi") }
macro_rules! scratch0 { () => ("r10") }
macro_rules! scratch1 { () => ("r11") }
} else {
compile_error!("platform not supported");
compile_error!("default calling convention for this platform is not known");

macro_rules! callee_vmctx { () => ("") }
macro_rules! scratch0 { () => ("") }
macro_rules! scratch1 { () => ("") }
}
}
pub(crate) use {callee_vmctx, scratch0, scratch1};

#[rustfmt::skip]
macro_rules! wasm_to_libcall_trampoline {
Expand All @@ -27,15 +51,15 @@ macro_rules! wasm_to_libcall_trampoline {
.cfi_startproc simple
.cfi_def_cfa_offset 0
// Load the pointer to `VMRuntimeLimits` in `", scratch0!(), "`.
mov ", scratch0!(), ", 8[", callee_vmctx!(), "]
// Load the pointer to `VMRuntimeLimits` in `scratch0!()`.
mov ", crate::arch::scratch0!(), ", 8[", crate::arch::callee_vmctx!(), "]
// Store the last Wasm FP into the `last_wasm_exit_fp` in the limits.
mov 24[", scratch0!(), "], rbp
mov 24[", crate::arch::scratch0!(), "], rbp
// Store the last Wasm PC into the `last_wasm_exit_pc` in the limits.
mov ", scratch1!(), ", [rsp]
mov 32[", scratch0!(), "], ", scratch1!(), "
mov ", crate::arch::scratch1!(), ", [rsp]
mov 32[", crate::arch::scratch0!(), "], ", crate::arch::scratch1!(), "
// Tail call to the actual implementation of this libcall.
jmp {}
Expand All @@ -47,6 +71,7 @@ macro_rules! wasm_to_libcall_trampoline {
);
};
}
pub(crate) use wasm_to_libcall_trampoline;

#[cfg(test)]
mod wasm_to_libcall_trampoline_offsets_tests {
Expand Down
Loading

0 comments on commit 3670f02

Please sign in to comment.