Skip to content

Commit

Permalink
Auto merge of rust-lang#128785 - matthiaskrgr:rollup-13chr4m, r=matth…
Browse files Browse the repository at this point in the history
…iaskrgr

Rollup of 5 pull requests

Successful merges:

 - rust-lang#128384 (Add tests to ensure MTE tags are preserved across FFI boundaries)
 - rust-lang#128407 (Migrate `min-global-align` and `no-alloc-shim` `run-make` tests to rmake)
 - rust-lang#128584 (Add a set of tests for LLVM 19)
 - rust-lang#128636 (migrate `thumb-none-cortex-m` to rmake)
 - rust-lang#128696 (Migrate `staticlib-dylib-linkage` `run-make` test to rmake)

Failed merges:

 - rust-lang#128639 (migrate `thumb-none-qemu` to rmake)

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Aug 7, 2024
2 parents 8d00669 + acef3a1 commit d6092d0
Show file tree
Hide file tree
Showing 25 changed files with 583 additions and 110 deletions.
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,19 +13,15 @@ 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-indirect-call-promotion/Makefile
run-make/remap-path-prefix-dwarf/Makefile
run-make/reproducible-build/Makefile
run-make/rlib-format-packed-bundled-libs/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

0 comments on commit d6092d0

Please sign in to comment.