Closed
Description
#![feature(asm)]
// Isomorphic to Option<usize>.
#[derive(Copy)]
enum Foo {
Yes(usize),
No
}
// All these functions are necessary to trigger the bug.
fn swap(x: &mut Foo, y: &mut Foo) {
let tmp = *x;
*x = *y;
*y = tmp;
}
fn replace(x: &mut Foo, mut y: Foo) -> Foo {
swap(x, &mut y);
y
}
fn take(x: &mut Foo) -> Foo {
static NO_FOO: Foo = Foo::No;
replace(x, NO_FOO)
}
fn take2(x: &mut Foo) -> Foo {
take(x)
}
fn main() {
let mut iter = Foo::Yes(5);
while let Foo::Yes(_) = take2(&mut iter) {
unsafe {
// Just to keep the loop alive.
asm!(""::::"volatile");
}
}
}
This happens only after the recent LLVM upgrade. The culprit seems to be half of NO_FOO
:
@NO_FOO = internal constant { i64, [8 x i8] } { i64 1, [8 x i8] undef }
; ...
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %3, i8* bitcast ({ i64, [8 x i8] }* @NO_FOO to i8*), i64 16, i32 8, i1 false)
Changing the memcpy
call to copy only 8 bytes instead of 16 (to not touch the undef
portion) removes the infinite loop.
cc @dotdash @Aatch