diff options
| author | Scott McMurray <scottmcm@users.noreply.github.com> | 2023-08-02 12:45:52 -0700 |
|---|---|---|
| committer | Scott McMurray <scottmcm@users.noreply.github.com> | 2023-08-06 15:47:40 -0700 |
| commit | 502af03445f045dade14f14e754803f02c2c5e24 (patch) | |
| tree | fbeb208e1c6d7df46431f1412404e8b48dfd5349 /tests | |
| parent | 85fbb571497d13cfb828de9b0d3e78656b9203c1 (diff) | |
| download | rust-502af03445f045dade14f14e754803f02c2c5e24.tar.gz rust-502af03445f045dade14f14e754803f02c2c5e24.zip | |
Add a new `compare_bytes` intrinsic instead of calling `memcmp` directly
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/codegen/intrinsics/compare_bytes.rs | 34 | ||||
| -rw-r--r-- | tests/ui/consts/const-compare-bytes-ub.rs | 41 | ||||
| -rw-r--r-- | tests/ui/consts/const-compare-bytes-ub.stderr | 54 | ||||
| -rw-r--r-- | tests/ui/consts/const-compare-bytes.rs | 27 | ||||
| -rw-r--r-- | tests/ui/proc-macro/meta-macro-hygiene.stdout | 2 | ||||
| -rw-r--r-- | tests/ui/proc-macro/nonterminal-token-hygiene.stdout | 2 |
6 files changed, 158 insertions, 2 deletions
diff --git a/tests/codegen/intrinsics/compare_bytes.rs b/tests/codegen/intrinsics/compare_bytes.rs new file mode 100644 index 00000000000..e69224d818c --- /dev/null +++ b/tests/codegen/intrinsics/compare_bytes.rs @@ -0,0 +1,34 @@ +// revisions: INT32 INT16 +// compile-flags: -O +// [INT32] ignore-16bit +// [INT16] only-16bit + +#![crate_type = "lib"] +#![feature(core_intrinsics)] + +use std::intrinsics::compare_bytes; + +#[no_mangle] +// CHECK-LABEL: @bytes_cmp( +pub unsafe fn bytes_cmp(a: *const u8, b: *const u8, n: usize) -> i32 { + // INT32: %[[TEMP:.+]] = tail call i32 @memcmp(ptr %a, ptr %b, {{i32|i64}} %n) + // INT32-NOT: sext + // INT32: ret i32 %[[TEMP]] + + // INT16: %[[TEMP1:.+]] = tail call i16 @memcmp(ptr %a, ptr %b, i16 %n) + // INT16: %[[TEMP2:.+]] = sext i16 %[[TEMP1]] to i32 + // INT16: ret i32 %[[TEMP2]] + compare_bytes(a, b, n) +} + +// Ensure that, even though there's an `sext` emitted by the intrinsic, +// that doesn't end up pessiming checks against zero. +#[no_mangle] +// CHECK-LABEL: @bytes_eq( +pub unsafe fn bytes_eq(a: *const u8, b: *const u8, n: usize) -> bool { + // CHECK: call {{.+}} @{{bcmp|memcmp}}(ptr %a, ptr %b, {{i16|i32|i64}} %n) + // CHECK-NOT: sext + // INT32: icmp eq i32 + // INT16: icmp eq i16 + compare_bytes(a, b, n) == 0_i32 +} diff --git a/tests/ui/consts/const-compare-bytes-ub.rs b/tests/ui/consts/const-compare-bytes-ub.rs new file mode 100644 index 00000000000..2b4062fd22b --- /dev/null +++ b/tests/ui/consts/const-compare-bytes-ub.rs @@ -0,0 +1,41 @@ +// check-fail + +#![feature(core_intrinsics)] +#![feature(const_intrinsic_compare_bytes)] +use std::intrinsics::compare_bytes; +use std::mem::MaybeUninit; + +fn main() { + const LHS_NULL: i32 = unsafe { + compare_bytes(0 as *const u8, 2 as *const u8, 0) + //~^ ERROR evaluation of constant value failed + }; + const RHS_NULL: i32 = unsafe { + compare_bytes(1 as *const u8, 0 as *const u8, 0) + //~^ ERROR evaluation of constant value failed + }; + const DANGLING_PTR_NON_ZERO_LENGTH: i32 = unsafe { + compare_bytes(1 as *const u8, 2 as *const u8, 1) + //~^ ERROR evaluation of constant value failed + }; + const LHS_OUT_OF_BOUNDS: i32 = unsafe { + compare_bytes([1, 2, 3].as_ptr(), [1, 2, 3, 4].as_ptr(), 4) + //~^ ERROR evaluation of constant value failed + }; + const RHS_OUT_OF_BOUNDS: i32 = unsafe { + compare_bytes([1, 2, 3, 4].as_ptr(), [1, 2, 3].as_ptr(), 4) + //~^ ERROR evaluation of constant value failed + }; + const LHS_UNINIT: i32 = unsafe { + compare_bytes(MaybeUninit::uninit().as_ptr(), [1].as_ptr(), 1) + //~^ ERROR evaluation of constant value failed + }; + const RHS_UNINIT: i32 = unsafe { + compare_bytes([1].as_ptr(), MaybeUninit::uninit().as_ptr(), 1) + //~^ ERROR evaluation of constant value failed + }; + const WITH_PROVENANCE: i32 = unsafe { + compare_bytes([&1].as_ptr().cast(), [&2].as_ptr().cast(), std::mem::size_of::<usize>()) + //~^ ERROR evaluation of constant value failed + }; +} diff --git a/tests/ui/consts/const-compare-bytes-ub.stderr b/tests/ui/consts/const-compare-bytes-ub.stderr new file mode 100644 index 00000000000..54fafded07b --- /dev/null +++ b/tests/ui/consts/const-compare-bytes-ub.stderr @@ -0,0 +1,54 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/const-compare-bytes-ub.rs:10:9 + | +LL | compare_bytes(0 as *const u8, 2 as *const u8, 0) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: null pointer is a dangling pointer (it has no provenance) + +error[E0080]: evaluation of constant value failed + --> $DIR/const-compare-bytes-ub.rs:14:9 + | +LL | compare_bytes(1 as *const u8, 0 as *const u8, 0) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: null pointer is a dangling pointer (it has no provenance) + +error[E0080]: evaluation of constant value failed + --> $DIR/const-compare-bytes-ub.rs:18:9 + | +LL | compare_bytes(1 as *const u8, 2 as *const u8, 1) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: 0x1[noalloc] is a dangling pointer (it has no provenance) + +error[E0080]: evaluation of constant value failed + --> $DIR/const-compare-bytes-ub.rs:22:9 + | +LL | compare_bytes([1, 2, 3].as_ptr(), [1, 2, 3, 4].as_ptr(), 4) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: alloc6 has size 3, so pointer to 4 bytes starting at offset 0 is out-of-bounds + +error[E0080]: evaluation of constant value failed + --> $DIR/const-compare-bytes-ub.rs:26:9 + | +LL | compare_bytes([1, 2, 3, 4].as_ptr(), [1, 2, 3].as_ptr(), 4) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: alloc13 has size 3, so pointer to 4 bytes starting at offset 0 is out-of-bounds + +error[E0080]: evaluation of constant value failed + --> $DIR/const-compare-bytes-ub.rs:30:9 + | +LL | compare_bytes(MaybeUninit::uninit().as_ptr(), [1].as_ptr(), 1) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reading memory at alloc17[0x0..0x1], but memory is uninitialized at [0x0..0x1], and this operation requires initialized memory + +error[E0080]: evaluation of constant value failed + --> $DIR/const-compare-bytes-ub.rs:34:9 + | +LL | compare_bytes([1].as_ptr(), MaybeUninit::uninit().as_ptr(), 1) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reading memory at alloc25[0x0..0x1], but memory is uninitialized at [0x0..0x1], and this operation requires initialized memory + +error[E0080]: evaluation of constant value failed + --> $DIR/const-compare-bytes-ub.rs:38:9 + | +LL | compare_bytes([&1].as_ptr().cast(), [&2].as_ptr().cast(), std::mem::size_of::<usize>()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-compare-bytes.rs b/tests/ui/consts/const-compare-bytes.rs new file mode 100644 index 00000000000..74e29f81386 --- /dev/null +++ b/tests/ui/consts/const-compare-bytes.rs @@ -0,0 +1,27 @@ +// run-pass + +#![feature(core_intrinsics)] +#![feature(const_intrinsic_compare_bytes)] +use std::intrinsics::compare_bytes; + +fn main() { + const A: i32 = unsafe { + compare_bytes(1 as *const u8, 2 as *const u8, 0) + }; + assert_eq!(A, 0); + + const B: i32 = unsafe { + compare_bytes([1, 2].as_ptr(), [1, 3].as_ptr(), 1) + }; + assert_eq!(B, 0); + + const C: i32 = unsafe { + compare_bytes([1, 2, 9].as_ptr(), [1, 3, 8].as_ptr(), 2) + }; + assert!(C < 0); + + const D: i32 = unsafe { + compare_bytes([1, 3, 8].as_ptr(), [1, 2, 9].as_ptr(), 2) + }; + assert!(D > 0); +} diff --git a/tests/ui/proc-macro/meta-macro-hygiene.stdout b/tests/ui/proc-macro/meta-macro-hygiene.stdout index e476a8024fd..ac65ba07512 100644 --- a/tests/ui/proc-macro/meta-macro-hygiene.stdout +++ b/tests/ui/proc-macro/meta-macro-hygiene.stdout @@ -18,7 +18,7 @@ Respanned: TokenStream [Ident { ident: "$crate", span: $DIR/auxiliary/make-macro use core /* 0#1 */::prelude /* 0#1 */::rust_2018 /* 0#1 */::*; #[macro_use /* 0#1 */] extern crate core /* 0#1 */; -extern crate compiler_builtins /* 444 */ as _ /* 0#1 */; +extern crate compiler_builtins /* 445 */ as _ /* 0#1 */; // Don't load unnecessary hygiene information from std extern crate std /* 0#0 */; diff --git a/tests/ui/proc-macro/nonterminal-token-hygiene.stdout b/tests/ui/proc-macro/nonterminal-token-hygiene.stdout index 23a21004238..4031eb98a38 100644 --- a/tests/ui/proc-macro/nonterminal-token-hygiene.stdout +++ b/tests/ui/proc-macro/nonterminal-token-hygiene.stdout @@ -39,7 +39,7 @@ PRINT-BANG INPUT (DEBUG): TokenStream [ use ::core /* 0#1 */::prelude /* 0#1 */::rust_2015 /* 0#1 */::*; #[macro_use /* 0#1 */] extern crate core /* 0#2 */; -extern crate compiler_builtins /* 444 */ as _ /* 0#2 */; +extern crate compiler_builtins /* 445 */ as _ /* 0#2 */; // Don't load unnecessary hygiene information from std extern crate std /* 0#0 */; |
