Skip to content

-C opt-level=z produces invalid code on i686-pc-windows-msvc #45034

Closed
@neivv

Description

@neivv
fn main() {
    let _vec: Vec<u8> = Vec::new();
    std::fs::create_dir(std::path::Path::new("a")).unwrap();
}

Will crash when compiled with rustc -C opt-level=z main.rs.

> rustup run nightly-i686-pc-windows-msvc rustc --version -v
rustc 1.22.0-nightly (4502e2aa9 2017-10-03)
binary: rustc
commit-hash: 4502e2aa9c28d8caa610fc1815fd9c5b5a16e91c
commit-date: 2017-10-03
host: i686-pc-windows-msvc
release: 1.22.0-nightly
LLVM version: 4.0

The asm for main is

__ZN4main4main17h0bca12b325d77113E:
Lfunc_begin2:
	pushl	%ebp
	movl	%esp, %ebp
	pushl	%ebx
	pushl	%edi
	pushl	%esi
	andl	$-8, %esp
	subl	$72, %esp
	movl	%esp, %esi
	movl	%ebp, 48(%esi)
	leal	56(%esi), %eax
	movl	%esp, -4(%eax)
	orl	$-1, 8(%eax)
	movl	$___ehhandler$_ZN4main4main17h0bca12b325d77113E, 4(%eax)
	movl	%fs:0, %ecx
	movl	%ecx, (%eax)
	xorl	%ecx, %ecx
	movl	%eax, %fs:0
	andl	$0, 8(%eax)
	incl	%ecx
	movl	%ecx, 12(%esi)
	andl	$0, 16(%esi)
	andl	$0, 20(%esi)
	pushl	%ecx
	pushl	$_str.7
	calll	__ZN3std3ffi6os_str85_$LT$impl$u20$core..convert..AsRef$LT$std..ffi..os_str..OsStr$GT$$u20$for$u20$str$GT$6as_ref17h154d386d199535e3E
	popl	%ecx
	popl	%esi
	movl	%eax, 8(%esi)
	movl	%edx, 4(%esi)
	calll	__ZN3std2fs10DirBuilder3new17h2a2d998af5809e7bE
	movb	%al, 24(%esi)
	pushl	4(%esi)
	pushl	8(%esi)
	calll	__ZN79_$LT$std..path..Path$u20$as$u20$core..convert..AsRef$LT$std..path..Path$GT$$GT$6as_ref17hbd919da430f6c47cE
	popl	%ecx
	popl	%esi
	pushl	%edx
	pushl	%eax
	calll	__ZN79_$LT$std..path..Path$u20$as$u20$core..convert..AsRef$LT$std..path..Path$GT$$GT$6as_ref17hbd919da430f6c47cE
	popl	%ecx
	popl	%esi
	leal	24(%esi), %ecx
	leal	36(%esi), %edi
	pushl	%edx
	pushl	%eax
	pushl	%ecx
	pushl	%edi
	calll	__ZN3std2fs10DirBuilder7_create17h457ad352f6fc1a89E
	addl	$16, %esp
	cmpl	$0, 36(%esi)
	jne	LBB6_6
	leal	12(%esi), %ecx
	calll	__ZN4core3ptr13drop_in_place17h8b2fec8553a09995E
	movl	56(%esi), %eax
	movl	%eax, %fs:0
	leal	-12(%ebp), %esp
	popl	%esi
	popl	%edi
	popl	%ebx
	popl	%ebp
	retl
LBB6_6:
	movl	40(%esi), %eax
	movl	44(%esi), %edx
	leal	24(%esi), %ecx
	movl	%edx, 4(%ecx)
	movl	%eax, (%ecx)
	calll	__ZN4core6result13unwrap_failed17h0ccedc4bcd16baddE
	.def	 "?dtor$9@?0?_ZN4main4main17h0bca12b325d77113E@4HA";
	.scl	3;
	.type	32;
	.endef
"?dtor$9@?0?_ZN4main4main17h0bca12b325d77113E@4HA":
LBB6_9:
	pushl	%ebp
	subl	$16, %esp
	leal	-68(%ebp), %esi
	movl	48(%esi), %ebp
	leal	12(%esi), %ecx
	calll	__ZN4core3ptr13drop_in_place17h8b2fec8553a09995E
	addl	$16, %esp
	popl	%ebp
	retl

Specifically, the function uses esi to store a local variable, but after
__ZN79_$LT$std..path..Path$u20$as$u20$core..convert..AsRef$LT$std..path..Path$GT$$GT$6as_ref17hbd919da430f6c47cE
one of the function arguments are popped from stack with popl %esi..

When using -C panic=abort, or i686-pc-windows-gnu, or removing the _vec, the code compiles correctly (uses only popl %ecx), so the cause may be related to stack unwinding?

The issue also doesn't occur with -C opt-level=s, which uses one byte larger addl $8, %esp instead of two pops.

Not sure if this happens on x86-64, at least the example works fine as the calling convention won't have to use stack there.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.C-bugCategory: This is a bug.P-highHigh priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions