Skip to content

Commit e78804f

Browse files
committed
Auto merge of rust-lang#2742 - RalfJung:targets, r=RalfJung
handle unknown targets more gracefully In particular don't require a list of all OSes in the TLS machinery. Instead just fall back to doing nothing.
2 parents 9f316ae + f58a50f commit e78804f

13 files changed

+92
-60
lines changed

src/shims/foreign_items.rs

+62-31
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
4747
let min_align = match this.tcx.sess.target.arch.as_ref() {
4848
"x86" | "arm" | "mips" | "powerpc" | "powerpc64" | "asmjs" | "wasm32" => 8,
4949
"x86_64" | "aarch64" | "mips64" | "s390x" | "sparc64" => 16,
50-
arch => bug!("Unsupported target architecture: {}", arch),
50+
arch => bug!("unsupported target architecture for malloc: `{}`", arch),
5151
};
5252
// Windows always aligns, even small allocations.
5353
// Source: <https://support.microsoft.com/en-us/help/286470/how-to-use-pageheap-exe-in-windows-xp-windows-2000-and-windows-server>
@@ -320,7 +320,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
320320
return Ok(Some(body));
321321
}
322322

323-
this.handle_unsupported(format!("can't call foreign function: {link_name}"))?;
323+
this.handle_unsupported(format!(
324+
"can't call foreign function `{link_name}` on OS `{os}`",
325+
os = this.tcx.sess.target.os,
326+
))?;
324327
return Ok(None);
325328
}
326329
}
@@ -336,9 +339,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
336339
) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> {
337340
let this = self.eval_context_mut();
338341

339-
let allocator_kind = if let Some(allocator_kind) = this.tcx.allocator_kind(()) {
340-
allocator_kind
341-
} else {
342+
let Some(allocator_kind) = this.tcx.allocator_kind(()) else {
342343
// in real code, this symbol does not exist without an allocator
343344
return Ok(EmulateByNameResult::NotSupported);
344345
};
@@ -420,9 +421,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
420421
let [ptr] = this.check_shim(abi, Abi::Rust, link_name, args)?;
421422
let ptr = this.read_pointer(ptr)?;
422423
let (alloc_id, _, _) = this.ptr_get_alloc_id(ptr).map_err(|_e| {
423-
err_machine_stop!(TerminationInfo::Abort(
424-
format!("pointer passed to miri_get_alloc_id must not be dangling, got {ptr:?}")
425-
))
424+
err_machine_stop!(TerminationInfo::Abort(format!(
425+
"pointer passed to miri_get_alloc_id must not be dangling, got {ptr:?}"
426+
)))
426427
})?;
427428
this.write_scalar(Scalar::from_u64(alloc_id.0.get()), dest)?;
428429
}
@@ -438,7 +439,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
438439
let ptr = this.read_pointer(ptr)?;
439440
let (alloc_id, offset, _) = this.ptr_get_alloc_id(ptr)?;
440441
if offset != Size::ZERO {
441-
throw_unsup_format!("pointer passed to miri_static_root must point to beginning of an allocated block");
442+
throw_unsup_format!(
443+
"pointer passed to miri_static_root must point to beginning of an allocated block"
444+
);
442445
}
443446
this.machine.static_roots.push(alloc_id);
444447
}
@@ -453,7 +456,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
453456

454457
// We read this as a plain OsStr and write it as a path, which will convert it to the target.
455458
let path = this.read_os_str_from_c_str(ptr)?.to_owned();
456-
let (success, needed_size) = this.write_path_to_c_str(Path::new(&path), out, out_size)?;
459+
let (success, needed_size) =
460+
this.write_path_to_c_str(Path::new(&path), out, out_size)?;
457461
// Return value: 0 on success, otherwise the size it would have needed.
458462
this.write_int(if success { 0 } else { needed_size }, dest)?;
459463
}
@@ -505,11 +509,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
505509
this.write_pointer(res, dest)?;
506510
}
507511
"calloc" => {
508-
let [items, len] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
512+
let [items, len] =
513+
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
509514
let items = this.read_machine_usize(items)?;
510515
let len = this.read_machine_usize(len)?;
511-
let size =
512-
items.checked_mul(len).ok_or_else(|| err_ub_format!("overflow during calloc size computation"))?;
516+
let size = items
517+
.checked_mul(len)
518+
.ok_or_else(|| err_ub_format!("overflow during calloc size computation"))?;
513519
let res = this.malloc(size, /*zero_init:*/ true, MiriMemoryKind::C)?;
514520
this.write_pointer(res, dest)?;
515521
}
@@ -519,7 +525,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
519525
this.free(ptr, MiriMemoryKind::C)?;
520526
}
521527
"realloc" => {
522-
let [old_ptr, new_size] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
528+
let [old_ptr, new_size] =
529+
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
523530
let old_ptr = this.read_pointer(old_ptr)?;
524531
let new_size = this.read_machine_usize(new_size)?;
525532
let res = this.realloc(old_ptr, new_size, MiriMemoryKind::C)?;
@@ -551,11 +558,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
551558
};
552559

553560
match link_name.as_str() {
554-
"__rust_alloc" => return this.emulate_allocator(Symbol::intern("__rg_alloc"), default),
561+
"__rust_alloc" =>
562+
return this.emulate_allocator(Symbol::intern("__rg_alloc"), default),
555563
"miri_alloc" => {
556564
default(this)?;
557565
return Ok(EmulateByNameResult::NeedsJumping);
558-
},
566+
}
559567
_ => unreachable!(),
560568
}
561569
}
@@ -574,7 +582,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
574582
)?;
575583

576584
// We just allocated this, the access is definitely in-bounds.
577-
this.write_bytes_ptr(ptr.into(), iter::repeat(0u8).take(usize::try_from(size).unwrap())).unwrap();
585+
this.write_bytes_ptr(
586+
ptr.into(),
587+
iter::repeat(0u8).take(usize::try_from(size).unwrap()),
588+
)
589+
.unwrap();
578590
this.write_pointer(ptr, dest)
579591
});
580592
}
@@ -600,7 +612,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
600612
};
601613

602614
match link_name.as_str() {
603-
"__rust_dealloc" => return this.emulate_allocator(Symbol::intern("__rg_dealloc"), default),
615+
"__rust_dealloc" =>
616+
return this.emulate_allocator(Symbol::intern("__rg_dealloc"), default),
604617
"miri_dealloc" => {
605618
default(this)?;
606619
return Ok(EmulateByNameResult::NeedsJumping);
@@ -609,7 +622,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
609622
}
610623
}
611624
"__rust_realloc" => {
612-
let [ptr, old_size, align, new_size] = this.check_shim(abi, Abi::Rust, link_name, args)?;
625+
let [ptr, old_size, align, new_size] =
626+
this.check_shim(abi, Abi::Rust, link_name, args)?;
613627
let ptr = this.read_pointer(ptr)?;
614628
let old_size = this.read_machine_usize(old_size)?;
615629
let align = this.read_machine_usize(align)?;
@@ -633,7 +647,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
633647

634648
// C memory handling functions
635649
"memcmp" => {
636-
let [left, right, n] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
650+
let [left, right, n] =
651+
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
637652
let left = this.read_pointer(left)?;
638653
let right = this.read_pointer(right)?;
639654
let n = Size::from_bytes(this.read_machine_usize(n)?);
@@ -653,7 +668,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
653668
this.write_scalar(Scalar::from_i32(result), dest)?;
654669
}
655670
"memrchr" => {
656-
let [ptr, val, num] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
671+
let [ptr, val, num] =
672+
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
657673
let ptr = this.read_pointer(ptr)?;
658674
let val = this.read_scalar(val)?.to_i32()?;
659675
let num = this.read_machine_usize(num)?;
@@ -676,7 +692,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
676692
}
677693
}
678694
"memchr" => {
679-
let [ptr, val, num] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
695+
let [ptr, val, num] =
696+
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
680697
let ptr = this.read_pointer(ptr)?;
681698
let val = this.read_scalar(val)?.to_i32()?;
682699
let num = this.read_machine_usize(num)?;
@@ -699,7 +716,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
699716
let [ptr] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
700717
let ptr = this.read_pointer(ptr)?;
701718
let n = this.read_c_str(ptr)?.len();
702-
this.write_scalar(Scalar::from_machine_usize(u64::try_from(n).unwrap(), this), dest)?;
719+
this.write_scalar(
720+
Scalar::from_machine_usize(u64::try_from(n).unwrap(), this),
721+
dest,
722+
)?;
703723
}
704724

705725
// math functions (note that there are also intrinsics for some other functions)
@@ -835,7 +855,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
835855
let a = this.read_scalar(a)?.to_u64()?;
836856
let b = this.read_scalar(b)?.to_u64()?;
837857

838-
#[allow(clippy::integer_arithmetic)] // adding two u64 and a u8 cannot wrap in a u128
858+
#[allow(clippy::integer_arithmetic)]
859+
// adding two u64 and a u8 cannot wrap in a u128
839860
let wide_sum = u128::from(c_in) + u128::from(a) + u128::from(b);
840861
#[allow(clippy::integer_arithmetic)] // it's a u128, we can shift by 64
841862
let (c_out, sum) = ((wide_sum >> 64).truncate::<u8>(), wide_sum.truncate::<u64>());
@@ -845,15 +866,18 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
845866
let sum_field = this.place_field(dest, 1)?;
846867
this.write_scalar(Scalar::from_u64(sum), &sum_field)?;
847868
}
848-
"llvm.x86.sse2.pause" if this.tcx.sess.target.arch == "x86" || this.tcx.sess.target.arch == "x86_64" => {
869+
"llvm.x86.sse2.pause"
870+
if this.tcx.sess.target.arch == "x86" || this.tcx.sess.target.arch == "x86_64" =>
871+
{
849872
let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
850873
this.yield_active_thread();
851874
}
852875
"llvm.aarch64.isb" if this.tcx.sess.target.arch == "aarch64" => {
853876
let [arg] = this.check_shim(abi, Abi::Unadjusted, link_name, args)?;
854877
let arg = this.read_scalar(arg)?.to_i32()?;
855878
match arg {
856-
15 => { // SY ("full system scope")
879+
// SY ("full system scope")
880+
15 => {
857881
this.yield_active_thread();
858882
}
859883
_ => {
@@ -863,11 +887,18 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
863887
}
864888

865889
// Platform-specific shims
866-
_ => match this.tcx.sess.target.os.as_ref() {
867-
target if target_os_is_unix(target) => return shims::unix::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest),
868-
"windows" => return shims::windows::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest),
869-
target => throw_unsup_format!("the target `{}` is not supported", target),
870-
}
890+
_ =>
891+
return match this.tcx.sess.target.os.as_ref() {
892+
target_os if target_os_is_unix(target_os) =>
893+
shims::unix::foreign_items::EvalContextExt::emulate_foreign_item_by_name(
894+
this, link_name, abi, args, dest,
895+
),
896+
"windows" =>
897+
shims::windows::foreign_items::EvalContextExt::emulate_foreign_item_by_name(
898+
this, link_name, abi, args, dest,
899+
),
900+
_ => Ok(EmulateByNameResult::NotSupported),
901+
},
871902
};
872903
// We only fall through to here if we did *not* hit the `_` arm above,
873904
// i.e., if we actually emulated the function with one of the shims.

src/shims/tls.rs

+2-7
Original file line numberDiff line numberDiff line change
@@ -257,16 +257,11 @@ impl TlsDtorsState {
257257
// And move to the final state.
258258
self.0 = Done;
259259
}
260-
"wasi" | "none" => {
261-
// No OS, no TLS dtors.
260+
_ => {
261+
// No TLS dtor support.
262262
// FIXME: should we do something on wasi?
263263
self.0 = Done;
264264
}
265-
os => {
266-
throw_unsup_format!(
267-
"the TLS machinery does not know how to handle OS `{os}`"
268-
);
269-
}
270265
}
271266
}
272267
PthreadDtors(state) => {

src/shims/unix/foreign_items.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -596,13 +596,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
596596
// Platform-specific shims
597597
_ => {
598598
let target_os = &*this.tcx.sess.target.os;
599-
match target_os {
600-
"android" => return shims::unix::android::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest),
601-
"freebsd" => return shims::unix::freebsd::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest),
602-
"linux" => return shims::unix::linux::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest),
603-
"macos" => return shims::unix::macos::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest),
604-
_ => panic!("unsupported Unix OS {target_os}"),
605-
}
599+
return match target_os {
600+
"android" => shims::unix::android::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest),
601+
"freebsd" => shims::unix::freebsd::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest),
602+
"linux" => shims::unix::linux::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest),
603+
"macos" => shims::unix::macos::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest),
604+
_ => Ok(EmulateByNameResult::NotSupported),
605+
};
606606
}
607607
};
608608

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
//@only-target-linux
22
//@only-on-host
3+
//@normalize-stderr-test: "OS `.*`" -> "$$OS"
34

45
extern "C" {
56
fn foo();
67
}
78

89
fn main() {
910
unsafe {
10-
foo(); //~ ERROR: unsupported operation: can't call foreign function: foo
11+
foo(); //~ ERROR: unsupported operation: can't call foreign function `foo`
1112
}
1213
}

tests/extern-so/fail/function_not_in_so.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error: unsupported operation: can't call foreign function: foo
1+
error: unsupported operation: can't call foreign function `foo` on $OS
22
--> $DIR/function_not_in_so.rs:LL:CC
33
|
44
LL | foo();
5-
| ^^^^^ can't call foreign function: foo
5+
| ^^^^^ can't call foreign function `foo` on $OS
66
|
77
= help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support
88
= note: BACKTRACE:

tests/fail/alloc/no_global_allocator.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
//@normalize-stderr-test: "OS `.*`" -> "$$OS"
12
// Make sure we pretend the allocation symbols don't exist when there is no allocator
23

34
#![feature(lang_items, start)]
@@ -10,7 +11,7 @@ extern "Rust" {
1011
#[start]
1112
fn start(_: isize, _: *const *const u8) -> isize {
1213
unsafe {
13-
__rust_alloc(1, 1); //~ERROR: unsupported operation: can't call foreign function: __rust_alloc
14+
__rust_alloc(1, 1); //~ERROR: unsupported operation: can't call foreign function `__rust_alloc`
1415
}
1516

1617
0

tests/fail/alloc/no_global_allocator.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error: unsupported operation: can't call foreign function: __rust_alloc
1+
error: unsupported operation: can't call foreign function `__rust_alloc` on $OS
22
--> $DIR/no_global_allocator.rs:LL:CC
33
|
44
LL | __rust_alloc(1, 1);
5-
| ^^^^^^^^^^^^^^^^^^ can't call foreign function: __rust_alloc
5+
| ^^^^^^^^^^^^^^^^^^ can't call foreign function `__rust_alloc` on $OS
66
|
77
= help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support
88
= note: BACKTRACE:
+3-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1+
//@normalize-stderr-test: "OS `.*`" -> "$$OS"
2+
13
fn main() {
24
extern "Rust" {
35
fn foo();
46
}
57

68
unsafe {
7-
foo(); //~ ERROR: unsupported operation: can't call foreign function: foo
9+
foo(); //~ ERROR: unsupported operation: can't call foreign function `foo`
810
}
911
}

tests/fail/unsupported_foreign_function.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error: unsupported operation: can't call foreign function: foo
1+
error: unsupported operation: can't call foreign function `foo` on $OS
22
--> $DIR/unsupported_foreign_function.rs:LL:CC
33
|
44
LL | foo();
5-
| ^^^^^ can't call foreign function: foo
5+
| ^^^^^ can't call foreign function `foo` on $OS
66
|
77
= help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support
88
= note: BACKTRACE:
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
//! `signal()` is special on Linux and macOS that it's only supported within libstd.
22
//! The implementation is not complete enough to permit user code to call it.
33
//@ignore-target-windows: No libc on Windows
4+
//@normalize-stderr-test: "OS `.*`" -> "$$OS"
45

56
fn main() {
67
unsafe {
78
libc::signal(libc::SIGPIPE, libc::SIG_IGN);
8-
//~^ ERROR: unsupported operation: can't call foreign function: signal
9+
//~^ ERROR: unsupported operation: can't call foreign function `signal`
910
}
1011
}

0 commit comments

Comments
 (0)