Skip to content

Rollup of 5 pull requests #128785

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 13 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/tools/compiletest/src/command-list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
"only-32bit",
"only-64bit",
"only-aarch64",
"only-aarch64-unknown-linux-gnu",
"only-apple",
"only-arm",
"only-avr",
Expand Down
14 changes: 14 additions & 0 deletions src/tools/run-make-support/src/assertion_helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,20 @@ pub fn assert_not_contains_regex<H: AsRef<str>, N: AsRef<str>>(haystack: H, need
}
}

/// Assert that `haystack` contains `needle` a `count` number of times.
#[track_caller]
pub fn assert_count_is<H: AsRef<str>, N: AsRef<str>>(count: usize, haystack: H, needle: N) {
let haystack = haystack.as_ref();
let needle = needle.as_ref();
if count != haystack.matches(needle).count() {
eprintln!("=== HAYSTACK ===");
eprintln!("{}", haystack);
eprintln!("=== NEEDLE ===");
eprintln!("{}", needle);
panic!("needle did not appear {count} times in haystack");
}
}

/// Assert that all files in `dir1` exist and have the same content in `dir2`
pub fn assert_dirs_are_equal(dir1: impl AsRef<Path>, dir2: impl AsRef<Path>) {
let dir2 = dir2.as_ref();
Expand Down
2 changes: 1 addition & 1 deletion src/tools/run-make-support/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ pub use path_helpers::{
pub use scoped_run::{run_in_tmpdir, test_while_readonly};

pub use assertion_helpers::{
assert_contains, assert_contains_regex, assert_dirs_are_equal, assert_equals,
assert_contains, assert_contains_regex, assert_count_is, assert_dirs_are_equal, assert_equals,
assert_not_contains, assert_not_contains_regex,
};

Expand Down
4 changes: 0 additions & 4 deletions src/tools/tidy/src/allowed_run_make_makefiles.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,7 @@ run-make/libtest-json/Makefile
run-make/libtest-junit/Makefile
run-make/libtest-thread-limit/Makefile
run-make/macos-deployment-target/Makefile
run-make/min-global-align/Makefile
run-make/native-link-modifier-bundle/Makefile
run-make/no-alloc-shim/Makefile
run-make/pdb-buildinfo-cl-cmd/Makefile
run-make/pgo-gen-lto/Makefile
run-make/pgo-indirect-call-promotion/Makefile
Expand All @@ -24,10 +22,8 @@ run-make/reproducible-build/Makefile
run-make/rlib-format-packed-bundled-libs/Makefile
run-make/simd-ffi/Makefile
run-make/split-debuginfo/Makefile
run-make/staticlib-dylib-linkage/Makefile
run-make/symbol-mangling-hashed/Makefile
run-make/sysroot-crates-are-unstable/Makefile
run-make/thumb-none-cortex-m/Makefile
run-make/thumb-none-qemu/Makefile
run-make/translation/Makefile
run-make/x86_64-fortanix-unknown-sgx-lvi/Makefile
20 changes: 20 additions & 0 deletions tests/codegen/issues/issue-107681-unwrap_unchecked.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//@ compile-flags: -O
//@ min-llvm-version: 19

// Test for #107681.
// Make sure we don't create `br` or `select` instructions.

#![crate_type = "lib"]

use std::iter::Copied;
use std::slice::Iter;

#[no_mangle]
pub unsafe fn foo(x: &mut Copied<Iter<'_, u32>>) -> u32 {
// CHECK-LABEL: @foo(
// CHECK-NOT: br
// CHECK-NOT: select
// CHECK: [[RET:%.*]] = load i32, ptr
// CHECK-NEXT: ret i32 [[RET]]
x.next().unwrap_unchecked()
}
20 changes: 20 additions & 0 deletions tests/codegen/issues/issue-118306.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//@ compile-flags: -O -Zno-jump-tables
//@ min-llvm-version: 19

// Test for #118306.
// Ensure that the default branch is optimized to be unreachable.

#![crate_type = "lib"]

#[no_mangle]
pub fn foo(input: u64) -> u64 {
// CHECK-LABEL: @foo(
// CHECK: switch {{.*}}, label %[[UNREACHABLE:.*]] [
// CHECK: [[UNREACHABLE]]:
// CHECK-NEXT: unreachable
match input % 4 {
1 | 2 => 1,
3 => 2,
_ => 0,
}
}
23 changes: 23 additions & 0 deletions tests/codegen/issues/issue-126585.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//@ compile-flags: -Copt-level=s
//@ min-llvm-version: 19

// Test for #126585.
// Ensure that this IR doesn't have extra undef phi input, which also guarantees that this asm
// doesn't have subsequent labels and unnecessary `jmp` instructions.

#![crate_type = "lib"]

#[no_mangle]
fn checked_div_round(a: u64, b: u64) -> Option<u64> {
// CHECK-LABEL: @checked_div_round
// CHECK: phi
// CHECK-NOT: undef
// CHECK: phi
// CHECK-NOT: undef
match b {
0 => None,
1 => Some(a),
// `a / b` is computable and `(a % b) * 2` can not overflow since `b >= 2`.
b => Some(a / b + if (a % b) * 2 >= b { 1 } else { 0 }),
}
}
22 changes: 0 additions & 22 deletions tests/run-make/min-global-align/Makefile

This file was deleted.

27 changes: 27 additions & 0 deletions tests/run-make/min-global-align/rmake.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// This test checks that global variables respect the target minimum alignment.
// The three bools `STATIC_BOOL`, `STATIC_MUT_BOOL`, and `CONST_BOOL` all have
// type-alignment of 1, but some targets require greater global alignment.
// See https://github.com/rust-lang/rust/pull/44440

//@ only-linux
// Reason: this test is target-independent, considering compilation is targeted
// towards linux architectures only.

use run_make_support::{assert_count_is, llvm_components_contain, rfs, rustc};

fn main() {
// Most targets are happy with default alignment -- take i686 for example.
if llvm_components_contain("x86") {
rustc().target("i686-unknown-linux-gnu").emit("llvm-ir").input("min_global_align.rs").run();
assert_count_is(3, rfs::read_to_string("min_global_align.ll"), "align 1");
}
// SystemZ requires even alignment for PC-relative addressing.
if llvm_components_contain("systemz") {
rustc()
.target("s390x-unknown-linux-gnu")
.emit("llvm-ir")
.input("min_global_align.rs")
.run();
assert_count_is(3, rfs::read_to_string("min_global_align.ll"), "align 2");
}
}
43 changes: 43 additions & 0 deletions tests/run-make/mte-ffi/bar.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#ifndef __BAR_H
#define __BAR_H

#include <sys/mman.h>
#include <sys/auxv.h>
#include <sys/prctl.h>
#include <unistd.h>
#include <stdio.h>

// Set the allocation tag on the destination address using the STG instruction.
#define set_tag(tagged_addr) do { \
asm volatile("stg %0, [%0]" : : "r" (tagged_addr) : "memory"); \
} while (0)

int mte_enabled() {
return (getauxval(AT_HWCAP2)) & HWCAP2_MTE;
}

void *alloc_page() {
// Enable MTE with synchronous checking
if (prctl(PR_SET_TAGGED_ADDR_CTRL,
PR_TAGGED_ADDR_ENABLE | PR_MTE_TCF_SYNC | (0xfffe << PR_MTE_TAG_SHIFT),
0, 0, 0))
{
perror("prctl() failed");
}

// Using `mmap` allows us to ensure that, on systems which support MTE, the allocated
// memory is 16-byte aligned for MTE.
// This also allows us to explicitly specify whether the region should be protected by
// MTE or not.
if (mte_enabled()) {
void *ptr = mmap(NULL, sysconf(_SC_PAGESIZE),
PROT_READ | PROT_WRITE | PROT_MTE, MAP_PRIVATE | MAP_ANONYMOUS,
-1, 0);
} else {
void *ptr = mmap(NULL, sysconf(_SC_PAGESIZE),
PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS,
-1, 0);
}
}

#endif // __BAR_H
44 changes: 44 additions & 0 deletions tests/run-make/mte-ffi/bar_float.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "bar.h"

extern void foo(char*);

void bar(char *ptr) {
if (((uintptr_t)ptr >> 56) != 0x1f) {
fprintf(stderr, "Top byte corrupted on Rust -> C FFI boundary!\n");
exit(1);
}
}

int main(void)
{
float *ptr = alloc_page();
if (ptr == MAP_FAILED)
{
perror("mmap() failed");
return EXIT_FAILURE;
}

// Store an arbitrary tag in bits 56-59 of the pointer (where an MTE tag may be),
// and a different value in the ignored top 4 bits.
ptr = (float *)((uintptr_t)ptr | 0x1fl << 56);

if (mte_enabled()) {
set_tag(ptr);
}

ptr[0] = 2.0f;
ptr[1] = 1.5f;

foo(ptr); // should change the contents of the page and call `bar`

if (ptr[0] != 0.5f || ptr[1] != 0.2f) {
fprintf(stderr, "invalid data in memory; expected '0.5 0.2', got '%f %f'\n",
ptr[0], ptr[1]);
return EXIT_FAILURE;
}

return 0;
}
39 changes: 39 additions & 0 deletions tests/run-make/mte-ffi/bar_function.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "bar.h"

typedef void (*fp)(int (*)());

extern void foo(fp);

void bar(int (*ptr)()) {
if (((uintptr_t)ptr >> 56) != 0x2f) {
fprintf(stderr, "Top byte corrupted on Rust -> C FFI boundary!\n");
exit(1);
}

int r = (*ptr)();
if (r != 32) {
fprintf(stderr, "invalid return value; expected 32, got '%d'\n", r);
exit(1);
}
}

int main(void)
{
fp ptr = alloc_page();
if (ptr == MAP_FAILED)
{
perror("mmap() failed");
return EXIT_FAILURE;
}

// Store an arbitrary tag in bits 56-59 of the pointer (where an MTE tag may be),
// and a different value in the ignored top 4 bits.
ptr = (fp)((uintptr_t)&bar | 0x1fl << 56);

foo(ptr);

return 0;
}
47 changes: 47 additions & 0 deletions tests/run-make/mte-ffi/bar_int.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "bar.h"

extern void foo(unsigned int *);

void bar(char *ptr) {
if (((uintptr_t)ptr >> 56) != 0x1f) {
fprintf(stderr, "Top byte corrupted on Rust -> C FFI boundary!\n");
exit(1);
}
}

int main(void)
{
// Construct a pointer with an arbitrary tag in bits 56-59, simulating an MTE tag.
// It's only necessary that the tag is preserved across FFI bounds for this test.
unsigned int *ptr;

ptr = alloc_page();
if (ptr == MAP_FAILED)
{
perror("mmap() failed");
return EXIT_FAILURE;
}

// Store an arbitrary tag in bits 56-59 of the pointer (where an MTE tag may be),
// and a different value in the ignored top 4 bits.
ptr = (unsigned int *)((uintptr_t)ptr | 0x1fl << 56);

if (mte_enabled()) {
set_tag(ptr);
}

ptr[0] = 61;
ptr[1] = 62;

foo(ptr); // should change the contents of the page to start with 0x63 0x64 and call `bar`

if (ptr[0] != 0x63 || ptr[1] != 0x64) {
fprintf(stderr, "invalid data in memory; expected '63 64', got '%d %d'\n", ptr[0], ptr[1]);
return EXIT_FAILURE;
}

return 0;
}
Loading
Loading