Auto merge of #151615 - matthiaskrgr:rollup-2WQ1USJ, r=matthiaskrgr

Rollup of 11 pull requests

Successful merges:

 - rust-lang/rust#149962 (Promote powerpc64-unknown-linux-musl to tier 2 with host tools)
 - rust-lang/rust#150138 (Add new Tier 3 targets for ARMv6)
 - rust-lang/rust#150905 (Fix(lib/win/net): Remove hostname support under Win7)
 - rust-lang/rust#151094 (remote-test-server: Fix compilation on UEFI targets)
 - rust-lang/rust#151346 (add `simd_splat` intrinsic)
 - rust-lang/rust#151353 (compiletest: Make `aux-crate` directive explicitly handle `--extern` modifiers)
 - rust-lang/rust#151538 (std: `sleep_until` on Motor and VEX)
 - rust-lang/rust#151098 (Add Korean translation to Rust By Example)
 - rust-lang/rust#151157 (Extend build-manifest local test guide)
 - rust-lang/rust#151403 (std: use 64-bit `clock_nanosleep` on GNU/Linux if available)
 - rust-lang/rust#151571 (Fix cstring-merging test for Hexagon target)
This commit is contained in:
bors
2026-01-24 22:26:32 +00:00
54 changed files with 630 additions and 75 deletions

View File

@@ -348,6 +348,31 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
ret.write_cvalue(fx, ret_lane);
}
sym::simd_splat => {
intrinsic_args!(fx, args => (value); intrinsic);
if !ret.layout().ty.is_simd() {
report_simd_type_validation_error(fx, intrinsic, span, ret.layout().ty);
return;
}
let (lane_count, lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx);
if value.layout().ty != lane_ty {
fx.tcx.dcx().span_fatal(
span,
format!(
"[simd_splat] expected element type {lane_ty:?}, got {got:?}",
got = value.layout().ty
),
);
}
for i in 0..lane_count {
let ret_lane = ret.place_lane(fx, i.into());
ret_lane.write_cvalue(fx, value);
}
}
sym::simd_neg
| sym::simd_bswap
| sym::simd_bitreverse

View File

@@ -121,6 +121,42 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
return Ok(bx.vector_select(vector_mask, arg1, args[2].immediate()));
}
#[cfg(feature = "master")]
if name == sym::simd_splat {
let (out_len, out_ty) = require_simd2!(ret_ty, SimdReturn);
require!(
args[0].layout.ty == out_ty,
InvalidMonomorphization::ExpectedVectorElementType {
span,
name,
expected_element: out_ty,
vector_type: ret_ty,
}
);
let vec_ty = llret_ty.unqualified().dyncast_vector().expect("vector return type");
let elem_ty = vec_ty.get_element_type();
// Cast pointer type to usize (GCC does not support pointer SIMD vectors).
let value = args[0];
let scalar = if value.layout.ty.is_numeric() {
value.immediate()
} else if value.layout.ty.is_raw_ptr() {
bx.ptrtoint(value.immediate(), elem_ty)
} else {
return_error!(InvalidMonomorphization::UnsupportedOperation {
span,
name,
in_ty: ret_ty,
in_elem: value.layout.ty
});
};
let elements = vec![scalar; out_len as usize];
return Ok(bx.context.new_rvalue_from_vector(bx.location, llret_ty, &elements));
}
// every intrinsic below takes a SIMD vector as its first argument
require_simd!(
args[0].layout.ty,

View File

@@ -1581,6 +1581,31 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
return Ok(bx.select(m_i1s, args[1].immediate(), args[2].immediate()));
}
if name == sym::simd_splat {
let (_out_len, out_ty) = require_simd!(ret_ty, SimdReturn);
require!(
args[0].layout.ty == out_ty,
InvalidMonomorphization::ExpectedVectorElementType {
span,
name,
expected_element: out_ty,
vector_type: ret_ty,
}
);
// `insertelement <N x elem> poison, elem %x, i32 0`
let poison_vec = bx.const_poison(llret_ty);
let idx0 = bx.const_i32(0);
let v0 = bx.insert_element(poison_vec, args[0].immediate(), idx0);
// `shufflevector <N x elem> v0, <N x elem> poison, <N x i32> zeroinitializer`
// The masks is all zeros, so this splats lane 0 (which has our element in it).
let splat = bx.shuffle_vector(v0, poison_vec, bx.const_null(llret_ty));
return Ok(splat);
}
// every intrinsic below takes a SIMD vector as its first argument
let (in_len, in_elem) = require_simd!(args[0].layout.ty, SimdInput);
let in_ty = args[0].layout.ty;

View File

@@ -1074,8 +1074,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
if constant_ty.is_simd() {
// However, some SIMD types do not actually use the vector ABI
// (in particular, packed SIMD types do not). Ensure we exclude those.
//
// We also have to exclude vectors of pointers because `immediate_const_vector`
// does not work for those.
let layout = bx.layout_of(constant_ty);
if let BackendRepr::SimdVector { .. } = layout.backend_repr {
let (_, element_ty) = constant_ty.simd_size_and_type(bx.tcx());
if let BackendRepr::SimdVector { .. } = layout.backend_repr
&& element_ty.is_numeric()
{
let (llval, ty) = self.immediate_const_vector(bx, constant);
return OperandRef {
val: OperandValue::Immediate(llval),

View File

@@ -61,6 +61,15 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
}
self.copy_op(&self.project_index(&input, index)?, &dest)?;
}
sym::simd_splat => {
let elem = &args[0];
let (dest, dest_len) = self.project_to_simd(&dest)?;
for i in 0..dest_len {
let place = self.project_index(&dest, i)?;
self.copy_op(elem, &place)?;
}
}
sym::simd_neg
| sym::simd_fabs
| sym::simd_ceil

View File

@@ -746,6 +746,7 @@ pub(crate) fn check_intrinsic_type(
sym::simd_extract | sym::simd_extract_dyn => {
(2, 0, vec![param(0), tcx.types.u32], param(1))
}
sym::simd_splat => (2, 0, vec![param(1)], param(0)),
sym::simd_cast
| sym::simd_as
| sym::simd_cast_ptr

View File

@@ -2141,6 +2141,7 @@ symbols! {
simd_shr,
simd_shuffle,
simd_shuffle_const_generic,
simd_splat,
simd_sub,
simd_trunc,
simd_with_exposed_provenance,

View File

@@ -1746,10 +1746,14 @@ supported_targets! {
("mipsel-unknown-none", mipsel_unknown_none),
("mips-mti-none-elf", mips_mti_none_elf),
("mipsel-mti-none-elf", mipsel_mti_none_elf),
("thumbv4t-none-eabi", thumbv4t_none_eabi),
("armv4t-none-eabi", armv4t_none_eabi),
("thumbv5te-none-eabi", thumbv5te_none_eabi),
("armv5te-none-eabi", armv5te_none_eabi),
("armv6-none-eabi", armv6_none_eabi),
("armv6-none-eabihf", armv6_none_eabihf),
("thumbv4t-none-eabi", thumbv4t_none_eabi),
("thumbv5te-none-eabi", thumbv5te_none_eabi),
("thumbv6-none-eabi", thumbv6_none_eabi),
("aarch64_be-unknown-linux-gnu", aarch64_be_unknown_linux_gnu),
("aarch64-unknown-linux-gnu_ilp32", aarch64_unknown_linux_gnu_ilp32),

View File

@@ -1,4 +1,4 @@
//! Targets the ARMv4T, with code as `a32` code by default.
//! Targets the ARMv4T architecture, with `a32` code by default.
//!
//! Primarily of use for the GBA, but usable with other devices too.
//!

View File

@@ -1,4 +1,4 @@
//! Targets the ARMv5TE, with code as `a32` code by default.
//! Targets the ARMv5TE architecture, with `a32` code by default.
use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base, cvs};

View File

@@ -0,0 +1,29 @@
//! Targets the ARMv6K architecture, with `a32` code by default.
use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base, cvs};
pub(crate) fn target() -> Target {
Target {
llvm_target: "armv6-none-eabi".into(),
metadata: TargetMetadata {
description: Some("Bare ARMv6 soft-float".into()),
tier: Some(3),
host_tools: Some(false),
std: Some(false),
},
pointer_width: 32,
arch: Arch::Arm,
data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
options: TargetOptions {
abi: Abi::Eabi,
llvm_floatabi: Some(FloatAbi::Soft),
asm_args: cvs!["-mthumb-interwork", "-march=armv6", "-mlittle-endian",],
features: "+soft-float,+strict-align,+v6k".into(),
atomic_cas: true,
has_thumb_interworking: true,
// LDREXD/STREXD available as of ARMv6K
max_atomic_width: Some(64),
..base::arm_none::opts()
},
}
}

View File

@@ -0,0 +1,29 @@
//! Targets the ARMv6K architecture, with `a32` code by default, and hard-float ABI
use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base, cvs};
pub(crate) fn target() -> Target {
Target {
llvm_target: "armv6-none-eabihf".into(),
metadata: TargetMetadata {
description: Some("Bare ARMv6 hard-float".into()),
tier: Some(3),
host_tools: Some(false),
std: Some(false),
},
pointer_width: 32,
arch: Arch::Arm,
data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
options: TargetOptions {
abi: Abi::EabiHf,
llvm_floatabi: Some(FloatAbi::Hard),
asm_args: cvs!["-mthumb-interwork", "-march=armv6", "-mlittle-endian",],
features: "+strict-align,+v6k,+vfp2,-d32".into(),
atomic_cas: true,
has_thumb_interworking: true,
// LDREXD/STREXD available as of ARMv6K
max_atomic_width: Some(64),
..base::arm_none::opts()
},
}
}

View File

@@ -17,8 +17,8 @@ pub(crate) fn target() -> Target {
llvm_target: "powerpc64-unknown-linux-musl".into(),
metadata: TargetMetadata {
description: Some("64-bit PowerPC Linux with musl 1.2.5".into()),
tier: Some(3),
host_tools: Some(false),
tier: Some(2),
host_tools: Some(true),
std: Some(true),
},
pointer_width: 64,

View File

@@ -1,4 +1,4 @@
//! Targets the ARMv4T, with code as `t32` code by default.
//! Targets the ARMv4T architecture, with `t32` code by default.
//!
//! Primarily of use for the GBA, but usable with other devices too.
//!

View File

@@ -1,4 +1,4 @@
//! Targets the ARMv5TE, with code as `t32` code by default.
//! Targets the ARMv5TE architecture, with `t32` code by default.
use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base, cvs};

View File

@@ -0,0 +1,30 @@
//! Targets the ARMv6K architecture, with `t32` code by default.
use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base, cvs};
pub(crate) fn target() -> Target {
Target {
llvm_target: "thumbv6-none-eabi".into(),
metadata: TargetMetadata {
description: Some("Thumb-mode Bare ARMv6 soft-float".into()),
tier: Some(3),
host_tools: Some(false),
std: Some(false),
},
pointer_width: 32,
arch: Arch::Arm,
data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
options: TargetOptions {
abi: Abi::Eabi,
llvm_floatabi: Some(FloatAbi::Soft),
asm_args: cvs!["-mthumb-interwork", "-march=armv6", "-mlittle-endian",],
features: "+soft-float,+strict-align,+v6k".into(),
// CAS atomics are implemented in LLVM on this target using __sync* functions,
// which were added to compiler-builtins in https://github.com/rust-lang/compiler-builtins/pull/1050
atomic_cas: true,
has_thumb_interworking: true,
max_atomic_width: Some(32),
..base::arm_none::opts()
},
}
}

View File

@@ -292,9 +292,18 @@ pub fn spin_loop() {
// SAFETY: the `cfg` attr ensures that we only execute this on aarch64 targets.
unsafe { crate::arch::aarch64::__isb(crate::arch::aarch64::SY) }
}
all(target_arch = "arm", target_feature = "v6") => {
// SAFETY: the `cfg` attr ensures that we only execute this on arm targets
// with support for the v6 feature.
all(
target_arch = "arm",
any(
all(target_feature = "v6k", not(target_feature = "thumb-mode")),
target_feature = "v6t2",
all(target_feature = "v6", target_feature = "mclass"),
)
) => {
// SAFETY: the `cfg` attr ensures that we only execute this on arm
// targets with support for the this feature. On ARMv6 in Thumb
// mode, T2 is required (see Arm DDI0406C Section A8.8.427),
// otherwise ARMv6-M or ARMv6K is enough
unsafe { crate::arch::arm::__yield() }
}
target_arch = "loongarch32" => crate::arch::loongarch32::ibar::<0>(),

View File

@@ -52,6 +52,13 @@ pub const unsafe fn simd_insert_dyn<T, U>(x: T, idx: u32, val: U) -> T;
#[rustc_intrinsic]
pub const unsafe fn simd_extract_dyn<T, U>(x: T, idx: u32) -> U;
/// Creates a vector where every lane has the provided value.
///
/// `T` must be a vector with element type `U`.
#[rustc_nounwind]
#[rustc_intrinsic]
pub const unsafe fn simd_splat<T, U>(value: U) -> T;
/// Adds two simd vectors elementwise.
///
/// `T` must be a vector of integers or floats.

View File

@@ -8,10 +8,10 @@ use crate::ffi::OsString;
///
/// # Underlying system calls
///
/// | Platform | System call |
/// |----------|---------------------------------------------------------------------------------------------------------|
/// | UNIX | [`gethostname`](https://www.man7.org/linux/man-pages/man2/gethostname.2.html) |
/// | Windows | [`GetHostNameW`](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-gethostnamew) |
/// | Platform | System call |
/// |--------------|---------------------------------------------------------------------------------------------------------|
/// | UNIX | [`gethostname`](https://www.man7.org/linux/man-pages/man2/gethostname.2.html) |
/// | Windows (8+) | [`GetHostNameW`](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-gethostnamew) |
///
/// Note that platform-specific behavior [may change in the future][changes].
///

View File

@@ -3,7 +3,8 @@ cfg_select! {
mod unix;
pub use unix::hostname;
}
target_os = "windows" => {
// `GetHostNameW` is only available starting with Windows 8.
all(target_os = "windows", not(target_vendor = "win7")) => {
mod windows;
pub use windows::hostname;
}

View File

@@ -237,3 +237,7 @@ cfg_select! {
}
_ => {}
}
// Only available starting with Windows 8.
#[cfg(not(target_vendor = "win7"))]
windows_targets::link!("ws2_32.dll" "system" fn GetHostNameW(name : PWSTR, namelen : i32) -> i32);

View File

@@ -2170,7 +2170,6 @@ GetFileType
GETFINALPATHNAMEBYHANDLE_FLAGS
GetFinalPathNameByHandleW
GetFullPathNameW
GetHostNameW
GetLastError
GetModuleFileNameW
GetModuleHandleA

View File

@@ -49,7 +49,6 @@ windows_targets::link!("kernel32.dll" "system" fn GetFileSizeEx(hfile : HANDLE,
windows_targets::link!("kernel32.dll" "system" fn GetFileType(hfile : HANDLE) -> FILE_TYPE);
windows_targets::link!("kernel32.dll" "system" fn GetFinalPathNameByHandleW(hfile : HANDLE, lpszfilepath : PWSTR, cchfilepath : u32, dwflags : GETFINALPATHNAMEBYHANDLE_FLAGS) -> u32);
windows_targets::link!("kernel32.dll" "system" fn GetFullPathNameW(lpfilename : PCWSTR, nbufferlength : u32, lpbuffer : PWSTR, lpfilepart : *mut PWSTR) -> u32);
windows_targets::link!("ws2_32.dll" "system" fn GetHostNameW(name : PWSTR, namelen : i32) -> i32);
windows_targets::link!("kernel32.dll" "system" fn GetLastError() -> WIN32_ERROR);
windows_targets::link!("kernel32.dll" "system" fn GetModuleFileNameW(hmodule : HMODULE, lpfilename : PWSTR, nsize : u32) -> u32);
windows_targets::link!("kernel32.dll" "system" fn GetModuleHandleA(lpmodulename : PCSTR) -> HMODULE);

View File

@@ -91,7 +91,7 @@ cfg_select! {
}
target_os = "vexos" => {
mod vexos;
pub use vexos::{sleep, yield_now};
pub use vexos::{sleep, sleep_until, yield_now};
#[expect(dead_code)]
mod unsupported;
pub use unsupported::{Thread, available_parallelism, current_os_id, set_name, DEFAULT_MIN_STACK_SIZE};
@@ -135,6 +135,8 @@ cfg_select! {
target_os = "vxworks",
target_os = "wasi",
target_vendor = "apple",
target_os = "motor",
target_os = "vexos"
)))]
pub fn sleep_until(deadline: crate::time::Instant) {
use crate::time::Instant;

View File

@@ -3,7 +3,7 @@ use crate::io;
use crate::num::NonZeroUsize;
use crate::sys::map_motor_error;
use crate::thread::ThreadInit;
use crate::time::Duration;
use crate::time::{Duration, Instant};
pub const DEFAULT_MIN_STACK_SIZE: usize = 1024 * 256;
@@ -62,3 +62,7 @@ pub fn yield_now() {
pub fn sleep(dur: Duration) {
moto_rt::thread::sleep_until(moto_rt::time::Instant::now() + dur)
}
pub fn sleep_until(deadline: Instant) {
moto_rt::thread::sleep_until(deadline.into_inner())
}

View File

@@ -647,6 +647,56 @@ pub fn sleep(dur: Duration) {
pub fn sleep_until(deadline: crate::time::Instant) {
use crate::time::Instant;
#[cfg(all(
target_os = "linux",
target_env = "gnu",
target_pointer_width = "32",
not(target_arch = "riscv32")
))]
{
use crate::sys::pal::time::__timespec64;
use crate::sys::pal::weak::weak;
// This got added in glibc 2.31, along with a 64-bit `clock_gettime`
// function.
weak! {
fn __clock_nanosleep_time64(
clock_id: libc::clockid_t,
flags: libc::c_int,
req: *const __timespec64,
rem: *mut __timespec64,
) -> libc::c_int;
}
if let Some(clock_nanosleep) = __clock_nanosleep_time64.get() {
let ts = deadline.into_inner().into_timespec().to_timespec64();
loop {
let r = unsafe {
clock_nanosleep(
crate::sys::time::Instant::CLOCK_ID,
libc::TIMER_ABSTIME,
&ts,
core::ptr::null_mut(),
)
};
match r {
0 => return,
libc::EINTR => continue,
// If the underlying kernel doesn't support the 64-bit
// syscall, `__clock_nanosleep_time64` will fail. The
// error code nowadays is EOVERFLOW, but it used to be
// ENOSYS so just don't rely on any particular value.
// The parameters are all valid, so the only reasons
// why the call might fail are EINTR and the call not
// being supported. Fall through to the clamping version
// in that case.
_ => break,
}
}
}
}
let Some(ts) = deadline.into_inner().into_timespec().to_timespec() else {
// The deadline is further in the future then can be passed to
// clock_nanosleep. We have to use Self::sleep instead. This might

View File

@@ -10,8 +10,12 @@ pub fn sleep(dur: Duration) {
let start = Instant::now();
while start.elapsed() < dur {
unsafe {
vex_sdk::vexTasksRun();
}
yield_now();
}
}
pub fn sleep_until(deadline: Instant) {
while Instant::now() < deadline {
yield_now();
}
}

View File

@@ -83,8 +83,11 @@ pub unsafe fn __sevl() {
/// improve overall system performance.
// Section 10.1 of ACLE says that the supported arches are: 8, 6K, 6-M
// LLVM says "instruction requires: armv6k"
// On ARMv6 in Thumb mode, T2 is required (see Arm DDI0406C Section A8.8.427)
#[cfg(any(
target_feature = "v6",
all(target_feature = "v6k", not(target_feature = "thumb-mode")),
target_feature = "v6t2",
all(target_feature = "v6", target_feature = "mclass"),
target_arch = "aarch64",
target_arch = "arm64ec",
doc

View File

@@ -75,7 +75,7 @@ book!(
EditionGuide, "src/doc/edition-guide", "edition-guide", &[];
EmbeddedBook, "src/doc/embedded-book", "embedded-book", &[];
Nomicon, "src/doc/nomicon", "nomicon", &[];
RustByExample, "src/doc/rust-by-example", "rust-by-example", &["es", "ja", "zh"];
RustByExample, "src/doc/rust-by-example", "rust-by-example", &["es", "ja", "zh", "ko"];
RustdocBook, "src/doc/rustdoc", "rustdoc", &[];
StyleGuide, "src/doc/style-guide", "style-guide", &[];
);

View File

@@ -244,6 +244,7 @@ pub(crate) fn is_ci_llvm_available_for_target(
("loongarch64-unknown-linux-musl", false),
("powerpc-unknown-linux-gnu", false),
("powerpc64-unknown-linux-gnu", false),
("powerpc64-unknown-linux-musl", false),
("powerpc64le-unknown-linux-gnu", false),
("powerpc64le-unknown-linux-musl", false),
("riscv64gc-unknown-linux-gnu", false),

View File

@@ -460,6 +460,7 @@ pub(crate) fn is_download_ci_available(target_triple: &str, llvm_assertions: boo
"loongarch64-unknown-linux-gnu",
"powerpc-unknown-linux-gnu",
"powerpc64-unknown-linux-gnu",
"powerpc64-unknown-linux-musl",
"powerpc64le-unknown-linux-gnu",
"powerpc64le-unknown-linux-musl",
"riscv64gc-unknown-linux-gnu",

View File

@@ -43,6 +43,9 @@ const STAGE0_MISSING_TARGETS: &[&str] = &[
"thumbv7r-none-eabi",
"thumbv7r-none-eabihf",
"thumbv8r-none-eabihf",
"armv6-none-eabi",
"armv6-none-eabihf",
"thumbv6-none-eabi",
];
/// Minimum version threshold for libstdc++ required when using prebuilt LLVM

View File

@@ -11,7 +11,7 @@ RUN sh /scripts/rustbuild-setup.sh
WORKDIR /tmp
COPY scripts/crosstool-ng-build.sh /scripts/
COPY host-x86_64/dist-powerpc64-linux/powerpc64-linux-gnu.defconfig /tmp/crosstool.defconfig
COPY host-x86_64/dist-powerpc64-linux-gnu/powerpc64-linux-gnu.defconfig /tmp/crosstool.defconfig
RUN /scripts/crosstool-ng-build.sh
COPY scripts/sccache.sh /scripts/

View File

@@ -0,0 +1,39 @@
FROM ubuntu:22.04
COPY scripts/cross-apt-packages.sh /scripts/
RUN sh /scripts/cross-apt-packages.sh
COPY scripts/crosstool-ng.sh /scripts/
RUN sh /scripts/crosstool-ng.sh
COPY scripts/rustbuild-setup.sh /scripts/
RUN sh /scripts/rustbuild-setup.sh
WORKDIR /tmp
COPY scripts/crosstool-ng-build.sh /scripts/
COPY host-x86_64/dist-powerpc64-linux-musl/powerpc64-unknown-linux-musl.defconfig /tmp/crosstool.defconfig
RUN /scripts/crosstool-ng-build.sh
COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh
ENV PATH=$PATH:/x-tools/powerpc64-unknown-linux-musl/bin
ENV \
AR_powerpc64_unknown_linux_musl=powerpc64-unknown-linux-musl-ar \
CC_powerpc64_unknown_linux_musl=powerpc64-unknown-linux-musl-gcc \
CXX_powerpc64_unknown_linux_musl=powerpc64-unknown-linux-musl-g++
ENV HOSTS=powerpc64-unknown-linux-musl
ENV RUST_CONFIGURE_ARGS \
--enable-extended \
--enable-full-tools \
--enable-profiler \
--enable-sanitizers \
--disable-docs \
--set target.powerpc64-unknown-linux-musl.crt-static=false \
--musl-root-powerpc64=/x-tools/powerpc64-unknown-linux-musl/powerpc64-unknown-linux-musl/sysroot/usr
ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS

View File

@@ -0,0 +1,15 @@
CT_CONFIG_VERSION="4"
CT_EXPERIMENTAL=y
CT_PREFIX_DIR="/x-tools/${CT_TARGET}"
CT_USE_MIRROR=y
CT_MIRROR_BASE_URL="https://ci-mirrors.rust-lang.org/rustc"
CT_ARCH_POWERPC=y
CT_ARCH_64=y
CT_ARCH_ABI="elfv2"
# CT_DEMULTILIB is not set
CT_KERNEL_LINUX=y
CT_LINUX_V_4_19=y
CT_LIBC_MUSL=y
CT_MUSL_V_1_2_5=y
CT_CC_LANG_CXX=y
CT_GETTEXT_NEEDED=y

View File

@@ -232,7 +232,10 @@ auto:
- name: dist-powerpc-linux
<<: *job-linux-4c
- name: dist-powerpc64-linux
- name: dist-powerpc64-linux-gnu
<<: *job-linux-4c
- name: dist-powerpc64-linux-musl
<<: *job-linux-4c
- name: dist-powerpc64le-linux-gnu

View File

@@ -665,7 +665,9 @@ to link to the extern crate to make the crate be available as an extern prelude.
That allows you to specify the additional syntax of the `--extern` flag, such as
renaming a dependency. For example, `//@ aux-crate:foo=bar.rs` will compile
`auxiliary/bar.rs` and make it available under then name `foo` within the test.
This is similar to how Cargo does dependency renaming.
This is similar to how Cargo does dependency renaming. It is also possible to
specify [`--extern` modifiers](https://github.com/rust-lang/rust/issues/98405).
For example, `//@ aux-crate:noprelude:foo=bar.rs`.
`aux-bin` is similar to `aux-build` but will build a binary instead of a
library. The binary will be available in `auxiliary/bin` relative to the working

View File

@@ -53,14 +53,14 @@ Directives can generally be found by browsing the
See [Building auxiliary crates](compiletest.html#building-auxiliary-crates)
| Directive | Explanation | Supported test suites | Possible values |
|-----------------------|-------------------------------------------------------------------------------------------------------|----------------------------------------|-----------------------------------------------|
| `aux-bin` | Build a aux binary, made available in `auxiliary/bin` relative to test directory | All except `run-make`/`run-make-cargo` | Path to auxiliary `.rs` file |
| `aux-build` | Build a separate crate from the named source file | All except `run-make`/`run-make-cargo` | Path to auxiliary `.rs` file |
| `aux-crate` | Like `aux-build` but makes available as extern prelude | All except `run-make`/`run-make-cargo` | `<extern_prelude_name>=<path/to/aux/file.rs>` |
| `aux-codegen-backend` | Similar to `aux-build` but pass the compiled dylib to `-Zcodegen-backend` when building the main file | `ui-fulldeps` | Path to codegen backend file |
| `proc-macro` | Similar to `aux-build`, but for aux forces host and don't use `-Cprefer-dynamic`[^pm]. | All except `run-make`/`run-make-cargo` | Path to auxiliary proc-macro `.rs` file |
| `build-aux-docs` | Build docs for auxiliaries as well. Note that this only works with `aux-build`, not `aux-crate`. | All except `run-make`/`run-make-cargo` | N/A |
| Directive | Explanation | Supported test suites | Possible values |
|-----------------------|-------------------------------------------------------------------------------------------------------|----------------------------------------|--------------------------------------------------------------------|
| `aux-bin` | Build a aux binary, made available in `auxiliary/bin` relative to test directory | All except `run-make`/`run-make-cargo` | Path to auxiliary `.rs` file |
| `aux-build` | Build a separate crate from the named source file | All except `run-make`/`run-make-cargo` | Path to auxiliary `.rs` file |
| `aux-crate` | Like `aux-build` but makes available as extern prelude | All except `run-make`/`run-make-cargo` | `[<extern_modifiers>:]<extern_prelude_name>=<path/to/aux/file.rs>` |
| `aux-codegen-backend` | Similar to `aux-build` but pass the compiled dylib to `-Zcodegen-backend` when building the main file | `ui-fulldeps` | Path to codegen backend file |
| `proc-macro` | Similar to `aux-build`, but for aux forces host and don't use `-Cprefer-dynamic`[^pm]. | All except `run-make`/`run-make-cargo` | Path to auxiliary proc-macro `.rs` file |
| `build-aux-docs` | Build docs for auxiliaries as well. Note that this only works with `aux-build`, not `aux-crate`. | All except `run-make`/`run-make-cargo` | N/A |
[^pm]: please see the [Auxiliary proc-macro section](compiletest.html#auxiliary-proc-macro) in the compiletest chapter for specifics.

View File

@@ -56,6 +56,7 @@
- [arm-none-eabi](platform-support/arm-none-eabi.md)
- [{arm,thumb}v4t-none-eabi](platform-support/armv4t-none-eabi.md)
- [{arm,thumb}v5te-none-eabi](platform-support/armv5te-none-eabi.md)
- [{arm,thumb}v6-none-eabi{,hf}](platform-support/armv6-none-eabi.md)
- [{arm,thumb}v7a-none-eabi{,hf}](platform-support/armv7a-none-eabi.md)
- [{arm,thumb}v7r-none-eabi{,hf}](platform-support/armv7r-none-eabi.md)
- [{arm,thumb}v8r-none-eabihf](platform-support/armv8r-none-eabihf.md)

View File

@@ -100,6 +100,7 @@ target | notes
[`i686-pc-windows-gnu`](platform-support/windows-gnu.md) | 32-bit MinGW (Windows 10+, Windows Server 2016+, Pentium 4) [^x86_32-floats-return-ABI] [^win32-msvc-alignment]
`powerpc-unknown-linux-gnu` | PowerPC Linux (kernel 3.2+, glibc 2.17)
`powerpc64-unknown-linux-gnu` | PPC64 Linux (kernel 3.2+, glibc 2.17)
[`powerpc64-unknown-linux-musl`](platform-support/powerpc64-unknown-linux-musl.md) | PPC64 Linux (kernel 4.19+, musl 1.2.5)
[`powerpc64le-unknown-linux-gnu`](platform-support/powerpc64le-unknown-linux-gnu.md) | PPC64LE Linux (kernel 3.10+, glibc 2.17)
[`powerpc64le-unknown-linux-musl`](platform-support/powerpc64le-unknown-linux-musl.md) | PPC64LE Linux (kernel 4.19+, musl 1.2.5)
[`riscv64gc-unknown-linux-gnu`](platform-support/riscv64gc-unknown-linux-gnu.md) | RISC-V Linux (kernel 4.20+, glibc 2.29)
@@ -292,6 +293,8 @@ target | std | host | notes
`armv4t-unknown-linux-gnueabi` | ? | | Armv4T Linux
[`armv5te-none-eabi`](platform-support/armv5te-none-eabi.md) | * | | Bare Armv5TE
`armv5te-unknown-linux-uclibceabi` | ? | | Armv5TE Linux with uClibc
[`armv6-none-eabi`](platform-support/armv6-none-eabi.md) | * | | Bare Armv6
[`armv6-none-eabihf`](platform-support/armv6-none-eabi.md) | * | | Bare Armv6, hardfloat
[`armv6-unknown-freebsd`](platform-support/freebsd.md) | ✓ | ✓ | Armv6 FreeBSD
[`armv6-unknown-netbsd-eabihf`](platform-support/netbsd.md) | ✓ | ✓ | Armv6 NetBSD w/hard-float
[`armv6k-nintendo-3ds`](platform-support/armv6k-nintendo-3ds.md) | ? | | Armv6k Nintendo 3DS, Horizon (Requires devkitARM toolchain)
@@ -371,7 +374,6 @@ target | std | host | notes
[`powerpc-wrs-vxworks-spe`](platform-support/vxworks.md) | ✓ | |
[`powerpc64-ibm-aix`](platform-support/aix.md) | ? | | 64-bit AIX (7.2 and newer)
[`powerpc64-unknown-freebsd`](platform-support/freebsd.md) | ✓ | ✓ | PPC64 FreeBSD (ELFv2)
[`powerpc64-unknown-linux-musl`](platform-support/powerpc64-unknown-linux-musl.md) | ✓ | ✓ | PPC64 Linux (kernel 4.19, musl 1.2.5)
[`powerpc64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/powerpc64
[`powerpc64-wrs-vxworks`](platform-support/vxworks.md) | ✓ | |
[`powerpc64le-unknown-freebsd`](platform-support/freebsd.md) | ✓ | ✓ | PPC64LE FreeBSD
@@ -410,6 +412,7 @@ target | std | host | notes
[`sparc64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/sparc64
[`thumbv4t-none-eabi`](platform-support/armv4t-none-eabi.md) | * | | Thumb-mode Bare Armv4T
[`thumbv5te-none-eabi`](platform-support/armv5te-none-eabi.md) | * | | Thumb-mode Bare Armv5TE
[`thumbv6-none-eabi`](platform-support/armv6-none-eabi.md) | * | | Thumb-mode Bare Armv6
[`thumbv6m-nuttx-eabi`](platform-support/nuttx.md) | ✓ | | ARMv6M with NuttX
[`thumbv7a-none-eabi`](platform-support/armv7a-none-eabi.md) | * | | Thumb-mode Bare Armv7-A
[`thumbv7a-none-eabihf`](platform-support/armv7a-none-eabi.md) | * | | Thumb-mode Bare Armv7-A, hardfloat

View File

@@ -37,6 +37,7 @@ their own document.
- *Legacy* Arm Architectures
- [`armv4t-none-eabi` and `thumbv4t-none-eabi`](armv4t-none-eabi.md)
- [`armv5te-none-eabi` and `thumbv5te-none-eabi`](armv5te-none-eabi.md)
- [`armv6-none-eabi`, `armv6-none-eabihf`, `thumbv6-none-eabi`](armv6-none-eabi.md)
## Instruction Sets

View File

@@ -0,0 +1,39 @@
# `armv6-none-eabi*` and `thumbv6-none-eabi`
* **Tier: 3**
* **Library Support:** core and alloc (bare-metal, `#![no_std]`)
Bare-metal target for any cpu in the Armv6 architecture family, supporting
ARM/Thumb code interworking (aka `Arm`/`Thumb`), with `Arm` code as the default
code generation. The most common processor family using the Armv6 architecture
is the ARM11, which includes the ARM1176JZF-S used in the original Raspberry Pi
and in the Raspberry Pi Zero.
This target assumes your processor has the Armv6K extensions, as basically all
Armv6 processors do[^1]. The Armv6K extension adds the `LDREXB` and `STREXB`
instructions required to efficiently implement CAS on the [`AtomicU8`] and
[`AtomicI8`] types.
The `thumbv6-none-eabi` target is the same as this one, but the instruction set
defaults to `Thumb`. Note that this target only supports the old Thumb-1
instruction set, not the later Thumb-2 instruction set that was added in the
Armv6T2 extension. Note that the Thumb-1 instruction set does not support
atomics.
The `armv6-none-eabihf` target uses the EABIHF hard-float ABI, and requires an
FPU - it assumes a VFP2D16 FPU is present. The FPU is not available from Thumb
mode so there is no `thumbv6-none-eabihf` target.
See [`arm-none-eabi`](arm-none-eabi.md) for information applicable to all
`arm-none-eabi` targets.
[`AtomicU8`]: https://docs.rust-lang.org/stable/core/sync/atomic/struct.AtomicU8.html
[`AtomicI8`]: https://docs.rust-lang.org/stable/core/sync/atomic/struct.AtomicI8.html
## Target Maintainers
[@thejpster](https://github.com/thejpster)
[^1]: The only ARMv6 processor without the Armv6k extensions is the first (r0)
revision of the ARM1136 - in the unlikely event you have a chip with one of
these processors, use the ARMv5TE target instead.

View File

@@ -1,10 +1,13 @@
# powerpc64-unknown-linux-musl
**Tier: 3**
**Tier: 2**
Target for 64-bit big endian PowerPC Linux programs using musl libc.
This target uses the ELF v2 ABI.
The baseline CPU required is a PowerPC 970, which means AltiVec is required and
the oldest IBM server CPU supported is therefore POWER6.
## Target maintainers
[@Gelbpunkt](https://github.com/Gelbpunkt)
@@ -38,9 +41,8 @@ linker = "powerpc64-linux-musl-gcc"
## Building Rust programs
Rust does not yet ship pre-compiled artifacts for this target. To compile for
this target, you will first need to build Rust with the target enabled (see
"Building the target" above).
This target is distributed through `rustup`, and otherwise requires no
special configuration.
## Cross-compilation

View File

@@ -18,7 +18,7 @@ This gets called by `promote-release` <https://github.com/rust-lang/promote-rele
a. If appropriate, call `tarball.is_preview(true)` for the component.
2. Add a new `PkgType` to build-manifest. Fix all the compile errors as appropriate.
## Testing changes locally
## Testing changes locally with rustup
In order to test the changes locally you need to have a valid dist directory
available locally. If you don't want to build all the compiler, you can easily
@@ -26,14 +26,32 @@ create one from the nightly artifacts with:
```sh
for component in rust rustc rust-std rust-docs cargo; do
wget -P build/dist https://static.rust-lang.org/dist/${component}-nightly-x86_64-unknown-linux-gnu.tar.gz
wget -P build/dist https://static.rust-lang.org/dist/${component}-nightly-x86_64-unknown-linux-gnu.tar.xz
done
```
Then, you can generate the manifest and all the packages from `build/dist` to
`build/manifest` with:
Then, you can generate the manifest and add it to `build/dist`:
```sh
mkdir -p build/manifest
cargo +nightly run --release -p build-manifest build/dist build/manifest 1970-01-01 http://example.com nightly
cargo +nightly run --release -p build-manifest build/dist build/dist 1970-01-01 http://localhost:8000 nightly
```
After that, generate a SHA256 stamp for the manifest file:
```sh
sha256sum build/dist/channel-rust-nightly.toml > build/dist/channel-rust-nightly.toml.sha256
```
And start a HTTP server from the `build` directory:
```sh
cd build
python3 -m http.server 8000
```
After you do all that, you can then install the locally generated components with rustup:
```
rustup uninstall nightly
RUSTUP_DIST_SERVER=http://localhost:8000 rustup toolchain install nightly --profile minimal
RUSTUP_DIST_SERVER=http://localhost:8000 rustup +nightly component add <my-new-component>
```
Note that generally it will not work to combine components built locally and those built from CI (nightly). Ideally, if you want to ship new rustup components, first dist them in nightly, and then test everything from nightly here after it's available on CI.

View File

@@ -6,12 +6,20 @@ use std::iter;
use super::directives::{AUX_BIN, AUX_BUILD, AUX_CODEGEN_BACKEND, AUX_CRATE, PROC_MACRO};
use crate::common::Config;
use crate::directives::DirectiveLine;
use crate::util::static_regex;
#[cfg(test)]
mod tests;
/// The value of an `aux-crate` directive.
#[derive(Clone, Debug, Default)]
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct AuxCrate {
/// Contains `--extern` modifiers, if any. See the tracking issue for more
/// info: <https://github.com/rust-lang/rust/issues/98405>
/// With `aux-crate: noprelude:foo=bar.rs` this will be `noprelude`.
pub extern_modifiers: Option<String>,
/// With `aux-crate: foo=bar.rs` this will be `foo`.
/// With `aux-crate: noprelude:foo=bar.rs` this will be `noprelude:foo`.
/// With `aux-crate: noprelude:foo=bar.rs` this will be `foo`.
pub name: String,
/// With `aux-crate: foo=bar.rs` this will be `bar.rs`.
pub path: String,
@@ -74,9 +82,20 @@ pub(super) fn parse_and_update_aux(
}
fn parse_aux_crate(r: String) -> AuxCrate {
let mut parts = r.trim().splitn(2, '=');
AuxCrate {
name: parts.next().expect("missing aux-crate name (e.g. log=log.rs)").to_string(),
path: parts.next().expect("missing aux-crate value (e.g. log=log.rs)").to_string(),
}
let r = r.trim();
// Matches:
// name=path
// modifiers:name=path
let caps = static_regex!(r"^(?:(?<modifiers>[^=]*?):)?(?<name>[^=]*)=(?<path>.*)$")
.captures(r)
.unwrap_or_else(|| {
panic!("couldn't parse aux-crate value `{r}` (should be e.g. `log=log.rs`)")
});
let modifiers = caps.name("modifiers").map(|m| m.as_str().to_string());
let name = caps["name"].to_string();
let path = caps["path"].to_string();
AuxCrate { extern_modifiers: modifiers, name, path }
}

View File

@@ -0,0 +1,27 @@
use super::*;
#[test]
fn test_aux_crate_value_no_modifiers() {
assert_eq!(
AuxCrate { extern_modifiers: None, name: "foo".to_string(), path: "foo.rs".to_string() },
parse_aux_crate("foo=foo.rs".to_string())
);
}
#[test]
fn test_aux_crate_value_with_modifiers() {
assert_eq!(
AuxCrate {
extern_modifiers: Some("noprelude".to_string()),
name: "foo".to_string(),
path: "foo.rs".to_string()
},
parse_aux_crate("noprelude:foo=foo.rs".to_string())
);
}
#[test]
#[should_panic(expected = "couldn't parse aux-crate value `foo.rs` (should be e.g. `log=log.rs`)")]
fn test_aux_crate_value_invalid() {
parse_aux_crate("foo.rs".to_string());
}

View File

@@ -1277,23 +1277,36 @@ impl<'test> TestCx<'test> {
.replace('-', "_")
};
let add_extern =
|rustc: &mut Command, aux_name: &str, aux_path: &str, aux_type: AuxType| {
let lib_name = get_lib_name(&path_to_crate_name(aux_path), aux_type);
if let Some(lib_name) = lib_name {
rustc.arg("--extern").arg(format!("{}={}/{}", aux_name, aux_dir, lib_name));
}
};
let add_extern = |rustc: &mut Command,
extern_modifiers: Option<&str>,
aux_name: &str,
aux_path: &str,
aux_type: AuxType| {
let lib_name = get_lib_name(&path_to_crate_name(aux_path), aux_type);
if let Some(lib_name) = lib_name {
let modifiers_and_name = match extern_modifiers {
Some(modifiers) => format!("{modifiers}:{aux_name}"),
None => aux_name.to_string(),
};
rustc.arg("--extern").arg(format!("{modifiers_and_name}={aux_dir}/{lib_name}"));
}
};
for AuxCrate { name, path } in &self.props.aux.crates {
for AuxCrate { extern_modifiers, name, path } in &self.props.aux.crates {
let aux_type = self.build_auxiliary(&path, &aux_dir, None);
add_extern(rustc, name, path, aux_type);
add_extern(rustc, extern_modifiers.as_deref(), name, path, aux_type);
}
for proc_macro in &self.props.aux.proc_macros {
self.build_auxiliary(proc_macro, &aux_dir, Some(AuxType::ProcMacro));
let crate_name = path_to_crate_name(proc_macro);
add_extern(rustc, &crate_name, proc_macro, AuxType::ProcMacro);
add_extern(
rustc,
None, // `extern_modifiers`
&crate_name,
proc_macro,
AuxType::ProcMacro,
);
}
// Build any `//@ aux-codegen-backend`, and pass the resulting library

View File

@@ -55,7 +55,7 @@ impl<'tcx> MiriMachine<'tcx> {
Os::Linux => {
Self::null_ptr_extern_statics(
ecx,
&["__cxa_thread_atexit_impl", "__clock_gettime64"],
&["__cxa_thread_atexit_impl", "__clock_gettime64", "__clock_nanosleep_time64"],
)?;
Self::weak_symbol_extern_statics(ecx, &["getrandom", "gettid", "statx"])?;
}

View File

@@ -10,13 +10,13 @@
//! themselves having support libraries. All data over the TCP sockets is in a
//! basically custom format suiting our needs.
#[cfg(all(not(windows), not(target_os = "motor")))]
#[cfg(not(any(windows, target_os = "motor", target_os = "uefi")))]
use std::fs::Permissions;
use std::fs::{self, File};
use std::io::prelude::*;
use std::io::{self, BufReader};
use std::net::{SocketAddr, TcpListener, TcpStream};
#[cfg(all(not(windows), not(target_os = "motor")))]
#[cfg(not(any(windows, target_os = "motor", target_os = "uefi")))]
use std::os::unix::prelude::*;
use std::path::{Path, PathBuf};
use std::process::{Command, ExitStatus, Stdio};
@@ -325,7 +325,7 @@ fn handle_run(socket: TcpStream, work: &Path, tmp: &Path, lock: &Mutex<()>, conf
]));
}
#[cfg(all(not(windows), not(target_os = "motor")))]
#[cfg(not(any(windows, target_os = "motor", target_os = "uefi")))]
fn get_status_code(status: &ExitStatus) -> (u8, i32) {
match status.code() {
Some(n) => (0, n),
@@ -333,7 +333,7 @@ fn get_status_code(status: &ExitStatus) -> (u8, i32) {
}
}
#[cfg(any(windows, target_os = "motor"))]
#[cfg(any(windows, target_os = "motor", target_os = "uefi"))]
fn get_status_code(status: &ExitStatus) -> (u8, i32) {
(0, status.code().unwrap())
}
@@ -359,11 +359,11 @@ fn recv<B: BufRead>(dir: &Path, io: &mut B) -> PathBuf {
dst
}
#[cfg(all(not(windows), not(target_os = "motor")))]
#[cfg(not(any(windows, target_os = "motor", target_os = "uefi")))]
fn set_permissions(path: &Path) {
t!(fs::set_permissions(&path, Permissions::from_mode(0o755)));
}
#[cfg(any(windows, target_os = "motor"))]
#[cfg(any(windows, target_os = "motor", target_os = "uefi"))]
fn set_permissions(_path: &Path) {}
fn my_copy(src: &mut dyn Read, which: u8, dst: &Mutex<dyn Write>) {

View File

@@ -1,5 +1,6 @@
// MIPS assembler uses the label prefix `$anon.` for local anonymous variables
// other architectures (including ARM and x86-64) use the prefix `.Lanon.`
// Hexagon uses `.string` instead of `.asciz` for null-terminated strings
//@ only-linux
//@ assembly-output: emit-asm
//@ compile-flags: --crate-type=lib -Copt-level=3 -Cllvm-args=-enable-global-merge=0
@@ -9,13 +10,13 @@ use std::ffi::CStr;
// CHECK: .section .rodata.str1.{{[12]}},"aMS"
// CHECK: {{(\.L|\$)}}anon.{{.+}}:
// CHECK-NEXT: .asciz "foo"
// CHECK-NEXT: .{{asciz|string}} "foo"
#[unsafe(no_mangle)]
static CSTR: &[u8; 4] = b"foo\0";
// CHECK-NOT: .section
// CHECK: {{(\.L|\$)}}anon.{{.+}}:
// CHECK-NEXT: .asciz "bar"
// CHECK-NEXT: .{{asciz|string}} "bar"
#[unsafe(no_mangle)]
pub fn cstr() -> &'static CStr {
c"bar"
@@ -23,7 +24,7 @@ pub fn cstr() -> &'static CStr {
// CHECK-NOT: .section
// CHECK: {{(\.L|\$)}}anon.{{.+}}:
// CHECK-NEXT: .asciz "baz"
// CHECK-NEXT: .{{asciz|string}} "baz"
#[unsafe(no_mangle)]
pub fn manual_cstr() -> &'static str {
"baz\0"

View File

@@ -139,6 +139,12 @@
//@ revisions: armv5te_unknown_linux_uclibceabi
//@ [armv5te_unknown_linux_uclibceabi] compile-flags: --target armv5te-unknown-linux-uclibceabi
//@ [armv5te_unknown_linux_uclibceabi] needs-llvm-components: arm
//@ revisions: armv6_none_eabi
//@ [armv6_none_eabi] compile-flags: --target armv6-none-eabi
//@ [armv6_none_eabi] needs-llvm-components: arm
//@ revisions: armv6_none_eabihf
//@ [armv6_none_eabihf] compile-flags: --target armv6-none-eabihf
//@ [armv6_none_eabihf] needs-llvm-components: arm
//@ revisions: armv6_unknown_freebsd
//@ [armv6_unknown_freebsd] compile-flags: --target armv6-unknown-freebsd
//@ [armv6_unknown_freebsd] needs-llvm-components: arm
@@ -559,6 +565,9 @@
//@ revisions: thumbv5te_none_eabi
//@ [thumbv5te_none_eabi] compile-flags: --target thumbv5te-none-eabi
//@ [thumbv5te_none_eabi] needs-llvm-components: arm
//@ revisions: thumbv6_none_eabi
//@ [thumbv6_none_eabi] compile-flags: --target thumbv6-none-eabi
//@ [thumbv6_none_eabi] needs-llvm-components: arm
//@ revisions: thumbv7a_none_eabi
//@ [thumbv7a_none_eabi] compile-flags: --target thumbv7a-none-eabi
//@ [thumbv7a_none_eabi] needs-llvm-components: arm

View File

@@ -0,0 +1,33 @@
//@ compile-flags: -Copt-level=3
#![crate_type = "lib"]
#![no_std]
#![feature(repr_simd, core_intrinsics)]
use core::intrinsics::simd::simd_splat;
#[path = "../../auxiliary/minisimd.rs"]
mod minisimd;
use minisimd::*;
// Test that `simd_splat` produces the canonical LLVM splat sequence.
#[no_mangle]
unsafe fn int(x: u16) -> u16x2 {
// CHECK-LABEL: int
// CHECK: start:
// CHECK-NEXT: %0 = insertelement <2 x i16> poison, i16 %x, i64 0
// CHECK-NEXT: %1 = shufflevector <2 x i16> %0, <2 x i16> poison, <2 x i32> zeroinitializer
// CHECK-NEXT: store
// CHECK-NEXT: ret
simd_splat(x)
}
#[no_mangle]
unsafe fn float(x: f32) -> f32x4 {
// CHECK-LABEL: float
// CHECK: start:
// CHECK-NEXT: %0 = insertelement <4 x float> poison, float %x, i64 0
// CHECK-NEXT: %1 = shufflevector <4 x float> %0, <4 x float> poison, <4 x i32> zeroinitializer
// CHECK-NEXT: store
// CHECK-NEXT: ret
simd_splat(x)
}

View File

@@ -0,0 +1,48 @@
//@ run-pass
#![feature(repr_simd, core_intrinsics)]
#[path = "../../../auxiliary/minisimd.rs"]
mod minisimd;
use minisimd::*;
use std::intrinsics::simd::simd_splat;
fn main() {
unsafe {
let x: Simd<u32, 1> = simd_splat(123u32);
let y: Simd<u32, 1> = const { simd_splat(123u32) };
assert_eq!(x.into_array(), [123; 1]);
assert_eq!(x.into_array(), y.into_array());
let x: u16x2 = simd_splat(42u16);
let y: u16x2 = const { simd_splat(42u16) };
assert_eq!(x.into_array(), [42; 2]);
assert_eq!(x.into_array(), y.into_array());
let x: u128x4 = simd_splat(42u128);
let y: u128x4 = const { simd_splat(42u128) };
assert_eq!(x.into_array(), [42; 4]);
assert_eq!(x.into_array(), y.into_array());
let x: i32x4 = simd_splat(-7i32);
let y: i32x4 = const { simd_splat(-7i32) };
assert_eq!(x.into_array(), [-7; 4]);
assert_eq!(x.into_array(), y.into_array());
let x: f32x4 = simd_splat(42.0f32);
let y: f32x4 = const { simd_splat(42.0f32) };
assert_eq!(x.into_array(), [42.0; 4]);
assert_eq!(x.into_array(), y.into_array());
let x: f64x2 = simd_splat(42.0f64);
let y: f64x2 = const { simd_splat(42.0f64) };
assert_eq!(x.into_array(), [42.0; 2]);
assert_eq!(x.into_array(), y.into_array());
static ZERO: u8 = 0u8;
let x: Simd<*const u8, 2> = simd_splat(&raw const ZERO);
let y: Simd<*const u8, 2> = const { simd_splat(&raw const ZERO) };
assert_eq!(x.into_array(), [&raw const ZERO; 2]);
assert_eq!(x.into_array(), y.into_array());
}
}