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

Rustup, aligned heap-allocations on wasm #3606

Merged
merged 4 commits into from
May 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
15 changes: 7 additions & 8 deletions ci/ci.sh
Original file line number Diff line number Diff line change
Expand Up @@ -144,16 +144,15 @@ case $HOST_TARGET in
TEST_TARGET=arm-unknown-linux-gnueabi run_tests
TEST_TARGET=s390x-unknown-linux-gnu run_tests # big-endian architecture of choice
# Partially supported targets (tier 2)
VERY_BASIC="integer vec string btreemap" # common things we test on all of them (if they have std), requires no target-specific shims
BASIC="$VERY_BASIC hello hashmap alloc align" # ensures we have the shims for stdout and basic data structures
BASIC="empty_main integer vec string btreemap hello hashmap heap_alloc align" # ensures we have the basics: stdout/stderr, system allocator, randomness (for HashMap initialization)
TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal $BASIC panic/panic concurrency/simple atomic threadname libc-mem libc-misc libc-random libc-time fs env num_cpus
TEST_TARGET=i686-unknown-freebsd run_tests_minimal $BASIC panic/panic concurrency/simple atomic threadname libc-mem libc-misc libc-random libc-time fs env num_cpus
TEST_TARGET=x86_64-unknown-illumos run_tests_minimal $BASIC hello panic/panic concurrency/simple pthread-sync libc-mem libc-misc libc-random env
TEST_TARGET=x86_64-pc-solaris run_tests_minimal $BASIC hello panic/panic concurrency/simple pthread-sync libc-mem libc-misc libc-random env
TEST_TARGET=aarch64-linux-android run_tests_minimal $VERY_BASIC hello panic/panic
TEST_TARGET=wasm32-wasi run_tests_minimal $VERY_BASIC wasm
TEST_TARGET=wasm32-unknown-unknown run_tests_minimal $VERY_BASIC wasm
TEST_TARGET=thumbv7em-none-eabihf run_tests_minimal no_std
TEST_TARGET=x86_64-unknown-illumos run_tests_minimal $BASIC panic/panic concurrency/simple pthread-sync libc-mem libc-misc libc-random env
TEST_TARGET=x86_64-pc-solaris run_tests_minimal $BASIC panic/panic concurrency/simple pthread-sync libc-mem libc-misc libc-random env
TEST_TARGET=aarch64-linux-android run_tests_minimal empty_main hello panic/panic
TEST_TARGET=wasm32-wasi run_tests_minimal empty_main wasm heap_alloc libc-mem
TEST_TARGET=wasm32-unknown-unknown run_tests_minimal empty_main wasm
TEST_TARGET=thumbv7em-none-eabihf run_tests_minimal no_std
# Custom target JSON file
TEST_TARGET=tests/avr.json MIRI_NO_STD=1 run_tests_minimal no_std
;;
Expand Down
2 changes: 1 addition & 1 deletion rust-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
b71fa82d786ae1b5866510f1b3a7e5b7e1890e4c
b71e8cbaf2c7cae4d36898fff1d0ba19d9233082
15 changes: 7 additions & 8 deletions src/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,13 @@ use rustc_target::abi::{Align, Size};
use rustc_target::spec::abi::Abi;

use crate::{
concurrency::{data_race, weak_memory},
shims::unix,
concurrency::{
data_race::{self, NaReadType, NaWriteType},
weak_memory,
},
*,
};

use self::concurrency::data_race::NaReadType;
use self::concurrency::data_race::NaWriteType;

/// First real-time signal.
/// `signal(7)` says this must be between 32 and 64 and specifies 34 or 35
/// as typical values.
Expand Down Expand Up @@ -464,9 +463,9 @@ pub struct MiriMachine<'mir, 'tcx> {
pub(crate) validate: bool,

/// The table of file descriptors.
pub(crate) fds: unix::FdTable,
pub(crate) fds: shims::FdTable,
/// The table of directory descriptors.
pub(crate) dirs: unix::DirTable,
pub(crate) dirs: shims::DirTable,

/// This machine's monotone clock.
pub(crate) clock: Clock,
Expand Down Expand Up @@ -641,7 +640,7 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
tls: TlsData::default(),
isolated_op: config.isolated_op,
validate: config.validate,
fds: unix::FdTable::new(config.mute_stdout_stderr),
fds: shims::FdTable::new(config.mute_stdout_stderr),
dirs: Default::default(),
layouts,
threads: ThreadManager::default(),
Expand Down
26 changes: 26 additions & 0 deletions src/shims/alloc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,32 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
Ok(ptr.into())
}

fn posix_memalign(
&mut self,
memptr: &OpTy<'tcx, Provenance>,
align: &OpTy<'tcx, Provenance>,
size: &OpTy<'tcx, Provenance>,
) -> InterpResult<'tcx, Scalar<Provenance>> {
let this = self.eval_context_mut();
let memptr = this.deref_pointer(memptr)?;
let align = this.read_target_usize(align)?;
let size = this.read_target_usize(size)?;

// Align must be power of 2, and also at least ptr-sized (POSIX rules).
// But failure to adhere to this is not UB, it's an error condition.
if !align.is_power_of_two() || align < this.pointer_size().bytes() {
Ok(this.eval_libc("EINVAL"))
} else {
let ptr = this.allocate_ptr(
Size::from_bytes(size),
Align::from_bytes(align).unwrap(),
MiriMemoryKind::C.into(),
)?;
this.write_pointer(ptr, &memptr)?;
Ok(Scalar::from_i32(0))
}
}

fn free(&mut self, ptr: Pointer<Option<Provenance>>) -> InterpResult<'tcx> {
let this = self.eval_context_mut();
if !this.ptr_is_null(ptr)? {
Expand Down
5 changes: 5 additions & 0 deletions src/shims/foreign_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
let this = self.eval_context_ref();
match this.tcx.sess.target.os.as_ref() {
os if this.target_os_is_unix() => shims::unix::foreign_items::is_dyn_sym(name, os),
"wasi" => shims::wasi::foreign_items::is_dyn_sym(name),
"windows" => shims::windows::foreign_items::is_dyn_sym(name),
_ => false,
}
Expand Down Expand Up @@ -947,6 +948,10 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
shims::unix::foreign_items::EvalContextExt::emulate_foreign_item_inner(
this, link_name, abi, args, dest,
),
"wasi" =>
shims::wasi::foreign_items::EvalContextExt::emulate_foreign_item_inner(
this, link_name, abi, args, dest,
),
"windows" =>
shims::windows::foreign_items::EvalContextExt::emulate_foreign_item_inner(
this, link_name, abi, args, dest,
Expand Down
11 changes: 7 additions & 4 deletions src/shims/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,23 @@

mod alloc;
mod backtrace;
pub mod foreign_items;
#[cfg(target_os = "linux")]
pub mod native_lib;
pub mod unix;
pub mod windows;
mod native_lib;
mod unix;
mod wasi;
mod windows;
mod x86;

pub mod env;
pub mod extern_static;
pub mod foreign_items;
pub mod os_str;
pub mod panic;
pub mod time;
pub mod tls;

pub use unix::{DirTable, FdTable};

/// What needs to be done after emulating an item (a shim or an intrinsic) is done.
pub enum EmulateItemResult {
/// The caller is expected to jump to the return block.
Expand Down
22 changes: 3 additions & 19 deletions src/shims/unix/foreign_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use std::str;

use rustc_middle::ty::layout::LayoutOf;
use rustc_span::Symbol;
use rustc_target::abi::{Align, Size};
use rustc_target::spec::abi::Abi;

use crate::shims::alloc::EvalContextExt as _;
Expand Down Expand Up @@ -249,24 +248,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {

// Allocation
"posix_memalign" => {
let [ret, align, size] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
let ret = this.deref_pointer(ret)?;
let align = this.read_target_usize(align)?;
let size = this.read_target_usize(size)?;
// Align must be power of 2, and also at least ptr-sized (POSIX rules).
// But failure to adhere to this is not UB, it's an error condition.
if !align.is_power_of_two() || align < this.pointer_size().bytes() {
let einval = this.eval_libc_i32("EINVAL");
this.write_int(einval, dest)?;
} else {
let ptr = this.allocate_ptr(
Size::from_bytes(size),
Align::from_bytes(align).unwrap(),
MiriMemoryKind::C.into(),
)?;
this.write_pointer(ptr, &ret)?;
this.write_null(dest)?;
}
let [memptr, align, size] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
let result = this.posix_memalign(memptr, align, size)?;
this.write_scalar(result, dest)?;
}

"mmap" => {
Expand Down
34 changes: 34 additions & 0 deletions src/shims/wasi/foreign_items.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
use rustc_span::Symbol;
use rustc_target::spec::abi::Abi;

use crate::shims::alloc::EvalContextExt as _;
use crate::*;

pub fn is_dyn_sym(_name: &str) -> bool {
false
}

impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
fn emulate_foreign_item_inner(
&mut self,
link_name: Symbol,
abi: Abi,
args: &[OpTy<'tcx, Provenance>],
dest: &MPlaceTy<'tcx, Provenance>,
) -> InterpResult<'tcx, EmulateItemResult> {
let this = self.eval_context_mut();
match link_name.as_str() {
// Allocation
"posix_memalign" => {
let [memptr, align, size] =
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
let result = this.posix_memalign(memptr, align, size)?;
this.write_scalar(result, dest)?;
}

_ => return Ok(EmulateItemResult::NotSupported),
}
Ok(EmulateItemResult::NeedsJumping)
}
}
1 change: 1 addition & 0 deletions src/shims/wasi/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod foreign_items;
6 changes: 4 additions & 2 deletions tests/pass-dep/libc/libc-mem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,8 @@ fn test_memalign() {
target_os = "windows",
target_os = "macos",
target_os = "illumos",
target_os = "solaris"
target_os = "solaris",
target_os = "wasi",
)))]
fn test_reallocarray() {
unsafe {
Expand All @@ -249,7 +250,8 @@ fn main() {
target_os = "windows",
target_os = "macos",
target_os = "illumos",
target_os = "solaris"
target_os = "solaris",
target_os = "wasi",
)))]
test_reallocarray();

Expand Down
3 changes: 3 additions & 0 deletions tests/pass/empty_main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// This may look trivial, but a bunch of code runs in std before
// `main` is called, so we are ensuring that that all works.
fn main() {}