Skip to content

Commit

Permalink
Auto merge of rust-lang#129773 - workingjubilee:rollup-qdoxwhe, r=wor…
Browse files Browse the repository at this point in the history
…kingjubilee

Rollup of 8 pull requests

Successful merges:

 - rust-lang#126183 (Separate core search logic with search ui)
 - rust-lang#129366 (linker: Synchronize native library search in rustc and linker)
 - rust-lang#129403 (Ban non-array SIMD)
 - rust-lang#129527 (Don't use `TyKind` in a lint)
 - rust-lang#129534 (Deny `wasm_c_abi` lint to nudge the last 25%)
 - rust-lang#129640 (Re-enable android tests/benches in alloc/core)
 - rust-lang#129731 (Allow running `./x.py test compiler`)
 - rust-lang#129754 (wasi: Fix sleeping for `Duration::MAX`)

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Aug 30, 2024
2 parents 0d63418 + 4f38687 commit 9917e34
Show file tree
Hide file tree
Showing 142 changed files with 4,474 additions and 4,685 deletions.
12 changes: 6 additions & 6 deletions compiler/rustc_codegen_cranelift/example/float-minmax-pass.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@

#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
struct f32x4(pub f32, pub f32, pub f32, pub f32);
struct f32x4(pub [f32; 4]);

use std::intrinsics::simd::*;

fn main() {
let x = f32x4(1.0, 2.0, 3.0, 4.0);
let y = f32x4(2.0, 1.0, 4.0, 3.0);
let x = f32x4([1.0, 2.0, 3.0, 4.0]);
let y = f32x4([2.0, 1.0, 4.0, 3.0]);

#[cfg(not(any(target_arch = "mips", target_arch = "mips64")))]
let nan = f32::NAN;
Expand All @@ -24,13 +24,13 @@ fn main() {
#[cfg(any(target_arch = "mips", target_arch = "mips64"))]
let nan = f32::from_bits(f32::NAN.to_bits() - 1);

let n = f32x4(nan, nan, nan, nan);
let n = f32x4([nan, nan, nan, nan]);

unsafe {
let min0 = simd_fmin(x, y);
let min1 = simd_fmin(y, x);
assert_eq!(min0, min1);
let e = f32x4(1.0, 1.0, 3.0, 3.0);
let e = f32x4([1.0, 1.0, 3.0, 3.0]);
assert_eq!(min0, e);
let minn = simd_fmin(x, n);
assert_eq!(minn, x);
Expand All @@ -40,7 +40,7 @@ fn main() {
let max0 = simd_fmax(x, y);
let max1 = simd_fmax(y, x);
assert_eq!(max0, max1);
let e = f32x4(2.0, 2.0, 4.0, 4.0);
let e = f32x4([2.0, 2.0, 4.0, 4.0]);
assert_eq!(max0, e);
let maxn = simd_fmax(x, n);
assert_eq!(maxn, x);
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_codegen_cranelift/example/std_example.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ fn main() {
enum Never {}
}

foo(I64X2(0, 0));
foo(I64X2([0, 0]));

transmute_fat_pointer();

Expand Down Expand Up @@ -204,7 +204,7 @@ fn rust_call_abi() {
}

#[repr(simd)]
struct I64X2(i64, i64);
struct I64X2([i64; 2]);

#[allow(improper_ctypes_definitions)]
extern "C" fn foo(_a: I64X2) {}
Expand Down
61 changes: 15 additions & 46 deletions compiler/rustc_codegen_ssa/src/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::collections::BTreeSet;
use std::ffi::OsString;
use std::fs::{read, File, OpenOptions};
use std::io::{BufWriter, Write};
use std::ops::Deref;
use std::ops::{ControlFlow, Deref};
use std::path::{Path, PathBuf};
use std::process::{ExitStatus, Output, Stdio};
use std::{env, fmt, fs, io, mem, str};
Expand All @@ -18,8 +18,8 @@ use rustc_data_structures::temp_dir::MaybeTempDir;
use rustc_errors::{DiagCtxtHandle, ErrorGuaranteed, FatalError};
use rustc_fs_util::{fix_windows_verbatim_for_gcc, try_canonicalize};
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
use rustc_metadata::find_native_static_library;
use rustc_metadata::fs::{copy_to_stdout, emit_wrapper_file, METADATA_FILENAME};
use rustc_metadata::{find_native_static_library, walk_native_lib_search_dirs};
use rustc_middle::bug;
use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
use rustc_middle::middle::dependency_format::Linkage;
Expand Down Expand Up @@ -2110,50 +2110,19 @@ fn add_library_search_dirs(
return;
}

// Library search paths explicitly supplied by user (`-L` on the command line).
for search_path in sess.target_filesearch(PathKind::Native).cli_search_paths() {
cmd.include_path(&fix_windows_verbatim_for_gcc(&search_path.dir));
}
for search_path in sess.target_filesearch(PathKind::Framework).cli_search_paths() {
// Contrary to the `-L` docs only framework-specific paths are considered here.
if search_path.kind != PathKind::All {
cmd.framework_path(&search_path.dir);
}
}

// The toolchain ships some native library components and self-contained linking was enabled.
// Add the self-contained library directory to search paths.
if self_contained_components.intersects(
LinkSelfContainedComponents::LIBC
| LinkSelfContainedComponents::UNWIND
| LinkSelfContainedComponents::MINGW,
) {
let lib_path = sess.target_tlib_path.dir.join("self-contained");
cmd.include_path(&fix_windows_verbatim_for_gcc(&lib_path));
}

// Toolchains for some targets may ship `libunwind.a`, but place it into the main sysroot
// library directory instead of the self-contained directories.
// Sanitizer libraries have the same issue and are also linked by name on Apple targets.
// The targets here should be in sync with `copy_third_party_objects` in bootstrap.
// FIXME: implement `-Clink-self-contained=+/-unwind,+/-sanitizers`, move the shipped libunwind
// and sanitizers to self-contained directory, and stop adding this search path.
if sess.target.vendor == "fortanix"
|| sess.target.os == "linux"
|| sess.target.os == "fuchsia"
|| sess.target.is_like_osx && !sess.opts.unstable_opts.sanitizer.is_empty()
{
cmd.include_path(&fix_windows_verbatim_for_gcc(&sess.target_tlib_path.dir));
}

// Mac Catalyst uses the macOS SDK, but to link to iOS-specific frameworks
// we must have the support library stubs in the library search path (#121430).
if let Some(sdk_root) = apple_sdk_root
&& sess.target.llvm_target.contains("macabi")
{
cmd.include_path(&sdk_root.join("System/iOSSupport/usr/lib"));
cmd.framework_path(&sdk_root.join("System/iOSSupport/System/Library/Frameworks"));
}
walk_native_lib_search_dirs(
sess,
self_contained_components,
apple_sdk_root,
|dir, is_framework| {
if is_framework {
cmd.framework_path(dir);
} else {
cmd.include_path(&fix_windows_verbatim_for_gcc(dir));
}
ControlFlow::<()>::Continue(())
},
);
}

/// Add options making relocation sections in the produced ELF files read-only
Expand Down
14 changes: 10 additions & 4 deletions compiler/rustc_codegen_ssa/src/back/linker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::{env, iter, mem, str};

use cc::windows_registry;
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
use rustc_metadata::find_native_static_library;
use rustc_metadata::{find_native_static_library, try_find_native_static_library};
use rustc_middle::bug;
use rustc_middle::middle::dependency_format::Linkage;
use rustc_middle::middle::exported_symbols;
Expand Down Expand Up @@ -891,9 +891,15 @@ impl<'a> Linker for MsvcLinker<'a> {
}

fn link_staticlib_by_name(&mut self, name: &str, verbatim: bool, whole_archive: bool) {
let prefix = if whole_archive { "/WHOLEARCHIVE:" } else { "" };
let suffix = if verbatim { "" } else { ".lib" };
self.link_arg(format!("{prefix}{name}{suffix}"));
// On MSVC-like targets rustc supports static libraries using alternative naming
// scheme (`libfoo.a`) unsupported by linker, search for such libraries manually.
if let Some(path) = try_find_native_static_library(self.sess, name, verbatim) {
self.link_staticlib_by_path(&path, whole_archive);
} else {
let prefix = if whole_archive { "/WHOLEARCHIVE:" } else { "" };
let suffix = if verbatim { "" } else { ".lib" };
self.link_arg(format!("{prefix}{name}{suffix}"));
}
}

fn link_staticlib_by_path(&mut self, path: &Path, whole_archive: bool) {
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_error_codes/src/error_codes/E0074.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ This will cause an error:
#![feature(repr_simd)]
#[repr(simd)]
struct Bad<T>(T, T, T, T);
struct Bad<T>([T; 4]);
```

This will not:
Expand All @@ -20,5 +20,5 @@ This will not:
#![feature(repr_simd)]
#[repr(simd)]
struct Good(u32, u32, u32, u32);
struct Good([u32; 4]);
```
18 changes: 12 additions & 6 deletions compiler/rustc_error_codes/src/error_codes/E0075.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
A `#[simd]` attribute was applied to an empty tuple struct.
A `#[simd]` attribute was applied to an empty or multi-field struct.

Erroneous code example:
Erroneous code examples:

```compile_fail,E0075
#![feature(repr_simd)]
Expand All @@ -9,15 +9,21 @@ Erroneous code example:
struct Bad; // error!
```

The `#[simd]` attribute can only be applied to non empty tuple structs, because
it doesn't make sense to try to use SIMD operations when there are no values to
operate on.
```compile_fail,E0075
#![feature(repr_simd)]
#[repr(simd)]
struct Bad([u32; 1], [u32; 1]); // error!
```

The `#[simd]` attribute can only be applied to a single-field struct, because
the one field must be the array of values in the vector.

Fixed example:

```
#![feature(repr_simd)]
#[repr(simd)]
struct Good(u32); // ok!
struct Good([u32; 2]); // ok!
```
10 changes: 5 additions & 5 deletions compiler/rustc_error_codes/src/error_codes/E0076.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
All types in a tuple struct aren't the same when using the `#[simd]`
The type of the field in a tuple struct isn't an array when using the `#[simd]`
attribute.

Erroneous code example:
Expand All @@ -7,18 +7,18 @@ Erroneous code example:
#![feature(repr_simd)]
#[repr(simd)]
struct Bad(u16, u32, u32 u32); // error!
struct Bad(u16); // error!
```

When using the `#[simd]` attribute to automatically use SIMD operations in tuple
struct, the types in the struct must all be of the same type, or the compiler
will trigger this error.
structs, if you want a single-lane vector then the field must be a 1-element
array, or the compiler will trigger this error.

Fixed example:

```
#![feature(repr_simd)]
#[repr(simd)]
struct Good(u32, u32, u32, u32); // ok!
struct Good([u16; 1]); // ok!
```
4 changes: 2 additions & 2 deletions compiler/rustc_error_codes/src/error_codes/E0077.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Erroneous code example:
#![feature(repr_simd)]
#[repr(simd)]
struct Bad(String); // error!
struct Bad([String; 2]); // error!
```

When using the `#[simd]` attribute on a tuple struct, the elements in the tuple
Expand All @@ -19,5 +19,5 @@ Fixed example:
#![feature(repr_simd)]
#[repr(simd)]
struct Good(u32, u32, u32, u32); // ok!
struct Good([u32; 4]); // ok!
```
4 changes: 2 additions & 2 deletions compiler/rustc_error_codes/src/error_codes/E0511.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ The generic type has to be a SIMD type. Example:
#[repr(simd)]
#[derive(Copy, Clone)]
struct i32x2(i32, i32);
struct i32x2([i32; 2]);
extern "rust-intrinsic" {
fn simd_add<T>(a: T, b: T) -> T;
}
unsafe { simd_add(i32x2(0, 0), i32x2(1, 2)); } // ok!
unsafe { simd_add(i32x2([0, 0]), i32x2([1, 2])); } // ok!
```
42 changes: 22 additions & 20 deletions compiler/rustc_hir_analysis/src/check/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1063,20 +1063,29 @@ fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) {
struct_span_code_err!(tcx.dcx(), sp, E0075, "SIMD vector cannot be empty").emit();
return;
}
let e = fields[FieldIdx::ZERO].ty(tcx, args);
if !fields.iter().all(|f| f.ty(tcx, args) == e) {
struct_span_code_err!(tcx.dcx(), sp, E0076, "SIMD vector should be homogeneous")
.with_span_label(sp, "SIMD elements must have the same type")

let array_field = &fields[FieldIdx::ZERO];
let array_ty = array_field.ty(tcx, args);
let ty::Array(element_ty, len_const) = array_ty.kind() else {
struct_span_code_err!(
tcx.dcx(),
sp,
E0076,
"SIMD vector's only field must be an array"
)
.with_span_label(tcx.def_span(array_field.did), "not an array")
.emit();
return;
};

if let Some(second_field) = fields.get(FieldIdx::from_u32(1)) {
struct_span_code_err!(tcx.dcx(), sp, E0075, "SIMD vector cannot have multiple fields")
.with_span_label(tcx.def_span(second_field.did), "excess field")
.emit();
return;
}

let len = if let ty::Array(_ty, c) = e.kind() {
c.try_eval_target_usize(tcx, tcx.param_env(def.did()))
} else {
Some(fields.len() as u64)
};
if let Some(len) = len {
if let Some(len) = len_const.try_eval_target_usize(tcx, tcx.param_env(def.did())) {
if len == 0 {
struct_span_code_err!(tcx.dcx(), sp, E0075, "SIMD vector cannot be empty").emit();
return;
Expand All @@ -1096,16 +1105,9 @@ fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) {
// These are scalar types which directly match a "machine" type
// Yes: Integers, floats, "thin" pointers
// No: char, "fat" pointers, compound types
match e.kind() {
ty::Param(_) => (), // pass struct<T>(T, T, T, T) through, let monomorphization catch errors
ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::RawPtr(_, _) => (), // struct(u8, u8, u8, u8) is ok
ty::Array(t, _) if matches!(t.kind(), ty::Param(_)) => (), // pass struct<T>([T; N]) through, let monomorphization catch errors
ty::Array(t, _clen)
if matches!(
t.kind(),
ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::RawPtr(_, _)
) =>
{ /* struct([f32; 4]) is ok */ }
match element_ty.kind() {
ty::Param(_) => (), // pass struct<T>([T; 4]) through, let monomorphization catch errors
ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::RawPtr(_, _) => (), // struct([u8; 4]) is ok
_ => {
struct_span_code_err!(
tcx.dcx(),
Expand Down
25 changes: 13 additions & 12 deletions compiler/rustc_lint/src/foreign_modules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -265,8 +265,6 @@ fn structurally_same_type_impl<'tcx>(
} else {
// Do a full, depth-first comparison between the two.
use rustc_type_ir::TyKind::*;
let a_kind = a.kind();
let b_kind = b.kind();

let compare_layouts = |a, b| -> Result<bool, &'tcx LayoutError<'tcx>> {
debug!("compare_layouts({:?}, {:?})", a, b);
Expand All @@ -281,12 +279,11 @@ fn structurally_same_type_impl<'tcx>(
Ok(a_layout == b_layout)
};

#[allow(rustc::usage_of_ty_tykind)]
let is_primitive_or_pointer =
|kind: &ty::TyKind<'_>| kind.is_primitive() || matches!(kind, RawPtr(..) | Ref(..));
|ty: Ty<'tcx>| ty.is_primitive() || matches!(ty.kind(), RawPtr(..) | Ref(..));

ensure_sufficient_stack(|| {
match (a_kind, b_kind) {
match (a.kind(), b.kind()) {
(Adt(a_def, _), Adt(b_def, _)) => {
// We can immediately rule out these types as structurally same if
// their layouts differ.
Expand Down Expand Up @@ -382,17 +379,21 @@ fn structurally_same_type_impl<'tcx>(

// An Adt and a primitive or pointer type. This can be FFI-safe if non-null
// enum layout optimisation is being applied.
(Adt(..), other_kind) | (other_kind, Adt(..))
if is_primitive_or_pointer(other_kind) =>
{
let (primitive, adt) =
if is_primitive_or_pointer(a.kind()) { (a, b) } else { (b, a) };
if let Some(ty) = types::repr_nullable_ptr(tcx, param_env, adt, ckind) {
ty == primitive
(Adt(..), _) if is_primitive_or_pointer(b) => {
if let Some(ty) = types::repr_nullable_ptr(tcx, param_env, a, ckind) {
ty == b
} else {
compare_layouts(a, b).unwrap_or(false)
}
}
(_, Adt(..)) if is_primitive_or_pointer(a) => {
if let Some(ty) = types::repr_nullable_ptr(tcx, param_env, b, ckind) {
ty == a
} else {
compare_layouts(a, b).unwrap_or(false)
}
}

// Otherwise, just compare the layouts. This may fail to lint for some
// incompatible types, but at the very least, will stop reads into
// uninitialised memory.
Expand Down
Loading

0 comments on commit 9917e34

Please sign in to comment.