-
Couldn't load subscription status.
- Fork 13.9k
Description
Code sample:
#[repr(transparent)]
pub struct K {
b: usize
}
pub fn foo(k: K) {
let x = unsafe { std::mem::transmute::<_, *mut i8>(k) };
std::hint::black_box(unsafe { *x });
}Expected to generate asm like this(for target aarch64-apple-darwin):
__ZN7example3foo17hbc2dffde7832bc1dE:
sub sp, sp, #16
ldrb w8, [x0]
strb w8, [sp, #15]
add x8, sp, #15
add sp, sp, #16
retHowever, the generated asm looks like this:
__ZN7example3foo17hbc2dffde7832bc1dE:
brk #0x1Godbolt: https://rust.godbolt.org/z/s5PY4TPME
I did some research, and found that Rust emits such LLVM IR for the transmute:
%x = getelementptr i8, ptr null, i64 %k
%dummy = load i8, ptr %x, align 1
However, load (gep ptr null) is assumed as unreachable in LLVM's InstCombine pass, thus brk is generated.
The transmute was orignally lowered as inttoptr rather than getelementptr i8 ptr null.., which is legal and the result assembly won't crash.
I performed a bisection and discovered that the codegen change was introduced by#121282. I suspect that this PR was intended to address integer-to-pointer conversions, but it inadvertently affects the transmute of integer-sized-struct-to-pointer conversions.
As far as I can tell, integer-sized-struct-to-pointer conversions are not UB 🤔 : https://doc.rust-lang.org/nightly/std/intrinsics/fn.transmute.html.