Wed Jun 06 19:35:56 2012: Request 77677 was acted upon. Transaction: Ticket created by bulk88. Queue: Win32-API Subject: x64 asm is broken for ::API, >4 param crash Broken in: 0.68 Severity: Normal Owner: Nobody Requestors: bul...@hotmail.com Status: new Ticket <URL: https://rt.cpan.org/Ticket/Display.html?id=77677 >
If there are over 4 parameters on x64 with GCC, there is a crash. Remember every function on x64 has 4 parameters without exception. RSI and R10 is filled with garbage with the 2 POPs at the end. The stack pusher loop is broken. RSI in Call_asm is the retval struct pointer on -O2 (strawberry perl's default). On -O0 it doesn't crash, IDK and don't care why. ________________________ .globl Call_x64_real Call_x64_real: pushq %rbp movq %rsp,%rbp subq $32,%rsp # keep space for 4 64bit params ADD 32 to RSP A FIXED AMOUNT # Store register parameters movq %rcx,16(%rbp) # ApiFunction movq %rdx,24(%rbp) # int_registers movq %r8,32(%rbp) # float_registers movq %r9,40(%rbp) # stack # Save regs we are gonna use pushq %rsi ADD 8 to RSP A FIXED AMOUNT pushq %r10 ADD 8 to RSP A FIXED AMOUNT # Load up integer registers first... movq 24(%rbp),%rax # rax = int_registers movq (%rax),%rcx movq 8(%rax),%rdx movq 16(%rax),%r8 movq 24(%rax),%r9 # Now floating-point registers movq 32(%rbp),%rax # rax = float_registers movsd (%rax),%xmm0 movsd 8(%rax),%xmm1 movsd 16(%rax),%xmm2 movsd 24(%rax),%xmm3 # Now the stack movq 40(%rbp),%rsi # rsi = stack movq 48(%rbp),%rax # rax = nstack NSTACK IS NUMBER OF STACK PARAMS FROM Call_asm required_stack = nparams > 4 ? nparams - 4 : 0; NSTACK IS required_stack IN THE CALLER Call_asm END COMMENT # Except not if there isn't any testq %rax,%rax je docall copystack: subq $1,%rax movq (%rsi,%rax,8),%r10 pushq %r10 ADD MANY 8s TO RSP THIS IS A LOOP VARIABLE AMOUNT testq %rax,%rax jne copystack docall: # And call movq 16(%rbp),%r10 # r10 = ApiFunction subq $32,%rsp # Microsoft x64 calling convention - allocate 32 bytes of "shadow space" on the stack ADD 32 TO RSP, A FIXED AMOUNT callq *%r10 addq $32,%rsp # restore stack REMOVE 32 FROM RSP, A FIXED AMOUNT # Store return value movq 56(%rbp),%r10 # r10 = iret movq %rax,(%r10) movq 64(%rbp),%r10 # r10 = dret movsd %xmm0,(%r10) # Restore regs popq %r10 REMOVE 8 FROM RSP, A FIXED AMOUNT popq %rsi REMOVE 8 FROM RSP, A FIXED AMOUNT movq %rbp,%rsp popq %rbp retq ____________________________________________ This bug is in the public 0.68, and my personal API versions (0.69/0.70). Its only on x64 and on GCC Perl. I'll investigate whether the same bug is in MSVC x64 side.