1
Fork 0

alloc now works on wasi (and some formatting)

This commit is contained in:
Ralf Jung 2024-05-16 10:43:38 +02:00
parent 0334bf8520
commit 6d314f3b11
10 changed files with 97 additions and 41 deletions

View file

@ -144,16 +144,15 @@ case $HOST_TARGET in
TEST_TARGET=arm-unknown-linux-gnueabi run_tests TEST_TARGET=arm-unknown-linux-gnueabi run_tests
TEST_TARGET=s390x-unknown-linux-gnu run_tests # big-endian architecture of choice TEST_TARGET=s390x-unknown-linux-gnu run_tests # big-endian architecture of choice
# Partially supported targets (tier 2) # 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="empty_main integer vec string btreemap hello hashmap heap_alloc align" # ensures we have the basics: stdout/stderr, system allocator, randomness (for HashMap initialization)
BASIC="$VERY_BASIC hello hashmap alloc align" # ensures we have the shims for stdout and basic data structures
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=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=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-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 hello 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 $VERY_BASIC hello panic/panic TEST_TARGET=aarch64-linux-android run_tests_minimal empty_main hello panic/panic
TEST_TARGET=wasm32-wasi run_tests_minimal $VERY_BASIC wasm TEST_TARGET=wasm32-wasi run_tests_minimal empty_main wasm heap_alloc libc-mem
TEST_TARGET=wasm32-unknown-unknown run_tests_minimal $VERY_BASIC wasm TEST_TARGET=wasm32-unknown-unknown run_tests_minimal empty_main wasm
TEST_TARGET=thumbv7em-none-eabihf run_tests_minimal no_std TEST_TARGET=thumbv7em-none-eabihf run_tests_minimal no_std
# Custom target JSON file # Custom target JSON file
TEST_TARGET=tests/avr.json MIRI_NO_STD=1 run_tests_minimal no_std TEST_TARGET=tests/avr.json MIRI_NO_STD=1 run_tests_minimal no_std
;; ;;

View file

@ -30,14 +30,13 @@ use rustc_target::abi::{Align, Size};
use rustc_target::spec::abi::Abi; use rustc_target::spec::abi::Abi;
use crate::{ use crate::{
concurrency::{data_race, weak_memory}, concurrency::{
shims::unix, data_race::{self, NaReadType, NaWriteType},
weak_memory,
},
*, *,
}; };
use self::concurrency::data_race::NaReadType;
use self::concurrency::data_race::NaWriteType;
/// First real-time signal. /// First real-time signal.
/// `signal(7)` says this must be between 32 and 64 and specifies 34 or 35 /// `signal(7)` says this must be between 32 and 64 and specifies 34 or 35
/// as typical values. /// as typical values.
@ -464,9 +463,9 @@ pub struct MiriMachine<'mir, 'tcx> {
pub(crate) validate: bool, pub(crate) validate: bool,
/// The table of file descriptors. /// The table of file descriptors.
pub(crate) fds: unix::FdTable, pub(crate) fds: shims::FdTable,
/// The table of directory descriptors. /// The table of directory descriptors.
pub(crate) dirs: unix::DirTable, pub(crate) dirs: shims::DirTable,
/// This machine's monotone clock. /// This machine's monotone clock.
pub(crate) clock: Clock, pub(crate) clock: Clock,
@ -641,7 +640,7 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
tls: TlsData::default(), tls: TlsData::default(),
isolated_op: config.isolated_op, isolated_op: config.isolated_op,
validate: config.validate, validate: config.validate,
fds: unix::FdTable::new(config.mute_stdout_stderr), fds: shims::FdTable::new(config.mute_stdout_stderr),
dirs: Default::default(), dirs: Default::default(),
layouts, layouts,
threads: ThreadManager::default(), threads: ThreadManager::default(),

View file

@ -111,6 +111,32 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
Ok(ptr.into()) 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> { fn free(&mut self, ptr: Pointer<Option<Provenance>>) -> InterpResult<'tcx> {
let this = self.eval_context_mut(); let this = self.eval_context_mut();
if !this.ptr_is_null(ptr)? { if !this.ptr_is_null(ptr)? {

View file

@ -108,6 +108,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
let this = self.eval_context_ref(); let this = self.eval_context_ref();
match this.tcx.sess.target.os.as_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), 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), "windows" => shims::windows::foreign_items::is_dyn_sym(name),
_ => false, _ => false,
} }
@ -947,6 +948,10 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
shims::unix::foreign_items::EvalContextExt::emulate_foreign_item_inner( shims::unix::foreign_items::EvalContextExt::emulate_foreign_item_inner(
this, link_name, abi, args, dest, this, link_name, abi, args, dest,
), ),
"wasi" =>
shims::wasi::foreign_items::EvalContextExt::emulate_foreign_item_inner(
this, link_name, abi, args, dest,
),
"windows" => "windows" =>
shims::windows::foreign_items::EvalContextExt::emulate_foreign_item_inner( shims::windows::foreign_items::EvalContextExt::emulate_foreign_item_inner(
this, link_name, abi, args, dest, this, link_name, abi, args, dest,

View file

@ -2,20 +2,23 @@
mod alloc; mod alloc;
mod backtrace; mod backtrace;
pub mod foreign_items;
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
pub mod native_lib; mod native_lib;
pub mod unix; mod unix;
pub mod windows; mod wasi;
mod windows;
mod x86; mod x86;
pub mod env; pub mod env;
pub mod extern_static; pub mod extern_static;
pub mod foreign_items;
pub mod os_str; pub mod os_str;
pub mod panic; pub mod panic;
pub mod time; pub mod time;
pub mod tls; pub mod tls;
pub use unix::{DirTable, FdTable};
/// What needs to be done after emulating an item (a shim or an intrinsic) is done. /// What needs to be done after emulating an item (a shim or an intrinsic) is done.
pub enum EmulateItemResult { pub enum EmulateItemResult {
/// The caller is expected to jump to the return block. /// The caller is expected to jump to the return block.

View file

@ -3,7 +3,6 @@ use std::str;
use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::layout::LayoutOf;
use rustc_span::Symbol; use rustc_span::Symbol;
use rustc_target::abi::{Align, Size};
use rustc_target::spec::abi::Abi; use rustc_target::spec::abi::Abi;
use crate::shims::alloc::EvalContextExt as _; use crate::shims::alloc::EvalContextExt as _;
@ -249,24 +248,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
// Allocation // Allocation
"posix_memalign" => { "posix_memalign" => {
let [ret, align, size] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let [memptr, align, size] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
let ret = this.deref_pointer(ret)?; let result = this.posix_memalign(memptr, align, size)?;
let align = this.read_target_usize(align)?; this.write_scalar(result, dest)?;
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)?;
}
} }
"mmap" => { "mmap" => {

View file

@ -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)
}
}

View file

@ -0,0 +1 @@
pub mod foreign_items;

View file

@ -226,7 +226,8 @@ fn test_memalign() {
target_os = "windows", target_os = "windows",
target_os = "macos", target_os = "macos",
target_os = "illumos", target_os = "illumos",
target_os = "solaris" target_os = "solaris",
target_os = "wasi",
)))] )))]
fn test_reallocarray() { fn test_reallocarray() {
unsafe { unsafe {
@ -249,7 +250,8 @@ fn main() {
target_os = "windows", target_os = "windows",
target_os = "macos", target_os = "macos",
target_os = "illumos", target_os = "illumos",
target_os = "solaris" target_os = "solaris",
target_os = "wasi",
)))] )))]
test_reallocarray(); test_reallocarray();

View file

@ -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() {}