Skip to content

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

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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