Remove the macro and expand it manually

This commit is contained in:
hyd-dev 2021-03-17 22:12:08 +08:00
parent 633ac2a222
commit 7ec919daa4
No known key found for this signature in database
GPG Key ID: 74FA7FD5B8DA14B8
5 changed files with 148 additions and 43 deletions

@ -13,36 +13,6 @@ use crate::*;
use super::backtrace::EvalContextExt as _;
use helpers::{check_abi, check_arg_count};
/// This macro behaves just like `match $link_name { ... }`, but inserts a
/// `$crate::helpers::check_abi($abi, $exp_abi)?` call at each match arm
/// except the wildcard one.
#[macro_export]
macro_rules! match_with_abi_check {
($link_name:expr, $abi:expr, $exp_abi:expr, {
$(|)? $($pattern:pat)|+ $(if $guard:expr)? => $shim_impl:block
$($remaining:tt)+
}) => {
match ($link_name, $abi, $exp_abi) {
($($pattern)|+, abi, exp_abi) $(if $guard)? => {
$crate::helpers::check_abi(abi, exp_abi)?;
$shim_impl
}
(link_name, abi, exp_abi) => match_with_abi_check!(
link_name,
abi,
exp_abi,
{ $($remaining)* }
),
}
};
($link_name:ident, $abi:ident, $exp_abi:ident, {
_ => $fallback:expr $(,)?
}) => ({
let _ = ($link_name, $abi, $exp_abi);
$fallback
});
}
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
/// Returns the minimum alignment for the target architecture for allocations of the given size.

@ -5,7 +5,7 @@ use rustc_target::abi::{Align, LayoutOf, Size};
use rustc_target::spec::abi::Abi;
use crate::*;
use helpers::check_arg_count;
use helpers::{check_abi, check_arg_count};
use shims::posix::fs::EvalContextExt as _;
use shims::posix::sync::EvalContextExt as _;
use shims::posix::thread::EvalContextExt as _;
@ -22,30 +22,35 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
) -> InterpResult<'tcx, bool> {
let this = self.eval_context_mut();
match_with_abi_check!(link_name, abi, Abi::C { unwind: false }, {
match link_name {
// Environment related shims
"getenv" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref name] = check_arg_count(args)?;
let result = this.getenv(name)?;
this.write_scalar(result, dest)?;
}
"unsetenv" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref name] = check_arg_count(args)?;
let result = this.unsetenv(name)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"setenv" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref name, ref value, ref overwrite] = check_arg_count(args)?;
this.read_scalar(overwrite)?.to_i32()?;
let result = this.setenv(name, value)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"getcwd" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref buf, ref size] = check_arg_count(args)?;
let result = this.getcwd(buf, size)?;
this.write_scalar(result, dest)?;
}
"chdir" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref path] = check_arg_count(args)?;
let result = this.chdir(path)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
@ -53,15 +58,18 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
// File related shims
"open" | "open64" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref path, ref flag, ref mode] = check_arg_count(args)?;
let result = this.open(path, flag, mode)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"fcntl" => {
check_abi(abi, Abi::C { unwind: false })?;
let result = this.fcntl(args)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"read" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref fd, ref buf, ref count] = check_arg_count(args)?;
let fd = this.read_scalar(fd)?.to_i32()?;
let buf = this.read_scalar(buf)?.check_init()?;
@ -70,6 +78,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
this.write_scalar(Scalar::from_machine_isize(result, this), dest)?;
}
"write" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref fd, ref buf, ref n] = check_arg_count(args)?;
let fd = this.read_scalar(fd)?.to_i32()?;
let buf = this.read_scalar(buf)?.check_init()?;
@ -80,52 +89,62 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
this.write_scalar(Scalar::from_machine_isize(result, this), dest)?;
}
"unlink" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref path] = check_arg_count(args)?;
let result = this.unlink(path)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"symlink" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref target, ref linkpath] = check_arg_count(args)?;
let result = this.symlink(target, linkpath)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"rename" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref oldpath, ref newpath] = check_arg_count(args)?;
let result = this.rename(oldpath, newpath)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"mkdir" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref path, ref mode] = check_arg_count(args)?;
let result = this.mkdir(path, mode)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"rmdir" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref path] = check_arg_count(args)?;
let result = this.rmdir(path)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"closedir" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref dirp] = check_arg_count(args)?;
let result = this.closedir(dirp)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"lseek" | "lseek64" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref fd, ref offset, ref whence] = check_arg_count(args)?;
let result = this.lseek64(fd, offset, whence)?;
// "lseek" is only used on macOS which is 64bit-only, so `i64` always works.
this.write_scalar(Scalar::from_i64(result), dest)?;
}
"fsync" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref fd] = check_arg_count(args)?;
let result = this.fsync(fd)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"fdatasync" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref fd] = check_arg_count(args)?;
let result = this.fdatasync(fd)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"readlink" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref pathname, ref buf, ref bufsize] = check_arg_count(args)?;
let result = this.readlink(pathname, buf, bufsize)?;
this.write_scalar(Scalar::from_machine_isize(result, this), dest)?;
@ -133,6 +152,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
// Allocation
"posix_memalign" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref ret, ref align, ref size] = check_arg_count(args)?;
let ret = this.deref_operand(ret)?;
let align = this.read_scalar(align)?.to_machine_usize(this)?;
@ -163,6 +183,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
// Dynamic symbol loading
"dlsym" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref handle, ref symbol] = check_arg_count(args)?;
this.read_scalar(handle)?.to_machine_usize(this)?;
let symbol = this.read_scalar(symbol)?.check_init()?;
@ -177,6 +198,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
// Querying system information
"sysconf" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref name] = check_arg_count(args)?;
let name = this.read_scalar(name)?.to_i32()?;
@ -202,6 +224,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
// Thread-local storage
"pthread_key_create" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref key, ref dtor] = check_arg_count(args)?;
let key_place = this.deref_operand(key)?;
let dtor = this.read_scalar(dtor)?.check_init()?;
@ -230,6 +253,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
this.write_null(dest)?;
}
"pthread_key_delete" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref key] = check_arg_count(args)?;
let key = this.force_bits(this.read_scalar(key)?.check_init()?, key.layout.size)?;
this.machine.tls.delete_tls_key(key)?;
@ -237,6 +261,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
this.write_null(dest)?;
}
"pthread_getspecific" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref key] = check_arg_count(args)?;
let key = this.force_bits(this.read_scalar(key)?.check_init()?, key.layout.size)?;
let active_thread = this.get_active_thread();
@ -244,6 +269,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
this.write_scalar(ptr, dest)?;
}
"pthread_setspecific" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref key, ref new_ptr] = check_arg_count(args)?;
let key = this.force_bits(this.read_scalar(key)?.check_init()?, key.layout.size)?;
let active_thread = this.get_active_thread();
@ -256,110 +282,132 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
// Synchronization primitives
"pthread_mutexattr_init" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref attr] = check_arg_count(args)?;
let result = this.pthread_mutexattr_init(attr)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"pthread_mutexattr_settype" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref attr, ref kind] = check_arg_count(args)?;
let result = this.pthread_mutexattr_settype(attr, kind)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"pthread_mutexattr_destroy" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref attr] = check_arg_count(args)?;
let result = this.pthread_mutexattr_destroy(attr)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"pthread_mutex_init" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref mutex, ref attr] = check_arg_count(args)?;
let result = this.pthread_mutex_init(mutex, attr)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"pthread_mutex_lock" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref mutex] = check_arg_count(args)?;
let result = this.pthread_mutex_lock(mutex)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"pthread_mutex_trylock" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref mutex] = check_arg_count(args)?;
let result = this.pthread_mutex_trylock(mutex)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"pthread_mutex_unlock" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref mutex] = check_arg_count(args)?;
let result = this.pthread_mutex_unlock(mutex)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"pthread_mutex_destroy" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref mutex] = check_arg_count(args)?;
let result = this.pthread_mutex_destroy(mutex)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"pthread_rwlock_rdlock" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref rwlock] = check_arg_count(args)?;
let result = this.pthread_rwlock_rdlock(rwlock)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"pthread_rwlock_tryrdlock" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref rwlock] = check_arg_count(args)?;
let result = this.pthread_rwlock_tryrdlock(rwlock)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"pthread_rwlock_wrlock" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref rwlock] = check_arg_count(args)?;
let result = this.pthread_rwlock_wrlock(rwlock)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"pthread_rwlock_trywrlock" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref rwlock] = check_arg_count(args)?;
let result = this.pthread_rwlock_trywrlock(rwlock)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"pthread_rwlock_unlock" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref rwlock] = check_arg_count(args)?;
let result = this.pthread_rwlock_unlock(rwlock)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"pthread_rwlock_destroy" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref rwlock] = check_arg_count(args)?;
let result = this.pthread_rwlock_destroy(rwlock)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"pthread_condattr_init" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref attr] = check_arg_count(args)?;
let result = this.pthread_condattr_init(attr)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"pthread_condattr_destroy" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref attr] = check_arg_count(args)?;
let result = this.pthread_condattr_destroy(attr)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"pthread_cond_init" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref cond, ref attr] = check_arg_count(args)?;
let result = this.pthread_cond_init(cond, attr)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"pthread_cond_signal" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref cond] = check_arg_count(args)?;
let result = this.pthread_cond_signal(cond)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"pthread_cond_broadcast" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref cond] = check_arg_count(args)?;
let result = this.pthread_cond_broadcast(cond)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"pthread_cond_wait" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref cond, ref mutex] = check_arg_count(args)?;
let result = this.pthread_cond_wait(cond, mutex)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"pthread_cond_timedwait" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref cond, ref mutex, ref abstime] = check_arg_count(args)?;
this.pthread_cond_timedwait(cond, mutex, abstime, dest)?;
}
"pthread_cond_destroy" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref cond] = check_arg_count(args)?;
let result = this.pthread_cond_destroy(cond)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
@ -367,30 +415,36 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
// Threading
"pthread_create" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref thread, ref attr, ref start, ref arg] = check_arg_count(args)?;
let result = this.pthread_create(thread, attr, start, arg)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"pthread_join" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref thread, ref retval] = check_arg_count(args)?;
let result = this.pthread_join(thread, retval)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"pthread_detach" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref thread] = check_arg_count(args)?;
let result = this.pthread_detach(thread)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"pthread_self" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[] = check_arg_count(args)?;
this.pthread_self(dest)?;
}
"sched_yield" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[] = check_arg_count(args)?;
let result = this.sched_yield()?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"nanosleep" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref req, ref rem] = check_arg_count(args)?;
let result = this.nanosleep(req, rem)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
@ -398,6 +452,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
// Miscellaneous
"isatty" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref fd] = check_arg_count(args)?;
this.read_scalar(fd)?.to_i32()?;
// "returns 1 if fd is an open file descriptor referring to a terminal; otherwise 0 is returned, and errno is set to indicate the error"
@ -407,6 +462,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
this.write_null(dest)?;
}
"pthread_atfork" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref prepare, ref parent, ref child] = check_arg_count(args)?;
this.force_bits(this.read_scalar(prepare)?.check_init()?, this.memory.pointer_size())?;
this.force_bits(this.read_scalar(parent)?.check_init()?, this.memory.pointer_size())?;
@ -419,6 +475,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
// These shims are enabled only when the caller is in the standard library.
"pthread_attr_getguardsize"
if this.frame().instance.to_string().starts_with("std::sys::unix::") => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref _attr, ref guard_size] = check_arg_count(args)?;
let guard_size = this.deref_operand(guard_size)?;
let guard_size_layout = this.libc_ty_layout("size_t")?;
@ -431,11 +488,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
| "pthread_attr_init"
| "pthread_attr_destroy"
if this.frame().instance.to_string().starts_with("std::sys::unix::") => {
check_abi(abi, Abi::C { unwind: false })?;
let &[_] = check_arg_count(args)?;
this.write_null(dest)?;
}
| "pthread_attr_setstacksize"
if this.frame().instance.to_string().starts_with("std::sys::unix::") => {
check_abi(abi, Abi::C { unwind: false })?;
let &[_, _] = check_arg_count(args)?;
this.write_null(dest)?;
}
@ -443,12 +502,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
| "signal"
| "sigaltstack"
if this.frame().instance.to_string().starts_with("std::sys::unix::") => {
check_abi(abi, Abi::C { unwind: false })?;
let &[_, _] = check_arg_count(args)?;
this.write_null(dest)?;
}
| "sigaction"
| "mprotect"
if this.frame().instance.to_string().starts_with("std::sys::unix::") => {
check_abi(abi, Abi::C { unwind: false })?;
let &[_, _, _] = check_arg_count(args)?;
this.write_null(dest)?;
}
@ -461,7 +522,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
_ => unreachable!(),
}
}
});
};
Ok(true)
}

@ -2,7 +2,7 @@ use rustc_middle::mir;
use rustc_target::spec::abi::Abi;
use crate::*;
use crate::helpers::check_arg_count;
use crate::helpers::{check_abi, check_arg_count};
use shims::posix::fs::EvalContextExt as _;
use shims::posix::linux::sync::futex;
use shims::posix::sync::EvalContextExt as _;
@ -20,9 +20,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
) -> InterpResult<'tcx, bool> {
let this = self.eval_context_mut();
match_with_abi_check!(link_name, abi, Abi::C { unwind: false }, {
match link_name {
// errno
"__errno_location" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[] = check_arg_count(args)?;
let errno_place = this.last_error_place()?;
this.write_scalar(errno_place.to_ref().to_scalar()?, dest)?;
@ -32,27 +33,32 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
// These symbols have different names on Linux and macOS, which is the only reason they are not
// in the `posix` module.
"close" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref fd] = check_arg_count(args)?;
let result = this.close(fd)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"opendir" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref name] = check_arg_count(args)?;
let result = this.opendir(name)?;
this.write_scalar(result, dest)?;
}
"readdir64_r" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref dirp, ref entry, ref result] = check_arg_count(args)?;
let result = this.linux_readdir64_r(dirp, entry, result)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"ftruncate64" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref fd, ref length] = check_arg_count(args)?;
let result = this.ftruncate64(fd, length)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
// Linux-only
"posix_fadvise" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref fd, ref offset, ref len, ref advice] = check_arg_count(args)?;
this.read_scalar(fd)?.to_i32()?;
this.read_scalar(offset)?.to_machine_isize(this)?;
@ -62,6 +68,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
this.write_null(dest)?;
}
"sync_file_range" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref fd, ref offset, ref nbytes, ref flags] = check_arg_count(args)?;
let result = this.sync_file_range(fd, offset, nbytes, flags)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
@ -69,6 +76,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
// Time related shims
"clock_gettime" => {
check_abi(abi, Abi::C { unwind: false })?;
// This is a POSIX function but it has only been tested on linux.
let &[ref clk_id, ref tp] = check_arg_count(args)?;
let result = this.clock_gettime(clk_id, tp)?;
@ -77,6 +85,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
// Querying system information
"pthread_attr_getstack" => {
check_abi(abi, Abi::C { unwind: false })?;
// We don't support "pthread_attr_setstack", so we just pretend all stacks have the same values here.
let &[ref attr_place, ref addr_place, ref size_place] = check_arg_count(args)?;
this.deref_operand(attr_place)?;
@ -98,16 +107,19 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
// Threading
"prctl" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref option, ref arg2, ref arg3, ref arg4, ref arg5] = check_arg_count(args)?;
let result = this.prctl(option, arg2, arg3, arg4, arg5)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"pthread_condattr_setclock" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref attr, ref clock_id] = check_arg_count(args)?;
let result = this.pthread_condattr_setclock(attr, clock_id)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"pthread_condattr_getclock" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref attr, ref clock_id] = check_arg_count(args)?;
let result = this.pthread_condattr_getclock(attr, clock_id)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
@ -115,6 +127,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
// Dynamically invoked syscalls
"syscall" => {
check_abi(abi, Abi::C { unwind: false })?;
// The syscall variadic function is legal to call with more arguments than needed,
// extra arguments are simply ignored. However, all arguments need to be scalars;
// other types might be treated differently by the calling convention.
@ -169,10 +182,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
// Miscelanneous
"getrandom" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref ptr, ref len, ref flags] = check_arg_count(args)?;
getrandom(this, ptr, len, flags, dest)?;
}
"sched_getaffinity" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref pid, ref cpusetsize, ref mask] = check_arg_count(args)?;
this.read_scalar(pid)?.to_i32()?;
this.read_scalar(cpusetsize)?.to_machine_usize(this)?;
@ -186,12 +201,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
// Incomplete shims that we "stub out" just to get pre-main initialization code to work.
// These shims are enabled only when the caller is in the standard library.
"pthread_getattr_np" if this.frame().instance.to_string().starts_with("std::sys::unix::") => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref _thread, ref _attr] = check_arg_count(args)?;
this.write_null(dest)?;
}
_ => throw_unsup_format!("can't call foreign function: {}", link_name),
});
};
Ok(true)
}

@ -2,7 +2,7 @@ use rustc_middle::mir;
use rustc_target::spec::abi::Abi;
use crate::*;
use helpers::check_arg_count;
use helpers::{check_abi, check_arg_count};
use shims::posix::fs::EvalContextExt as _;
use shims::posix::thread::EvalContextExt as _;
@ -18,9 +18,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
) -> InterpResult<'tcx, bool> {
let this = self.eval_context_mut();
match_with_abi_check!(link_name, abi, Abi::C { unwind: false }, {
match link_name {
// errno
"__error" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[] = check_arg_count(args)?;
let errno_place = this.last_error_place()?;
this.write_scalar(errno_place.to_ref().to_scalar()?, dest)?;
@ -28,36 +29,43 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
// File related shims
"close" | "close$NOCANCEL" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref result] = check_arg_count(args)?;
let result = this.close(result)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"stat" | "stat$INODE64" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref path, ref buf] = check_arg_count(args)?;
let result = this.macos_stat(path, buf)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"lstat" | "lstat$INODE64" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref path, ref buf] = check_arg_count(args)?;
let result = this.macos_lstat(path, buf)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"fstat" | "fstat$INODE64" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref fd, ref buf] = check_arg_count(args)?;
let result = this.macos_fstat(fd, buf)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"opendir" | "opendir$INODE64" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref name] = check_arg_count(args)?;
let result = this.opendir(name)?;
this.write_scalar(result, dest)?;
}
"readdir_r" | "readdir_r$INODE64" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref dirp, ref entry, ref result] = check_arg_count(args)?;
let result = this.macos_readdir_r(dirp, entry, result)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"ftruncate" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref fd, ref length] = check_arg_count(args)?;
let result = this.ftruncate64(fd, length)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
@ -65,40 +73,47 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
// Environment related shims
"_NSGetEnviron" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[] = check_arg_count(args)?;
this.write_scalar(this.machine.env_vars.environ.unwrap().ptr, dest)?;
}
// Time related shims
"gettimeofday" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref tv, ref tz] = check_arg_count(args)?;
let result = this.gettimeofday(tv, tz)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"mach_absolute_time" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[] = check_arg_count(args)?;
let result = this.mach_absolute_time()?;
this.write_scalar(Scalar::from_u64(result), dest)?;
}
"mach_timebase_info" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref info] = check_arg_count(args)?;
let result = this.mach_timebase_info(info)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
},
// Access to command-line arguments
"_NSGetArgc" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[] = check_arg_count(args)?;
this.write_scalar(this.machine.argc.expect("machine must be initialized"), dest)?;
}
"_NSGetArgv" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[] = check_arg_count(args)?;
this.write_scalar(this.machine.argv.expect("machine must be initialized"), dest)?;
}
// Thread-local storage
"_tlv_atexit" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref dtor, ref data] = check_arg_count(args)?;
let dtor = this.read_scalar(dtor)?.check_init()?;
let dtor = this.memory.get_fn(dtor)?.as_instance()?;
@ -109,12 +124,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
// Querying system information
"pthread_get_stackaddr_np" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref thread] = check_arg_count(args)?;
this.read_scalar(thread)?.to_machine_usize(this)?;
let stack_addr = Scalar::from_uint(STACK_ADDR, this.pointer_size());
this.write_scalar(stack_addr, dest)?;
}
"pthread_get_stacksize_np" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref thread] = check_arg_count(args)?;
this.read_scalar(thread)?.to_machine_usize(this)?;
let stack_size = Scalar::from_uint(STACK_SIZE, this.pointer_size());
@ -123,6 +140,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
// Threading
"pthread_setname_np" => {
check_abi(abi, Abi::C { unwind: false })?;
let &[ref name] = check_arg_count(args)?;
let name = this.read_scalar(name)?.check_init()?;
this.pthread_setname_np(name)?;
@ -131,6 +149,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
// Incomplete shims that we "stub out" just to get pre-main initialization code to work.
// These shims are enabled only when the caller is in the standard library.
"mmap" if this.frame().instance.to_string().starts_with("std::sys::unix::") => {
check_abi(abi, Abi::C { unwind: false })?;
// This is a horrible hack, but since the guard page mechanism calls mmap and expects a particular return value, we just give it that value.
let &[ref addr, _, _, _, _, _] = check_arg_count(args)?;
let addr = this.read_scalar(addr)?.check_init()?;
@ -138,7 +157,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
}
_ => throw_unsup_format!("can't call foreign function: {}", link_name),
});
};
Ok(true)
}

@ -5,7 +5,7 @@ use rustc_target::abi::Size;
use rustc_target::spec::abi::Abi;
use crate::*;
use helpers::check_arg_count;
use helpers::{check_abi, check_arg_count};
use shims::windows::sync::EvalContextExt as _;
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
@ -25,34 +25,40 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
// DWORD = ULONG = u32
// BOOL = i32
// BOOLEAN = u8
match_with_abi_check!(link_name, abi, Abi::System { unwind: false }, {
match link_name {
// Environment related shims
"GetEnvironmentVariableW" => {
check_abi(abi, Abi::System { unwind: false })?;
let &[ref name, ref buf, ref size] = check_arg_count(args)?;
let result = this.GetEnvironmentVariableW(name, buf, size)?;
this.write_scalar(Scalar::from_u32(result), dest)?;
}
"SetEnvironmentVariableW" => {
check_abi(abi, Abi::System { unwind: false })?;
let &[ref name, ref value] = check_arg_count(args)?;
let result = this.SetEnvironmentVariableW(name, value)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"GetEnvironmentStringsW" => {
check_abi(abi, Abi::System { unwind: false })?;
let &[] = check_arg_count(args)?;
let result = this.GetEnvironmentStringsW()?;
this.write_scalar(result, dest)?;
}
"FreeEnvironmentStringsW" => {
check_abi(abi, Abi::System { unwind: false })?;
let &[ref env_block] = check_arg_count(args)?;
let result = this.FreeEnvironmentStringsW(env_block)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"GetCurrentDirectoryW" => {
check_abi(abi, Abi::System { unwind: false })?;
let &[ref size, ref buf] = check_arg_count(args)?;
let result = this.GetCurrentDirectoryW(size, buf)?;
this.write_scalar(Scalar::from_u32(result), dest)?;
}
"SetCurrentDirectoryW" => {
check_abi(abi, Abi::System { unwind: false })?;
let &[ref path] = check_arg_count(args)?;
let result = this.SetCurrentDirectoryW(path)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
@ -60,6 +66,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
// File related shims
"GetStdHandle" => {
check_abi(abi, Abi::System { unwind: false })?;
let &[ref which] = check_arg_count(args)?;
let which = this.read_scalar(which)?.to_i32()?;
// We just make this the identity function, so we know later in `WriteFile`
@ -67,6 +74,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
this.write_scalar(Scalar::from_machine_isize(which.into(), this), dest)?;
}
"WriteFile" => {
check_abi(abi, Abi::System { unwind: false })?;
let &[ref handle, ref buf, ref n, ref written_ptr, ref overlapped] = check_arg_count(args)?;
this.read_scalar(overlapped)?.to_machine_usize(this)?; // this is a poiner, that we ignore
let handle = this.read_scalar(handle)?.to_machine_isize(this)?;
@ -102,6 +110,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
// Allocation
"HeapAlloc" => {
check_abi(abi, Abi::System { unwind: false })?;
let &[ref handle, ref flags, ref size] = check_arg_count(args)?;
this.read_scalar(handle)?.to_machine_isize(this)?;
let flags = this.read_scalar(flags)?.to_u32()?;
@ -111,6 +120,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
this.write_scalar(res, dest)?;
}
"HeapFree" => {
check_abi(abi, Abi::System { unwind: false })?;
let &[ref handle, ref flags, ref ptr] = check_arg_count(args)?;
this.read_scalar(handle)?.to_machine_isize(this)?;
this.read_scalar(flags)?.to_u32()?;
@ -119,6 +129,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
this.write_scalar(Scalar::from_i32(1), dest)?;
}
"HeapReAlloc" => {
check_abi(abi, Abi::System { unwind: false })?;
let &[ref handle, ref flags, ref ptr, ref size] = check_arg_count(args)?;
this.read_scalar(handle)?.to_machine_isize(this)?;
this.read_scalar(flags)?.to_u32()?;
@ -130,11 +141,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
// errno
"SetLastError" => {
check_abi(abi, Abi::System { unwind: false })?;
let &[ref error] = check_arg_count(args)?;
let error = this.read_scalar(error)?.check_init()?;
this.set_last_error(error)?;
}
"GetLastError" => {
check_abi(abi, Abi::System { unwind: false })?;
let &[] = check_arg_count(args)?;
let last_error = this.get_last_error()?;
this.write_scalar(last_error, dest)?;
@ -142,6 +155,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
// Querying system information
"GetSystemInfo" => {
check_abi(abi, Abi::System { unwind: false })?;
let &[ref system_info] = check_arg_count(args)?;
let system_info = this.deref_operand(system_info)?;
// Initialize with `0`.
@ -157,6 +171,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
// Thread-local storage
"TlsAlloc" => {
check_abi(abi, Abi::System { unwind: false })?;
// This just creates a key; Windows does not natively support TLS destructors.
// Create key and return it.
@ -165,6 +180,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
this.write_scalar(Scalar::from_uint(key, dest.layout.size), dest)?;
}
"TlsGetValue" => {
check_abi(abi, Abi::System { unwind: false })?;
let &[ref key] = check_arg_count(args)?;
let key = u128::from(this.read_scalar(key)?.to_u32()?);
let active_thread = this.get_active_thread();
@ -172,6 +188,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
this.write_scalar(ptr, dest)?;
}
"TlsSetValue" => {
check_abi(abi, Abi::System { unwind: false })?;
let &[ref key, ref new_ptr] = check_arg_count(args)?;
let key = u128::from(this.read_scalar(key)?.to_u32()?);
let active_thread = this.get_active_thread();
@ -184,6 +201,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
// Access to command-line arguments
"GetCommandLineW" => {
check_abi(abi, Abi::System { unwind: false })?;
let &[] = check_arg_count(args)?;
this.write_scalar(
this.machine.cmd_line.expect("machine must be initialized"),
@ -193,17 +211,20 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
// Time related shims
"GetSystemTimeAsFileTime" => {
check_abi(abi, Abi::System { unwind: false })?;
#[allow(non_snake_case)]
let &[ref LPFILETIME] = check_arg_count(args)?;
this.GetSystemTimeAsFileTime(LPFILETIME)?;
}
"QueryPerformanceCounter" => {
check_abi(abi, Abi::System { unwind: false })?;
#[allow(non_snake_case)]
let &[ref lpPerformanceCount] = check_arg_count(args)?;
let result = this.QueryPerformanceCounter(lpPerformanceCount)?;
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"QueryPerformanceFrequency" => {
check_abi(abi, Abi::System { unwind: false })?;
#[allow(non_snake_case)]
let &[ref lpFrequency] = check_arg_count(args)?;
let result = this.QueryPerformanceFrequency(lpFrequency)?;
@ -212,27 +233,33 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
// Synchronization primitives
"AcquireSRWLockExclusive" => {
check_abi(abi, Abi::System { unwind: false })?;
let &[ref ptr] = check_arg_count(args)?;
this.AcquireSRWLockExclusive(ptr)?;
}
"ReleaseSRWLockExclusive" => {
check_abi(abi, Abi::System { unwind: false })?;
let &[ref ptr] = check_arg_count(args)?;
this.ReleaseSRWLockExclusive(ptr)?;
}
"TryAcquireSRWLockExclusive" => {
check_abi(abi, Abi::System { unwind: false })?;
let &[ref ptr] = check_arg_count(args)?;
let ret = this.TryAcquireSRWLockExclusive(ptr)?;
this.write_scalar(Scalar::from_u8(ret), dest)?;
}
"AcquireSRWLockShared" => {
check_abi(abi, Abi::System { unwind: false })?;
let &[ref ptr] = check_arg_count(args)?;
this.AcquireSRWLockShared(ptr)?;
}
"ReleaseSRWLockShared" => {
check_abi(abi, Abi::System { unwind: false })?;
let &[ref ptr] = check_arg_count(args)?;
this.ReleaseSRWLockShared(ptr)?;
}
"TryAcquireSRWLockShared" => {
check_abi(abi, Abi::System { unwind: false })?;
let &[ref ptr] = check_arg_count(args)?;
let ret = this.TryAcquireSRWLockShared(ptr)?;
this.write_scalar(Scalar::from_u8(ret), dest)?;
@ -240,6 +267,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
// Dynamic symbol loading
"GetProcAddress" => {
check_abi(abi, Abi::System { unwind: false })?;
#[allow(non_snake_case)]
let &[ref hModule, ref lpProcName] = check_arg_count(args)?;
this.read_scalar(hModule)?.to_machine_isize(this)?;
@ -254,6 +282,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
// Miscellaneous
"SystemFunction036" => {
check_abi(abi, Abi::System { unwind: false })?;
// The actual name of 'RtlGenRandom'
let &[ref ptr, ref len] = check_arg_count(args)?;
let ptr = this.read_scalar(ptr)?.check_init()?;
@ -262,6 +291,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
this.write_scalar(Scalar::from_bool(true), dest)?;
}
"GetConsoleScreenBufferInfo" => {
check_abi(abi, Abi::System { unwind: false })?;
// `term` needs this, so we fake it.
let &[ref console, ref buffer_info] = check_arg_count(args)?;
this.read_scalar(console)?.to_machine_isize(this)?;
@ -271,6 +301,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
this.write_null(dest)?;
}
"GetConsoleMode" => {
check_abi(abi, Abi::System { unwind: false })?;
// Windows "isatty" (in libtest) needs this, so we fake it.
let &[ref console, ref mode] = check_arg_count(args)?;
this.read_scalar(console)?.to_machine_isize(this)?;
@ -280,6 +311,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
this.write_null(dest)?;
}
"SwitchToThread" => {
check_abi(abi, Abi::System { unwind: false })?;
let &[] = check_arg_count(args)?;
// Note that once Miri supports concurrency, this will need to return a nonzero
// value if this call does result in switching to another thread.
@ -288,29 +320,34 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
// Better error for attempts to create a thread
"CreateThread" => {
check_abi(abi, Abi::System { unwind: false })?;
throw_unsup_format!("Miri does not support concurrency on Windows");
}
// Incomplete shims that we "stub out" just to get pre-main initialization code to work.
// These shims are enabled only when the caller is in the standard library.
"GetProcessHeap" if this.frame().instance.to_string().starts_with("std::sys::windows::") => {
check_abi(abi, Abi::System { unwind: false })?;
let &[] = check_arg_count(args)?;
// Just fake a HANDLE
this.write_scalar(Scalar::from_machine_isize(1, this), dest)?;
}
"SetConsoleTextAttribute" if this.frame().instance.to_string().starts_with("std::sys::windows::") => {
check_abi(abi, Abi::System { unwind: false })?;
#[allow(non_snake_case)]
let &[ref _hConsoleOutput, ref _wAttribute] = check_arg_count(args)?;
// Pretend these does not exist / nothing happened, by returning zero.
this.write_null(dest)?;
}
"AddVectoredExceptionHandler" if this.frame().instance.to_string().starts_with("std::sys::windows::") => {
check_abi(abi, Abi::System { unwind: false })?;
#[allow(non_snake_case)]
let &[ref _First, ref _Handler] = check_arg_count(args)?;
// Any non zero value works for the stdlib. This is just used for stack overflows anyway.
this.write_scalar(Scalar::from_machine_usize(1, this), dest)?;
}
"SetThreadStackGuarantee" if this.frame().instance.to_string().starts_with("std::sys::windows::") => {
check_abi(abi, Abi::System { unwind: false })?;
#[allow(non_snake_case)]
let &[_StackSizeInBytes] = check_arg_count(args)?;
// Any non zero value works for the stdlib. This is just used for stack overflows anyway.
@ -321,6 +358,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
| "LeaveCriticalSection"
| "DeleteCriticalSection"
if this.frame().instance.to_string().starts_with("std::sys::windows::") => {
check_abi(abi, Abi::System { unwind: false })?;
#[allow(non_snake_case)]
let &[ref _lpCriticalSection] = check_arg_count(args)?;
assert_eq!(this.get_total_thread_count(), 1, "concurrency on Windows is not supported");
@ -330,6 +368,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
}
"TryEnterCriticalSection"
if this.frame().instance.to_string().starts_with("std::sys::windows::") => {
check_abi(abi, Abi::System { unwind: false })?;
#[allow(non_snake_case)]
let &[ref _lpCriticalSection] = check_arg_count(args)?;
assert_eq!(this.get_total_thread_count(), 1, "concurrency on Windows is not supported");
@ -338,7 +377,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
}
_ => throw_unsup_format!("can't call foreign function: {}", link_name),
});
}
Ok(true)
}